作为程序员一定要保持良好的睡眠,才能好编程

高并发解决方案案例考察

发布时间:2017-12-05



    高并发和大流量解决方案考点:

        

        PHP如何解决网站大流程与高并发的问题


        高并发架构相关的概念

        高并发解决方案

        

        并发:在某个时间点有多少个访问同时到来。

                  QPS:每秒钟请求或访问的数量。指每秒响应请求数(HTTP请求)


        吞吐量:单位时间内处理的请求数


        响应时间:从请求发出到收到响应花费的时间。


        测试工具: ab  wrk  http_load 等


        ab是apache的一款工具      观察使用  top  命令来查看的。

       


        如果QPS 50 那么此站点属于小型网站


        w34.jpg

            w35.jpg

w36.jpg


    流量优化:

        防盗链处理:

        什么是盗链?

            盗链是指在自己的页面上展示一些并不在自己服务器上的内容。

        

        什么是防盗链

            就是通过一些技术手段,让其他访问的url地址,不能正确的显示这个内容。


        工作原理:

            通过referer 或签名,网站可以检测到目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。

            一旦检测到来源不是本站即进行阻止或者返回指定的页面。

            

        


        

        Referer 请求目标文件的来源 是哪里?    


        那么我们通过nginx 来进行一些解读:

        

        1、通过referer

                nginx模块: nginx_http_referer_module 用于阻挡来源非法的域名请求


            nginx指令 valid_referers 全局变量 $invalid_referer   可以使用这个变量,这个配置 放在nginx的配置文件中

            valid_referers none|blocked|server_names|string...


                referers none 来源为空的情况

                referers blocked  referer 来源头部不为空,但里面的值被代理或防火墙删除了,这些值都不以http://或者https://开头   

                server_names

                        

location ~.*\.(gif|jpg|png|flv|swf|rar|zip)${                    
    valid_referers none blocked xiaosong.com *.xiaosongit.com;
    if($invalid_referer){  //如果为真,返回403 就可以了。                     
            #return 403;
            rewrite ^/ http://www.xiaosongit.com/403.jpg;
    }
}


        这是配置文件,这样就会显示  不允许显示此图。

        

        上图可以通过伪装referer 来进行访问。



        再次看看签名是怎么做的?



        2、通过签名

        httpAccessKeyModule  实现nginx防盗链   accesskey on|off


 

                        

location ~.*\.(gif|jpg|png|flv|swf|rar|zip)${                    
       accesskey on;

        accesskey_hashmethod md5;

        accesskey_arg "sign";  #参数的键名 可以随便起名

        accesskey_signature "xiaosong$remote_addr";

}


$sign=md5('xiaosong'.$_SERVER['REMOTE_ADDR']);

echo '<img src="image/logo.jpg?sign='.$sign.'">';

            




        前段优化:

            减少http请求  合并css文件   合并js文件

             添加异步请求:按需请求,需要加载的时候,去服务器请求加载数据。


        启用浏览器缓存和文件压缩

        


            本地缓存

                如果本地还能使用,那么就不会去请求浏览器,这样的话,请求最快

        

                             

                expires 服务器时间

                expires 客户端时间


                浏览器与服务器的时间无法保持一致,如果时间差距大,就会影响缓存。

                


                Cache-Control    针对expires返回的是一个时间


                no-store 禁止浏览器缓存响应

                no-cache 不允许直接使用本地缓存,先发起请求和服务器协商

                max-age=3600 告知浏览器该响应本地缓存有效的最长期限,以秒为单位

                                           就是缓存1个小时

                

                缓存优先级

                pragma>Cache-Control>Expires

                1.jpg

                


        协商缓存:

        相关header

            Last-modified:通知浏览器资源最后的修改时间,如果没有修改的话就直接返回304 让其直接只用本地缓存。

            if-modified-since:把Last-modified这个时间带服务器并做检测,如果有变化,就重新缓存,如果没有变化的话就是用本地缓存。

            

            ETAG 文件指纹标识符  如果文件内容修改、指纹就换改变

            

            都是判断文件是否发生了修改



        适合缓存的内容:

                不变的图像,如果 logo 图标

                css、js

                下载文件

        适合使用协商缓存:

            html文件、经常更换的图片、或js、css

        


        不建议缓存的内容:用户、api 等


        2.jpg

                    

        3.jpg



        本地缓存配置  expires 指令  过期时间。

            如果 expires为负值 那么就等于  Cache-Control :no-Cache
            

            4.jpg

            

            看看 expires 的过期时间  是如何设置的,h代表小时   d 代表天数  

            


            在nginx中开启 expires 来设置一下缓存。


            5.jpg

            

            http://tool.css-js.com

            

            图片压缩:

            tinypng

            jpegMini

            ImageOptim

            这是三个网站,可以压缩图片



            gZIp 是否开启压缩 nginx

            6.jpg

        7.jpg

            8.jpg

        9.jpg

    

        那么我怎么知道有没有开启压缩呢?

        10.jpg

  

       


            浏览器缓存




        

       CDN加速  解决带宽不够用

        内容分发网络

        CDN工作原理:

                11.jpg

    适用cdn

        12.jpg   

13.jpg


        什么是CDN?

        CDN的优势是什么?


        CDN的适用场景

        例如CSS/JS图片、大文件下载、直播网站

        

        CDN 真实服务器的一个镜像,cdn系统能够将连接、负载、以及用户距离找到距离近的最快的

        

        cdn跨运营商的网络加速、保证不同网络的用户都得到良好的访问质量

        

        CDN的实现:


            BAT等都有提供cdn服务

                阿里云、腾讯云  

            可以用LVS做4层负载均衡

            也可用Nginx、varnish、squid、apache做7层负载均衡和cache

      14.jpg

      



        建立独立图片服务器

        

        独立的必要性

        分担web服务器的IO负载,将耗费资源的图片服务分离出来,提高服务器性能和稳定性。

        减少带宽、减少cpu、增加硬盘转数,提高图片响应能力。

        青牛云

         

        独立域名

        同一域名浏览器的并发连接数有限制,突破浏览器连接数的限制。

        一个浏览器同一个域名一般是2-6个并发

        就会多了并发的请求。

        

        独立后的问题

       如何进行图片上传和图片同步

        

        NFS共享方式:

        利用FTP同步:

        青牛云的接口  :  


        


        动态语言静态化

    

        fpm 反向代理

   

        什么是动态语言静态化

        将现有PHP动态语言的逻辑静态生成静态html文件,让用户访问动态脚本重定向到静态html文件的过程

              


         为什么要静态化

         节省cpu资源、访问速度更快、不和mysql数据库打交道

       

        

          静态化的实现方式

           模板引擎 

            15.jpg           

                display() 方法 动态的生成一个静态文件。

                16.jpg


        利用ob系列函数:


            17.jpg                

            18.jpg


        下一次 直接判断 是否过期  是否存在,如果都为真  那么就直接返回这个模板文件


        filectime()


        19.jpg

            

        直接生成一个对应的html文件,下一次直接判断是否过期、是否存在,直接显示:


        20.jpg

   


        21.jpg

        通过这样的方式进行缓存文件的缓存。

 

          对实时性要求不高的页面:保存一个长期不变的页面            

        

        

        动态语言的并发处理


            什么是进程、线程、协程

                是计算机中的程序,进程是一个执行中过的程序。

                运行

                阻塞 

                

            线程是进程中的一个实体,是被系统独立调度和分派的基本单元,线程自己不拥有系统资源


            一个进程可以拥有多个线程。 线程是协程中一个


            在单个程序中同时运行多个线程完成不同的工作,成为多线程。

            每一个进程都有一个线程,如果进程只有一个线程,那就是进程本身了。

            

            线程是进程内的一个执行单元,进程内至少有一个线程,他们共享进程地址空间,而进程有自己的独立的地址空间。

            线程是处理器调度的基本单位,但进程不是。

            二者都可以并发执行。

            有进程进行控制线程。

            


            协程:由用户进行控制  异步处理  协程能保留上一次调用的状态


            进程间通讯不方便。


            线程就是把一个进程分为很多片

            22.jpg

        

    

            23.jpg

24.jpg


    

$sockserv=stream_socket_server("tcp://0.0.0.0:8000",$errno,$errstr);



25.jpg

严重依赖进程,这就缺陷。


创建进程的数量是有限的,


    现在高并发异步IO的服务器程序都是基于epoll实现的           

    

    

    Reactor模型

        26.jpg          Nginx多线程的Reactor


        swoole 名字叫斯沃   多线程的Reactor+多线程的worker    


            什么是多进程、多线程

            

            同步阻塞模型


            异步非阻塞模型


            PHP并发变成实践


                PHP的Swoole扩展

                    异步多线程服务器、消息队列、毫秒定时器、异步文件读写

                    除了异步IO的支持之外,Swoole为PHP多进程的模式设计了多个并发数据结构和IPC通讯机制,可以大大简化多进程并发编程的工作。 就不在用 socker 和Reactor 了。

                    27.jpg

                是一种异步模型,不用等待。可以是PHP的一个框架。

                需要打一个扩展。


                消息队列

                    场景说明:用户注册后,需要发送注册邮件和注册短信


                    串行方式:将注册信息写入数据库成功后,发送注册邮件,发送注册短信


                    并行方式:将注册信息写入数据库成功后,发送注册邮件,同时发送短信

                    
                    应用解耦:

                        场景说明:用户下单后,订单系统需要通知库存系统

                     28.jpg                   

            流量削峰

            29.jpg

30.jpg


31.jpg

                   

                接口的并发请求

                

            32.jpg




    数据库缓存


        什么是数据库缓存

        




        为什么要使用缓存

        极大解决数据库服务器的压力

         提高应用数据的响应速度

        常见的缓存形式:内存缓存、文件缓存

         为了节俭IO的开销,因此我们使用的是内存缓存。

        

        高并发下,能最大成都地降低对数据库服务器的访问压力。

        

        最大可能的降低IO的访问,这个比较慢,

        放在内存中的数据访问速度最快。

        


        缓存方式的选择:

        缓存场景的选择:

        缓存数据的实时性:缓存一个时间长度,过了一段时间后就销毁,重新访问缓存

        缓存数据的稳定性:

        


        使用mysql查询缓存:    

         mysql自带的查询缓存:

            query_cache_type:0 1 2

            0 不使用缓存

            1 始终使用缓存

            2 按需使用缓存

            为1:

            select sql_no_cache * from web_aa where id>100;

            为2:

            select sql_cache * from web_aa where id>100;


            

            query_cache_size=0 默认情况下query_cache_size为0 表示为查询缓存预留的内存是0 ,则无法使用查询缓存。

            这个可以在php.ini 配置项中配置

            也可以使用 sql语句设置:

            set GLOBAL query_cache_size=13421555;

            

            清理缓存:

            flush query cache

            flush tables

                

            作为一个了解,知道即可。


        

            极大降低CPU的使用率



        使用memcache缓存

        

        是一套分布式的高速缓存系统  内存 对象  维护一个庞大hash表        

        33.jpg

        需要PHP安装memcache 或 memcached的扩展



        使用redis缓存



        redis与memcache的区别


            性能相差不大

            持久化 redis

            redis,依赖客户端来实现分布式读写

            redis支持快照进行持久化,aof增强了可靠性的同时,对性能有所影响。

            34.jpg

           

        字符串、队列、hash、集合、

            

        

        

        session_set_save_handler 来设置session 保存在哪里



        


    mysql数据库底层优化


    数据表数据类型优化

    这个怎么优化呢?优化两个点

    字段使用什么样的数据类型更加合适

    字段使用什么速度会更快


    tinyint   smallint      int     bigint

    0-255          

    考虑空间的问题,考虑范围的问题

    unsingd 正

    

    char  和 varchar

    手机号  char  11位

    md5   char  32位

    varchar  用户名

    字符串长度是否固定

    

    enum

    内部采用整形的方式存储

    效率更快  确定的东西可以采用enum来存储


    IP地址的存储

    可以采用整形来存  ip2long    long2ip

    可以采用整形来存储IP地址 ,使用PHP函数


    索引

    索引并不是越多越好,在合适的字段上创建合适的索引

    

    符合索引  前缀原则  如果a b c

    

    like查询% 不使用索引


     全表索引优化     

    

    字符串类型索引失效的问题   如果字符串中存储的是一个整形,如果没有加单引号 那么索引会失效

    

    使用Limit


    切分查询 删除1000万   那么 我们可以采用拆分  每次删除100万


    优化特定类型

    count(*) 没有where 的查询 是最快的


    优化关联查询  特定的关联查询


    优化自查询 尽量不适用子查询 要是用联合联合查询  left join



    优化group by  和 distinct


    优化limit 和 union   联合


    存储引擎的优化


    myISAM    Innodb

    

    使用行级锁


    分区操作

    通过特定的策略对数据表进行物理拆分

    根据热点数据一个区、冷数据一个区

    对用户透明


    partition by 使用分区



    分库分表

        分库分表  拆分成多张表格

    

    水平拆分

    

    垂直拆分   

    

    join

    

    union   

    

    数据库架构的优化

        主从复制

        读写分离

        双主热备

        负载均衡  LVS        MyCat 中间件





    web服务器的负载均衡


    实现两种负载均衡

    

   实现七层均衡的实现  nginx

        

    1.jpg

    

    nginx 负载均衡

        内置策略   扩展策略

        内置策略   IP Hash  、加权轮询

        扩展策略    fair策略  通用hash  一致性hash

       

        加权轮询:

        首先将请求都分给高权重的机器,知道该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器

        当所有后端机器都挂掉了,nginx会立即将所有机器的标志位清成初始状态,以避免造成所有的额机器都处在timeout的状态。

      IP Hash :

        变相的一种轮询


    fair策略

        判断响应时间最快的,选择一个负载最轻的


    nginx负载均衡配置


        ji2.jpg

      


add header  cache-control max-age=3600;

3.jpg        




add_header REAL_SERVER 8082;

4.jpg



5.jpg

7.jpg




8.jpg


   按照  weight 从大到小 

        

    实现四层均衡的实现  LVS实现服务器集群 nat dr tun














    

    



    



    









    create index indexname  









    


        






        





           



    索引优化

    sql语句的优化

    存储引擎的优化

    数据表结构设计的优化

    数据库服务器架构的优化








        服务器端优化:

            页面静态化

            并发处理

            

        

        数据库优化:

            数据库缓存

            分库分表 操作

            读写分离

    

        web服务器优化:

            负载均衡 LVS