Nginx调优-超详细
作者:mmseoamin日期:2023-12-14

Nginx调优

  • 一、性能优化考虑点
  • 二、当前系统结构瓶颈
  • 三、了解业务模式
  • 四、master-worker机制
    • master-worker工作原理
    • master-worker机制
    • master-worker模式
    • accept_mutex解决“惊群现象”
    • 用多进程结构而不用多线程结构的好处
    • 实现高并发的秘密-IO多路复用
    • Nginx的master-worker工作机制的优势
    • 五、系统与Nginx性能优化
      • 文件句柄
      • cpu的亲和配置
      • 事件处理模型优化
      • 设置work_connections连接数
      • keepalive timeout会话保持时间
      • GZIP压缩性能优化
      • 连接超时时间
      • proxy超时设置
      • proxy_set_header
      • 高效传输模式
      • fastcgi调优
      • expires缓存调优
      • 访问限流(rate limiting)
        • 限速方法
        • nginx限速模块
        • 限速原理
        • 限速实现
          • 1)单位时间内请求数限制
            • 1.首先测试不加burst不加nodelay的情况:
            • 2. 只加burst不加nodelay和的情况:
            • 3.加burst加nodelay的情况
            • 总结
            • 2)限制并发连接数
            • 3)限制下载速度
            • 4)综合案例
            • 六、内核参数优化
            • 七、实战配置
              • 内核参数配置
              • nginx全局配置
              • 负载均衡
              • server配置
              • HTTPS配置(ssl配置)

                一、性能优化考虑点

                当我需要进行性能优化时,说明我们服务器无法满足日益增长的业务。性能优化是一个比较大的课题,需要从以下几个方面进行探讨。

                • 当前系统结构瓶颈
                • 了解业务模式 原理、性能和安全

                  二、当前系统结构瓶颈

                  首先需要了解的是当前系统瓶颈,用的是什么,跑的什么业务。里面的服务是什么样子,每个服务最大支持多少并发。比如针对Nginx而言,我们处理静态资源最高的并发是多大。

                  • 可以通过查看当前cpu负荷,内存使用率,进程使用率来做简单判断。还可以通过操作系统的一些工具来判断当前系统性能瓶颈,如分析对应日志,查看请求数量。
                  • 也可以通过nginx vts模块来查看对应的连接数,总握手次数,总请求数。以对上线进行压力测试,来了解当前的系统的性能,并发数,做好性能评估。

                    三、了解业务模式

                    虽然我们是在做性能优化,但还是要熟悉业务,最终目的都是为了业务服务的。我们要了解每一个接口业务类型是什么样的业务,

                    • 比如电商抢购模式,这种情况配是流量会很小,但是到了抢购时间,流量一下子就会猛涨。也要了解系统层级结构,每一层中间层做的是代理还是动静分离,还是后台进行直接服务。需要我们对业务接入层和系统层次要有一个梳理。

                      四、master-worker机制

                      master-worker工作原理

                      Nginx调优-超详细,master-worker工作原理,第1张

                      Nginx调优-超详细,一个master(进程)管理多个worker(进程),第2张

                      • 一个 master (进程) 管理多个 worker (进程)

                        master-worker机制

                        • 争抢机制示意图

                          Nginx调优-超详细,在这里插入图片描述,第3张

                        • 一个master Process管理多个worker process,也就是说Nginx采用的是多进程结构,而不是多线程结构

                        • 当client发出请求(任务)时,master Process会通知管理的worker process

                        • worker process开始争抢任务,争抢到的worker process会开启连接,完成任务

                        • 每个worker都是一个独立的进程,每个进程里只有一个主线程

                        • Nginx采用了IO多路复用机制(需要在Linux环境),使用IO多路复用机制,是Nginx在使用为数不多的worker process就可以实现高并发的关键

                        • master-worker机制示意图

                          Nginx调优-超详细,在这里插入图片描述,第4张

                          master-worker模式

                          • Nginx 在启动后会有一个 master 进程和多个相互独立的 worker 进程
                          • Master 进程接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接
                          • Master进程能监控Worker进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的worker进程

                            accept_mutex解决“惊群现象”

                            • 所有子进程都继承了父进程sockfd,当连接进来时,所有子进程都将收到通知并 “争着” 与它建立连接,这就叫 “惊群现象”
                            • 大量的进程被激活又挂起,只有一个进程可以accept()到这个连接,会消耗系统资源
                            • Nginx提供了一个accept_mutex ,这是一个加在accept上的一把共享锁。即每个 worker 进程在执行 accept 之前都需要先获取锁,获取不到就放弃执行 accept() 有了这把锁之后,同一时刻,就只会有一个进程去 accpet(),就不会有惊群问题了
                            • 当一个worker进程在 accept() 这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,完成一个完整的请求
                            • 一个请求,完全由 worker 进程来处理,而且只能在一个 worker 进程中处理

                              用多进程结构而不用多线程结构的好处

                              • 节省锁带来的开销,每个 worker 进程都是独立的进程,不共享资源,不需要加锁。在编程以及问题查找上,也会方便很多
                              • 独立进程,减少风险。采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master 进程则很快重新启动新的 worker 进程

                                实现高并发的秘密-IO多路复用

                                • 对于 Nginx 来讲,一个进程只有一个主线程,那么它是怎么实现高并发的呢?
                                • 采用了 IO 多路复用的原理,通过异步非阻塞的事件处理机制,epoll模型,实现了轻量级和高并发
                                • nginx 是如何具体实现的呢?

                                  举例来说:每进来一个request,会有一个 worker 进程去处理。但不是全程的处理,处理到什么程度呢?

                                  处理到可能发生阻塞的地方,比如向上游 (后端) 服务器转发 request,并等待请求返回

                                  那么,这个处理的 worker 不会这么傻等着,他会在发送完请求后,注册一个事件:“如果 upstream 返回了,告诉我一声,我再接着干”。于是他就休息去了

                                  此时,如果再有 request 进来,他就可以很快再按这种方式处理

                                  而一旦上游服务器返回了,就会触发这个事件,worker 才会来接手,这个 request 才会接着往下走

                                  由于 web server 的工作性质决定了每个 request 的大部份生命都是在网络传输中,实际上花费在 server 机器上的时间片不多,这就是几个进程就能解决高并发的秘密所在

                                  Nginx的master-worker工作机制的优势

                                  • 支持 nginx -s reload 热部署,这个特征在前面我们使用过
                                  • 对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多
                                  • 每个 worker 都是一个独立的进程,但每个进程里只有一个主线程,通过异步非阻塞的方式 / IO 多路复用来处理请求,即使是高并发请求也能应对
                                  • 采用独立的进程,互相之间不会影响,一个worker进程退出后,其它 worker 进程还在工作,服务不会中断,master进程则很快启动新的worker进程
                                  • 一个 worker 分配一个CPU,那么worker的线程可以把一个cpu的性能发挥到极致

                                    五、系统与Nginx性能优化

                                    大家对相关的系统瓶颈及现状有了一定的了解之后,就可以根据邮箱性能方面做一个全体的优化。

                                    • 网络(网络流量、是否有丢包、网络的稳定性都会邮箱用户请求)
                                    • 系统(系统负载、饱和、内存使用率、系统的稳定性、硬盘磁盘是否损坏)
                                    • 服务(连接优化、内核性能优化、http服务请求优化都可以在nginx中根据业务来进行设置)
                                    • 程序(接口性能、处理请求速度、每个程序的执行效率)
                                    • 数据库、底层服务

                                      文件句柄

                                      linux/unix,一切皆文件,每一次用户发起请求就会生成一个文件句柄,文件句柄可以理解为就是一个索引,所有文件句柄就会随着请求量的增多,而进程调用的频率增加,文件句柄的产生就会越多,系统对文件句柄默认的限制是1024个,对于nginx来说非常小了,需要改大一点

                                      ulimit -n #可以查看系统设置的最大文件句柄
                                      

                                      Nginx调优-超详细,在这里插入图片描述,第5张

                                      1. 设置方式

                                        系统全局性修改

                                        用户局部性修改

                                        进程局部性修改

                                      2. 系统全局性修改和用户局部性修改
                                      vim /etc/security/limits.conf
                                      

                                      Nginx调优-超详细,在这里插入图片描述,第6张

                                      soft:软控制,到达设定值后,操作系统不会采取措施,只是发提醒

                                      hard:硬控制,到达设定值后,操作系统会采取机制对当前进行进行限制,这个时候请求就会受到影响

                                      root:这里代表root用户(系统全局性修改)

                                      *:代表全局,即所有用户都受此限制(用户局部性修改)

                                      nofile:指限制的是文件数的配置项。后面的数字即设定的值,一般设置10000左右

                                      尤其在企业新装的系统,这个地方应该根据实际情况进行设置,可以设置全局的,也可以设置用户级别的。

                                      su #刷新以下环境
                                      ulimit -n #再次查看系统最大文件句柄
                                      

                                      Nginx调优-超详细,在这里插入图片描述,第7张

                                      这里就改为了,我们对root用户设置的最大文件句柄65535

                                      1. 进程局部性修改
                                      vim /usr/local/nginx/conf/nginx.conf
                                      

                                      每个进程的最大文件打开数,所以最好与ulimit -n的值保持一致。

                                      Nginx调优-超详细,在这里插入图片描述,第8张

                                      重启一下服务

                                      Nginx调优-超详细,在这里插入图片描述,第9张

                                      cpu的亲和配置

                                      cpu的亲和能偶使nginx对于不同的work工作进程绑定到不同的cpu上面去。就能够减少在work间不断切换cpu,把进程通常不会在处理器之间频繁迁移,进程迁移的频率小,来减少性能损耗。

                                      每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu 数相等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗

                                      Nginx调优-超详细,在这里插入图片描述,第10张

                                      1. 具体设置

                                        Nginx允许工作进程个数一般设置CPU的核心或者核心数*2.如果不了解cpu核数,可以使用top后按1看出来,也可以查看/proc/cpuinfo文件

                                      cat /proc/cpuinfo | grep ^processor | wc -l #查看cpu核数
                                      

                                      Nginx调优-超详细,在这里插入图片描述,第11张

                                      lscpu | grep "CPU(s)" #另一种查看cpu核数的方式
                                      

                                      Nginx调优-超详细,在这里插入图片描述,第12张

                                      这里我是4核

                                      随后进入nginx配置文件进行修改。需要知道的就是nginx 1.9版本之后,就帮我们自动绑定了cpu;

                                      所以我们只需要打开cpu亲和就行

                                      vim /usr/local/nginx/conf/nginx.conf 
                                      
                                      user nginx;
                                      worker_processes  4;
                                      worker_cpu_affinity auto;
                                      #或者 worker_cpu_affinity 0001 0010 0100 1000;
                                      worker_rlimit_nofile 65535;
                                      
                                      • worker_rlimit_nofile更改worker进程的最大打开文件数限制。如果没设置的话,这个值为操作系统的限制。设置后你的操作系统和Nginx可以处理比ulimit -a”更多的文件,使用把这个值设高,这样nginx就不会有 “too many open files”问题了。

                                        重启一下nginx,查看一下nginx worker进程绑定对应的cpu

                                        ps -eo pid,args,psr | grep -v grep | grep nginx
                                        

                                        Nginx调优-超详细,在这里插入图片描述,第13张

                                        这样就能看到nginx的子进程都绑定到了哪些cpu核上

                                        设置worker数量,Nginx 默认没有开启利用多核cpu,可以通过增加worker_cpu_affinity配置参数来充分利用多核cpu的性能

                                        #2 核 cpu,开启 2 个进程
                                        worker_processes 2;
                                        worker_cpu_affinity 01 10;
                                        #2 核 cpu,开启 4 个进程,
                                        worker_processes 4;
                                        worker_cpu_affinity 01 10 01 10;
                                        #4 核 cpu,开启 2 个进程,0101 表示开启第一个和第三个内核,1010 表示开启第二个和第四个内核;
                                        worker_processes 2;
                                        worker_cpu_affinity 0101 1010;
                                        #4 个 cpu,开启 4 个进程
                                        worker_processes 4;
                                        worker_cpu_affinity 0001 0010 0100 1000;
                                        #8 核 cpu,开启 8 个进程
                                        worker_processes 8;
                                        worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
                                        
                                        • worker_cpu_affinity 理解

                                          Nginx调优-超详细,在这里插入图片描述,第14张

                                          Nginx调优-超详细,在这里插入图片描述,第15张

                                          事件处理模型优化

                                          nginx的连接处理机制在于不同的操作系统会采用不同的I/O模型,Linux下,nginx使用epoll的I/O多路复用模型,在freebsd(类unix操作系统)使用kqueue的I/O多路复用模型,在Solaris(unix系统的一个重要分支操作系统)使用/dev/pool方式的I/O多路复用模型,在windows使用的icop等等。要根据系统类型不同选择不同的事物处理模型,我们使用的是centos,因此讲nginx的事件处理模型调整为epoll。

                                          进入配置文件再进行修改

                                          events {
                                              worker_connections  10240;
                                              multi_accept on;  
                                              use epoll;
                                          }
                                          
                                          • multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的连接,默认是on,设置为on后,多个worker按串行方式来处理连接,也就是一个连接只有一个worker被唤醒,其他的处于休眠状态,设置为off后,多个worker按并行方式来处理连接,也就是一个连接会唤醒所有的worker,直到连接分配完毕,没有取得连接的继续休眠。当你的服务器连接数不多时,开启这个参数会让负载有一定的降低,但是当服务器的吞吐量很大时,为了效率,可以关闭这个参数。

                                            设置work_connections连接数

                                            work_connections表示每个worker(子进程)可以创建多少个连接,

                                            默认:work_connections:1024

                                            最大:work_connections:65535

                                            同时要根据系统的最大打开文件数来调整

                                            系统的最大打开文件数>= worker_connections*worker_process

                                            根据系统的最大打开文件数来调整,worker_connections 进程连接数量要小于等于系统的最大打开文件数

                                            worker_connections 进程连接数量真实数量= worker_connections * worker_process

                                            查看系统的最大打开文件数:

                                            ulimit -a | grep "open files"
                                            

                                            这里我自己改为10240(这个参数与服务器性能相关)

                                            worker_connections  10240;
                                            
                                            • 根据最大连接数计算最大并发数

                                              如果是支持 http1.1 的浏览器每次访问要占两个连接,所以普通的静态访问最大并发数是:worker_connections * worker_processes /2

                                              而如果是HTTP作为反向代理来说,最大并发数量应该是 worker_connections * worker_processes/4

                                              因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会各占用两个连接

                                              看一个示意图

                                              Nginx调优-超详细,在这里插入图片描述,第16张

                                              keepalive timeout会话保持时间

                                              • 这里先解释一下什么是keepalive,keepalive就是建立一下长连接,这个timeout就是,当浏览器建立一个连接之后,这个连接最长能存在多少事件不给他关闭,这个65也不是说建立65s连接后就直接关闭,而是一个活跃事件,就是第一次请求和下一次请求都会刷新这个65s,再65s内没有再请求数据才会真的关闭这个连接,所以这个事件也不应该太长,60左右也差不多了。

                                                keepalive_timeout 65;

                                                keepalive 其他的一些配置

                                                keepalive:像上游服务器的保留连接数

                                                keepalive_disable:是指把某些浏览器禁用掉

                                                keepalive_requests:这个表示当我们建立一个可复用长连接,在当前这一个连接里可以并发接收多少个请求,默认1000个

                                                send_timeout:在向客户端发送数据时,建立好连接后,超过两次活动时间(服务器很长时间没有返回数据)那么就会将这个连接关掉

                                                keepalive_time:一个tcp连接的总时长,超过这个时间要再请求连接一下

                                                GZIP压缩性能优化

                                                gzip  on;   #表示开启压缩功能
                                                gzip_min_length 1k;  #表示允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值为0,表示不管页面多大都进行压缩,设置建议设大于1k。如果小于1k可能会越压越大。
                                                gzip_buffers 4 32k; #压缩缓存区大小
                                                gzip_http_version 1.1; #压缩版本
                                                gzip_comp_level 6; #压缩比率,一般选择4-6,为了性能gzip_typs text/css text/xml application/javascript; #指>定压缩的类型 gzip_vary on; #vary header支持;
                                                gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript text/css application/xml;
                                                gzip_vary on ; #varyheader支持,改选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用Squid缓存经过nginx压缩的数据。
                                                
                                                • gzip_min_length 1k:设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0,不管页面多大都进行压缩,建议设置成大于1K,如果小与1K可能会越压越大。
                                                • gzip_buffers 4 32k:压缩缓冲区大小,表示申请4个单位为32K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。
                                                • gzip_http_version 1.1:压缩版本,用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可。
                                                • gzip_comp_level 6:压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源。
                                                • gzip_types text/css text/xml application/javascript:用来指定压缩的类型,‘text/html’类型总是会被压缩。默认值: gzip_types text/html (默认不对js/css文件进行压缩)压缩类型,匹配MIME型进行压缩;

                                                  连接超时时间

                                                  其目的是保护服务器资源,cpu,内存没控制连接数,因为建立连接也是需要消耗资源的。

                                                  keepalive_timeout 60; #客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接。
                                                  tcp_nodelay on; #也是防止网络阻塞,不过要包涵在keepalived参数才有效。
                                                  client_header_buffer_size 4k; #客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过 1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
                                                  open_file_cache max=102400 inactive=20s; #这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
                                                  open_file_cache_valid 30s; #这个是指多长时间检查一次缓存的有效信息。
                                                  open_file_cache_min_uses 1; #open_file_cache指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。
                                                  client_header_timeout 15; #设置请求头的超时时间。我们也可以把这个设置低些,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误。
                                                  client_body_timeout 15; #设置请求体的超时时间。我们也可以把这个设置低些,超过这个时间没有发送任何数据,和上面一样的错误提示。
                                                  reset_timedout_connection on; #告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。
                                                  send_timeout 15; #响应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接。
                                                  server_tokens off; #并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。
                                                  client_max_body_size 10m; #上传文件大小限制。
                                                  

                                                  proxy超时设置

                                                  proxy_connect_timeout 90; #后端服务器连接的超时时间,发起握手等候响应超时时间
                                                  proxy_send_timeout 90;  #后端服务器数据回传时间,就是在规定时间内后端服务器必须传完所有的数据
                                                  proxy_read_timeout 90;  #连接成功后,等候后端服务器响应时间,其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间,页面等待服务器响应时间)
                                                  proxy_buffers 4 32k;  #4是数量 32k是大小 该指令设置缓存区的大小和数量,从被代理的后端服务器取得的第一部分响应内容,会放置到这里,默认情况下,一个缓存区的大小等于内存页面大小,可能是4k也可能是8k取决于平台
                                                  proxy_busy_buffers_size 64k; #nginx在收到服务器数据后,会分配一部分缓冲区来用于向客户端发送数据,这个缓存区大小由proxy_busy_buffers_size决定的。大小通常是proxy_buffers单位大小的两倍,官网默认是8k/16k。
                                                  
                                                  • buffer工作原理
                                                    1. 所有的proxy buffer参数都是作用到每一个请求的。每一个请求会按照参数的配置获得自己的buffer。proxy buffer不是global(全局配置),而是per request(在请求前执行的操作(如时间戳、签名))的

                                                    2. proxy_buffering是为了开启response buffering of the proxied server(反向代理服务器响应数据的缓存),开启后proxy_buffers和proxy_busy_buffers_size参数才会起作用

                                                    3. 无论proxy_buffer是否开启,proxy_buffer_size都是工作的,proxy_buffer_size所设置的buffer_size的作用是用来存储upstream端response的header。

                                                    4. 在proxy_buffering 开启的情况下,Nginx将会尽可能的读取所有的upstream端传输的数据到buffer,直到proxy_buffers设置的所有buffer们被写满或者数据被读取完(EOF)。此时nginx开始向客户端传输数据,会同时传输这一整串buffer们。同时如果response的内容很大的话,Nginx会接收并把他们写入到temp_file里去。大小由proxy_max_temp_file_size控制。如果busy的buffer传输完了会从temp_file里面接着读数据,直到传输完毕。

                                                    5. 一旦proxy_buffers设置的buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这个buffer将会一直处在busy状态,我们不能对这个buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过proxy_busy_buffers_size,所以proxy_busy_buffers_size是用来控制同时传输到客户端的buffer数量的。

                                                    proxy_set_header

                                                    proxy_set_header用来设定被代理服务器接收到的header信息

                                                    语法:proxy_set_header field value;

                                                    field :为要更改的项目,也可以理解为变量的名字,比如host

                                                    value :为变量的值

                                                    如果不设置proxy_set_header,则默认host的值为proxy_pass后面跟的那个域名或者IP(一般写IP)

                                                    proxy_set_header X-Real-IP $remote_addr;

                                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                                                    用来设置被代理端接收到的远程客户端IP,如果不设置,则header信息中并不会透传远程真实客户端的IP地址。

                                                    server {
                                                            ...
                                                            location /http/ {
                                                                    proxy_pass http://http_backend;
                                                                    proxy_http_version 1.1;                 # 对于http协议应该指定为1.1
                                                                    proxy_set_header Connection "";         # 清除"connection"头字段 , Connection: keep-alive
                                                                    proxy_set_header Host $http_host;		# 代理服务器匹配请求web01服务器的时候,默认加上Host头信息(域名)	
                                                    				proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;		# 追加客户端ip地址以及全链路ip地址到web服务器记录日志	
                                                    				proxy_next_upstream error timeout http_500 http_502 http_503 http_504; # 当Nginx虚拟服务池其中任意一台服务器返回错误码500,502,503,504等错误时,可以分配到下一台服务器程序继续处理,提高平台访问的成功率
                                                    				proxy_connect_timeout 60s;				# nginx代理与后端服务器连接超时时间(代理连接超时)
                                                    				proxy_read_timeout 60s;					# nginx代理等待后端服务器的响应时间(代理响应超时)
                                                    				proxy_send_timeout 60s;					# 后端服务器数据回传给nginx代理超时时间(回传数据给代理超时)
                                                    				
                                                    				proxy_buffering on;						# nginx会把后端返回的内容先放到缓冲区中,然后再返回给客户端,边收边传,不是全部接收再传给客户端
                                                    				proxy_buffers_size 4k;					# 设置nginx代理保存用户头信息的缓存区大小
                                                    				proxy_buffers 8 8k;						# 设置nginx代理缓冲区大小(8*8 = 64k)
                                                            ...
                                                            }
                                                    }
                                                    
                                                    • $proxy_host 自然是 proxy_pass后面跟着的host

                                                      比如一个请求 https://zhidao.baidu.com/question/22908463.html

                                                      Request.ServerVariables(“HTTP_HOST”) 可以获得HTTP_HOST请求标题:zhidao.baidu.com

                                                    • $http_host始终等于HTTP_HOST请求标题

                                                    • $host等于$http_host,小写并且没有端口号(如果存在),除非HTTP_HOST不存在或是空值。在这种情况下,$host等于server_name

                                                    • $proxy_add_x_forwarded_for 从客户访问到到最后的后台服务所经理的所有节点的ip汇总221.221.1.100,10.30.30.109,…

                                                      nginx的自带变量 $remote_addr 代表客户端的IP

                                                    • $remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。

                                                    • $remote_addr 只能获取到与服务器本身直连的上层请求ip,所以设置$remote_addr一般都是设置第一个代理上面;但是问题是,有时候是通过cdn访问过来的,那么后面web服务器获取到的,永远都是cdn的ip 而非真是用户ip,那么这个时候就要用到X-Forwarded-For 了,这个变量的意思,其实就像是链路反追踪,从客户的真实ip为起点,穿过多层级的proxy ,最终到达web 服务器,都会记录下来,所以在获取用户真实ip的时候,一般就可以设置成,proxy_set_header X-Forwarded-For

                                                    • $proxy_add_x_forwarded_for; 这样就能获取所有的代理ip 客户ip $proxy_add_x_forwarded_for变量包含客户端请求头中的X-Forwarded-For与$remote_addr两部分,他们之间用逗号分开。

                                                      高效传输模式

                                                      sendfile on; #开启高效文件传输模式。
                                                      tcp_nopush on;#需要在sendfile开启模式才有效,防止网络阻塞,级级的减少网络报文段的数量。将响应头和正文的开始部分一起发送,而不是一个接一个的发送(也就是说数据包不会马上传出等到数据包最大时一次性传)
                                                      tcp_nodelay on; #只要有数据包产生,不管大小多少,就尽快传输
                                                      

                                                      fastcgi调优

                                                      fastcgi_connect_timeout 600; #指定连接到后端FastCGI的超时时间。
                                                      fastcgi_send_timeout 600; #向FastCGI传送请求的超时时间。
                                                      fastcgi_read_timeout 600; #指定接收FastCGI应答的超时时间。
                                                      fastcgi_buffer_size 64k; #指定读取FastCGI应答第一部分需要用多大的缓冲区,默认的缓冲区大小为。fastcgi_buffers指令中的每块大小,可以将这个值设置更小。
                                                      fastcgi_buffers 4 64k; #指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求,如果一个php脚本所产生的页面大小为256KB,那么会分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp_path指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于磁盘。一般这个值应该为站点中php脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“8 32K”、“4 64k”等。
                                                      fastcgi_busy_buffers_size 128k; #建议设置为fastcgi_buffers的两倍,繁忙时候的buffer。
                                                      fastcgi_temp_file_write_size 128k; #在写入fastcgi_temp_path时将用多大的数据块,默认值是fastcgi_buffers的两倍,该数值设置小时若负载上来时可能报502BadGateway。
                                                      fastcgi_temp_path /usr/local/nginx1.22/nginx_tmp; #缓存临时目录。
                                                      fastcgi_intercept_errors on; #这个指令指定是否传递4xx和5xx错误信息到客户端,或者允许nginx使用error_page处理错误信息。注:静态文件不存在会返回404页面,但是php页面则返回空白页!
                                                      fastcgi_cache_path /usr/local/nginx1.22/fastcgi_cache levels=1:2 keys_zone=cache_fastcgi:128m inactive=1d max_size=10g; #fastcgi_cache缓存目录,可以设置目录层级,比如1:2会生成16*256个子目录,cache_fastcgi是这个缓存空间的名字,cache是用多少内存(这样热门的内容nginx直接放内存,提高访问速度),inactive表示默认失效时间,如果缓存数据在失效时间内没有被访问,将被删除,max_size表示最多用多少硬盘空间。
                                                      

                                                      此外还有

                                                      fastcgi_cache cache_fastcgi:#表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502的错误放生。cache_fastcgi为proxy_cache_path指令创建的缓存区名称。

                                                      fastcgi_cache_valid 200 302 1h:#用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存一小时,要和fastcgi_cache配合使用。

                                                      fastcgi_cache_valid 301 1d:将301应答缓存一天。

                                                      fastcgi_cache_valid any 1m:将其他应答缓存为1分钟。

                                                      fastcgi_cache_min_uses 1:该指令用于设置经过多少次请求的相同URL将被缓存。

                                                      fastcgi_cache_key http://hosthosthostrequest_uri:该指令用来设置web缓存的Key值,nginx根据Key值md5哈希存储.一般根据host (域名) 、host(域名)、host(域名)、request_uri(请求的路径)等变量组合成proxy_cache_key 。

                                                      fastcgi_pass:指定FastCGI服务器监听端口与地址,可以是本机或者其它。

                                                      • 总结

                                                        nginx的缓存功能有:proxy_cache / fastcgi_cache

                                                        proxy_cache的作用是缓存后端服务器的内容,可能是任何内容,包括静态的和动态。

                                                        fastcgi_cache的作用是缓存fastcgi生成的内容,很多情况是php生成的动态的内容。

                                                        proxy_cache缓存减少了nginx与后端通信的次数,节省了传输时间和后端宽带。

                                                        fastcgi_cache缓存减少了nginx与php的通信的次数,更减轻了php和数据库(mysql)的压力。

                                                        expires缓存调优

                                                        缓存,主要针对于图片,css,js等元素更改机会比较少的情况下使用,特别是图片,占用带宽大,我们完全可以设置图片在浏览器本地缓存365d,css,js,html可以缓存个10来天,这样用户第一次打开加载慢一点,第二次,就非常快了!缓存的时候,我们需要将需要缓存的拓展名列出来, Expires缓存配置在server字段里面。

                                                        location ~* \.(ico|jpe?g|gif|png|jpeg|bmp|swf|flv)$
                                                        {
                                                        	expires 30d;  #过期时间为30天
                                                        	#log_not_found off;
                                                        	access_log off;
                                                        }
                                                        location ~* \.(js|css)$ 
                                                        {
                                                        	expires 7d;
                                                        	log_not_found off;
                                                        	access_log off;
                                                        }
                                                        

                                                        注:log_not_found off;是否在error_log中记录不存在的错误。默认是。

                                                        Expires:是缓存到期的时间

                                                        访问限流(rate limiting)

                                                        我们构建网站是为了让用户访问它们,我们希望用于合法访问。所以不得不采取一些措施限制滥用访问的用户。这种滥用指的是从同一IP每秒到服务器请求的连接数。因为这可能是在同一时间内,世界各地的多台机器上的爬虫机器人多次尝试爬取网站的内容。

                                                        限速方法

                                                        限速分为很多种限速方法:

                                                        1)下载速度限速

                                                        2)单位时间内请求数限制

                                                        3)基于客户端的并发连接限速

                                                        nginx限速模块

                                                        Nginx官方版本限制IP的连接和并发分别有两个模块:

                                                        limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”。

                                                        limit_req_conn 用来限制同一时间连接数,即并发限制。

                                                        应用场景

                                                        下载限速:限制现在速度及并发连接数,应用在下载服务器中,保护带宽及服务器的IO资源。

                                                        请求限速:限制单位时间内用户访问请求,防止恶意攻击,保护服务器及资源安全。

                                                        限速原理

                                                        • 漏桶算法

                                                          算法思想是:

                                                          水(请求)从上方倒入水桶,从水桶下方流出(被处理);

                                                          来不及流出的水存在水桶中(缓冲),以固定速率流出;

                                                          水桶满后水溢出(丢弃)。

                                                          这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。

                                                          相比漏桶算法,令牌桶算法不同之处在于它不但有一只“桶”,还有个队列,这个桶是用来存放令牌的,队列才是用来存放请求的。

                                                          Nginx调优-超详细,在这里插入图片描述,第17张

                                                          限速实现

                                                          1)单位时间内请求数限制

                                                          可用于防止DDoS攻击,或防止上游服务器同时被太多请求淹没。

                                                          16000个IP地址的状态信息,大约需要1MB

                                                          #基于IP对下载速率做限制  限制每秒处理1次请求,对突发超过5个以后的请求放入缓存区
                                                          http {
                                                              limit_req_zone $binary_remote_addr zone=baism:1m rate=1r/s;
                                                              server {
                                                                  location /abc {
                                                                      limit_req zone=baism burst=5 nodelay;
                                                                  }
                                                          }
                                                          

                                                          参数解释

                                                          • limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s;

                                                            第一个参数:$binary_remote_addr ,表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。$binary_remote_addr为IPv4时占用4B,为IPv6时占用16B。

                                                            第二个参数:zone=baism:10m,表示生成一个大小为10M,名字为baism的内存区域,用来存储访问的频次信息。

                                                            第三个参数:rate=1r/s,表示允许相同标识的客户端的访问频次

                                                            ,这里限制的是每秒1次,还可以有比如30r/m的,即每2秒才能处理一个请求。

                                                          • limit_req zone=baism burst=5 nodelay;

                                                            第一个参数:zone=baism ,设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。

                                                            第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区,当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有5个,超过的请求会直接报503的错误然后返回

                                                            第三个参数:nodelay,如果设置,会在瞬时提供处理(burst+rate)个请求的能力

                                                            ,请求超过(burst+rate)的时候就会直接返回503,永远不存在请求需要等待的情况(这里的rate的单位是:r/s)

                                                            如果没有设置,则所有请求会依次等待排队。

                                                            burst详解及试验:

                                                            设定一个场景,一个nginx反向代理的后端服务单页请求数是30个,如果我们设置30r/s的话,那么这个burst设置就没有意义了,但是如果我们不想把rate设置成这么大,比如5r/s,也要完成这个一个页面30个请求的需求。这个时候burst就有作用了。(前后端一体化的服务,其静态资源单次刷新后,再访问时只会刷新动态请求)。

                                                            假设我们一个页面是30个请求,后面每秒都会刷新一个页面,但是新页面由于静态资源已经刷新,只有2-3个请求,因此我们把burst设置成200个(可以让用户连续强制刷新大约8次)。

                                                            当我们第一次访问时,由于rate是5个,只能处理5个,另外的25个会放到burst队列,虽然设置成nodelay会把这25个也处理了,但是队列中占用的25个位置,需要25/rate=5秒来清除,如果第二次请求是3个,那么我们实时处理了3个请求,并且rate剩余2个可以清空burst队列,这个时候,队列就是占用了23个位置。最后如果我们队列满了的话,那么就会出现503的请求。

                                                            验证效果:基本按上面的方式,连续每秒30个请求,即f5强制刷新,那么大约会再多少次后出现503的情况呢,答案大约是8次(200/25)。

                                                            burst=(每次请求数-请求限制数)*允许强制刷新的次数

                                                            例子演示:

                                                            首先我们配置了limit_req_zone,rate=10r/m,即每六秒才处理一次请求,如下:

                                                            Nginx调优-超详细,在这里插入图片描述,第18张

                                                            1.首先测试不加burst不加nodelay的情况:

                                                            Nginx调优-超详细,在这里插入图片描述,第19张

                                                            查看当前的tcp连接数

                                                            netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

                                                            结果如下:

                                                            Nginx调优-超详细,在这里插入图片描述,第20张

                                                            使用ab测试工具,发起10个并发请求:

                                                            ab -n 10 -c 10 url

                                                            ab工具返回结果:

                                                            Nginx调优-超详细,在这里插入图片描述,第21张

                                                            可以看到一共10个请求,9个请求都失败了。且0.002秒就完成了压测

                                                            接着查看当前的tcp连接数:

                                                            Nginx调优-超详细,在这里插入图片描述,第22张

                                                            可以观察到此时服务端的TIME_WAIT 比上图多了10,这意味着是服务端主动要求断开了所有TCP连接

                                                            接着再查看 /var/log/nginx/access.log,印证了只有一个请求成功了,其它就是都直接返回了503,即服务器拒绝了请求。

                                                            Nginx调优-超详细,在这里插入图片描述,第23张

                                                            2. 只加burst不加nodelay和的情况:

                                                            Nginx调优-超详细,在这里插入图片描述,第24张

                                                            查看当前的tcp连接数

                                                            netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

                                                            结果如下:

                                                            Nginx调优-超详细,在这里插入图片描述,第25张

                                                            使用ab测试工具,发起10个并发请求:

                                                            ab -n 10 -c 10 url

                                                            可以看到测试经过30s才结束

                                                            ab工具返回结果:

                                                            Nginx调优-超详细,在这里插入图片描述,第26张

                                                            压测中一共10个请求,有4个请求失败了,直接返回503

                                                            查看当前的tcp连接数:

                                                            Nginx调优-超详细,在这里插入图片描述,第27张

                                                            上图是ab测试第一秒时的截图,对比第一次截图,TIME_WAIT=19 24 表示有服务器端主动断开了5个TCP连接,即5个请求被瞬时拒绝

                                                            接着查看 /var/log/nginx/access.log日志

                                                            Nginx调优-超详细,在这里插入图片描述,第28张

                                                            可以观察到在50分46秒,即压测第1秒时,成功处理了1个请求,另外有4个请求瞬间返回了503,剩下的5个请求每隔6s处理一次。

                                                            这是因为设置了burst=5,在服务器接收到10个并发请求后,先处理1个请求,同时将5个请求放入burst缓冲队列中,等待处理。而超过(burst+1)数量的请求就被直接抛弃了,即直接抛弃了4个请求。

                                                            3.加burst加nodelay的情况

                                                            Nginx调优-超详细,在这里插入图片描述,第29张

                                                            查看当前的tcp连接数

                                                            netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

                                                            结果如下:

                                                            Nginx调优-超详细,在这里插入图片描述,第30张

                                                            使用ab测试工具,发起10个并发请求:

                                                            ab -n 10 -c 10 url

                                                            可以看到压测在0.001s内完成了,这也是添加nodelay参数的意义

                                                            ab工具返回结果:

                                                            Nginx调优-超详细,在这里插入图片描述,第31张

                                                            压测中一共10个请求,有4个请求失败了,直接返回了503

                                                            接着查看当前的tcp连接数:所有的请求都在1s内完成了

                                                            Nginx调优-超详细,在这里插入图片描述,第32张

                                                            接着查看 /var/log/nginx/access.log日志

                                                            Nginx调优-超详细,在这里插入图片描述,第33张

                                                            可以发现在1s内,服务器端处理了6个请求(峰值速度:burst+原来的处理速度)。对于剩下的4个请求,直接返回503,在下一秒如果继续向服务端发送10个请求,服务端会直接拒绝这10个请求并返回503。因为设定了没6s处理1个请求,所以直到30 s 之后,才可以再处理一个请求,即如果此时向服务端发送10个请求,会返回9个503,一个200

                                                            查看/var/log/nginx/error.log日志,发现有4个请求被直接拒绝了,没有延时请求。

                                                            Nginx调优-超详细,在这里插入图片描述,第34张

                                                            总结
                                                            • limit_req zone=req_zone;

                                                              严格依照在limti_req_zone中配置的rate来处理请求

                                                              超过rate处理能力范围的,直接drop

                                                              表现为对收到的请求无延时

                                                            • limit_req zone=req_zone burst=5;

                                                              依照在limti_req_zone中配置的rate来处理请求

                                                              同时设置了一个大小为5的缓冲队列,在缓冲队列中的请求会等待慢慢处理

                                                              超过了burst缓冲队列长度和rate处理能力的请求被直接丢弃

                                                              表现为对收到的请求有延时

                                                            • limit_req zone=req_zone burst=5 nodelay;

                                                              依照在limti_req_zone中配置的rate来处理请求

                                                              同时设置了一个大小为5的缓冲队列,当请求到来时,会爆发出一个峰值处理能力,对于峰值处理数量之外的请求,直接丢弃

                                                              在完成峰值请求之后,缓冲队列不能再放入请求。如果rate=10r/m,且这段时间内没有请求再到来,则每6s缓冲队列就能回复一个缓冲请求的能力,直到回复到能缓冲5个请求位置。

                                                              2)限制并发连接数

                                                              limit_conn_zone 中1MB的内存空间可以存储32000个32B16000个64B的变量计数状态。

                                                              变量计数状态在32位系统平台占用32B或64B,在64位系统平台占用64B

                                                              10M的话换算下来可以保留16万个IP地址信息

                                                              #基于IP做连接限制  限制同一IP并发为1
                                                              limit_conn_zone $binary_remote_addr zone=addr:10m;
                                                              server {
                                                                      listen       80;
                                                                      server_name  localhost;
                                                                      location / {
                                                                          root   html;
                                                                          index  index.html index.htm;
                                                                      }
                                                                      location /abc {
                                                                         limit_conn addr 1;
                                                                      }
                                                                  }
                                                              }
                                                              
                                                              3)限制下载速度
                                                              # 下载速度为100k
                                                              server {
                                                                      listen       80;
                                                                      server_name  localhost;
                                                                      location / {
                                                                          root   html;
                                                                          index  index.html index.htm;
                                                                      }
                                                                      location /abc {
                                                                         limit_rate 100k;
                                                                      }
                                                                  }
                                                              }
                                                              
                                                              4)综合案例
                                                              http {
                                                                  include       mime.types;
                                                                  default_type  application/octet-stream;
                                                                  sendfile        on;
                                                                  keepalive_timeout  65;
                                                                  #基于IP做连接限制
                                                                  limit_conn_zone $binary_remote_addr zone=addr:10m;
                                                                  #基于IP对下载速率做限制,限制每秒处理1次请求,
                                                                  limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
                                                               
                                                                  server {
                                                                      listen       80;
                                                                      server_name  localhost;
                                                                      location / {
                                                                          root   html;
                                                                          index  index.html index.htm;
                                                                      }
                                                                      location /abc {
                                                                         # 对突发超过5个以后的请求放入缓存区
                                                                         limit_req zone=one burst=5 nodelay;
                                                                         # 限制并发连接数为4
                                                                         limit_conn addr 4;
                                                                         # 限制下载速度为100K
                                                                         limit_rate 100k;
                                                                      }
                                                                  }
                                                              }
                                                              
                                                              #限制用户连接数来预防DOS攻击
                                                              limit_conn_zone $binary_remote_addr zone=perip:10m;
                                                              limit_conn_zone $server_name zone=perserver:10m;
                                                              #限制同一客户端ip最大并发连接数
                                                              limit_conn perip 2;
                                                              #限制同一server最大并发连接数
                                                              limit_conn perserver 20;
                                                              #限制下载速度,根据自身服务器带宽配置
                                                              limit_rate 300k;
                                                              

                                                              六、内核参数优化

                                                              vim /etc/sysctl.conf  #进入这个文件修改
                                                              sysctl -p   #让修改的内核信息生效
                                                              #################################################
                                                              fs.file-max = 999999
                                                              net.ipv4.ip_forward = 0
                                                              net.ipv4.conf.default.rp_filter = 1
                                                              net.ipv4.conf.default.accept_source_route = 0
                                                              kernel.sysrq = 0
                                                              kernel.core_uses_pid = 1
                                                              net.ipv4.tcp_syncookies = 1
                                                              kernel.msgmnb = 65536
                                                              kernel.msgmax = 65536
                                                              kernel.shmmax = 68719476736
                                                              kernel.shmall = 4294967296
                                                              net.ipv4.tcp_max_tw_buckets = 6000
                                                              net.ipv4.tcp_sack = 1
                                                              net.ipv4.tcp_window_scaling = 1
                                                              net.ipv4.tcp_rmem = 10240 87380 12582912
                                                              net.ipv4.tcp_wmem = 10240 87380 12582912
                                                              net.core.wmem_default = 8388608
                                                              net.core.rmem_default = 8388608
                                                              net.core.rmem_max = 16777216
                                                              net.core.wmem_max = 16777216
                                                              net.core.netdev_max_backlog = 262144
                                                              net.core.somaxconn = 40960
                                                              net.ipv4.tcp_max_orphans = 3276800
                                                              net.ipv4.tcp_max_syn_backlog = 262144
                                                              net.ipv4.tcp_timestamps = 0
                                                              net.ipv4.tcp_synack_retries = 1
                                                              net.ipv4.tcp_syn_retries = 1
                                                              net.ipv4.tcp_tw_recycle = 1
                                                              net.ipv4.tcp_tw_reuse = 1
                                                              net.ipv4.tcp_mem = 94500000 915000000 927000000
                                                              net.ipv4.tcp_fin_timeout = 1
                                                              net.ipv4.tcp_keepalive_time = 30
                                                              net.ipv4.ip_local_port_range = 1024 65000
                                                              
                                                              • fs.file-max = 999999:这个参数表示进程(比如一个worker进程)可以同时打开的最大句柄数,这个参数直线限制最大并发连接数,需根据实际情况配置。
                                                              • net.ipv4.tcp_max_tw_buckets = 6000:这个参数表示操作系统允许TIME_WAIT套接字数量的最大值,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。该参数默认为180000,过多的TIME_WAIT套接字会使Web服务器变慢。

                                                                注:主动关闭连接的服务端会产生TIME_WAIT状态的连接

                                                              • net.ipv4.ip_local_port_range = 1024 65000:允许系统打开的端口范围。
                                                              • net.ipv4.tcp_tw_recycle = 1:启用timewait快速回收。
                                                              • net.ipv4.tcp_tw_reuse = 1:开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接。这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT状态的连接。
                                                              • net.ipv4.tcp_keepalive_time = 30:这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。默认是2小时,若将其设置的小一些,可以更快地清理无效的连接。
                                                              • net.ipv4.tcp_syncookies = 1:开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理。
                                                              • net.core.somaxconn = 40960:web 应用中 listen 函数的 backlog 默认会给我们内核参数的。

                                                                net.core.somaxconn:限制到128,而nginx定义的NGX_LISTEN_BACKLOG 默认为511,所以有必要调整这个值。注:对于一个TCP连接,Server与Client需要通过三次握手来建立网络连接.当三次握手成功后,我们可以看到端口的状态由LISTEN转变为ESTABLISHED,接着这条链路上就可以开始传送数据了.每一个处于监听(Listen)状态的端口,都有自己的监听队列.监听队列的长度与如somaxconn参数和使用该端口的程序中listen()函数有关。somaxconn定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128,对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多。大的侦听队列对防止拒绝服务 DoS 攻击也会有所帮助。

                                                              • net.core.netdev_max_backlog = 262144:每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
                                                              • net.ipv4.tcp_max_syn_backlog = 262144:这个参数标示TCP三次握手建立阶段接受SYN请求队列的最大长度,默认为1024,将其设置得大一些可以使出现Nginx繁忙来不及accept新连接的情况时,Linux不至于丢失客户端发起的连接请求。
                                                              • net.ipv4.tcp_rmem = 10240 87380 12582912:这个参数定义了TCP接受缓存(用于TCP接受滑动窗口)的最小值、默认值、最大值。
                                                              • net.ipv4.tcp_wmem = 10240 87380 12582912:这个参数定义了TCP发送缓存(用于TCP发送滑动窗口)的最小值、默认值、最大值。
                                                              • net.core.rmem_default = 6291456:这个参数表示内核套接字接受缓存区默认的大小。
                                                              • net.core.wmem_default = 6291456:这个参数表示内核套接字发送缓存区默认的大小。
                                                              • net.core.rmem_max = 12582912:这个参数表示内核套接字接受缓存区的最大大小。
                                                              • net.core.wmem_max = 12582912:这个参数表示内核套接字发送缓存区的最大大小。
                                                              • net.ipv4.tcp_syncookies = 1:该参数与性能无关,用于解决TCP的SYN攻击。

                                                                七、实战配置

                                                                内核参数配置

                                                                #如果想把timewait降下了就要把tcp_max_tw_buckets值减小,默认是180000
                                                                net.ipv4.tcp_max_tw_buckets = 5000
                                                                 
                                                                #开启重用功能,允许将TIME-WAIT状态的sockets重新用于新的TCP连接
                                                                net.ipv4.tcp_tw_reuse = 1
                                                                 
                                                                #系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击
                                                                net.ipv4.tcp_max_orphans = 262144
                                                                 
                                                                #当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时。我们可以调短时间跨度
                                                                net.ipv4.tcp_keepalive_time = 30
                                                                

                                                                nginx全局配置

                                                                worker_processes  1;
                                                                pid  /var/run/nginx.pid;
                                                                 
                                                                events {
                                                                    worker_connections  2048;
                                                                        multi_accept on;
                                                                        use epoll;
                                                                }
                                                                 
                                                                http {
                                                                    include       /etc/nginx/mime.types;
                                                                    default_type  application/octet-stream;
                                                                                                          
                                                                        log_format main '{"@timestamp":"$time_iso8601",'   
                                                                        '"host":"$server_addr",'
                                                                        '"clientip":"$remote_addr",'
                                                                        '"size":$body_bytes_sent,'
                                                                        '"responsetime":$request_time,'
                                                                        '"upstreamtime":"$upstream_response_time",'
                                                                        '"upstreamhost":"$upstream_addr",'
                                                                        '"http_host":"$host",'
                                                                        '"url":"$uri",'
                                                                        '"xff":"$http_x_forwarded_for",'
                                                                        '"referer":"$http_referer",'
                                                                        '"agent":"$http_user_agent",'
                                                                        '"status":"$status"}';
                                                                        
                                                                    sendfile on;
                                                                    tcp_nopush on;
                                                                    tcp_nodelay on;
                                                                        
                                                                    server_names_hash_bucket_size 128;
                                                                    server_names_hash_max_size 512;
                                                                    keepalive_timeout  65;
                                                                    client_header_timeout 15s;
                                                                    client_body_timeout 15s;
                                                                    send_timeout 60s;
                                                                        
                                                                        limit_conn_zone $binary_remote_addr zone=perip:10m;
                                                                        limit_conn_zone $server_name zone=perserver:10m;
                                                                        limit_conn perip 2;
                                                                        limit_conn perserver 20;
                                                                        limit_rate 300k; 
                                                                proxy_cache_path /data/nginx-cache levels=1:2 keys_zone=nginx-cache:20m max_size=50g inactive=168h;
                                                                        
                                                                        client_body_buffer_size 512k;
                                                                        client_header_buffer_size 4k;
                                                                        client_max_body_size 512k;
                                                                        large_client_header_buffers 2 8k;
                                                                        proxy_connect_timeout 5s;
                                                                        proxy_send_timeout 120s;
                                                                        proxy_read_timeout 120s;
                                                                        proxy_buffer_size 16k;
                                                                        proxy_buffers 4 64k;
                                                                        proxy_busy_buffers_size 128k;
                                                                        proxy_temp_file_write_size 128k;
                                                                        proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
                                                                        
                                                                        gzip on;
                                                                        gzip_min_length 1k;
                                                                        gzip_buffers 4 16k;
                                                                        gzip_http_version 1.1;
                                                                        gzip_comp_level 4;
                                                                        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
                                                                        gzip_vary on;
                                                                        gzip_disable "MSIE [1-6].";
                                                                 
                                                                    include /etc/nginx/conf.d/*.conf;
                                                                }
                                                                

                                                                负载均衡

                                                                upstream ygoapi{ 
                                                                  server ip:port fail_timeout=5 max_fails=3;
                                                                  server ip:port fail_timeout=5 max_fails=3;
                                                                  ip_hash;  #负载均衡策略
                                                                }
                                                                

                                                                server配置

                                                                #隐藏版本信息
                                                                server_tokens off;
                                                                server {
                                                                    listen       80;
                                                                    server_name  www.ygoclub.com;
                                                                    charset utf-8;
                                                                	
                                                                	#重定向HTTP请求到HTTPS
                                                                	return 301 https://$server_name$request_uri;
                                                                }
                                                                

                                                                HTTPS配置(ssl配置)

                                                                这里主要是配置ssl证书

                                                                在nginx服务的目录下创建cert

                                                                server {
                                                                    listen 443;
                                                                    server_name 域名;
                                                                    ssl on;
                                                                    root /xxx/xxx/html; // 前台文件存放文件夹,一般使用 Nginx 初始化的文件夹,当然也可以自己修改
                                                                    index index.html;// 上面配置的文件夹里面的index.html
                                                                    ssl_certificate /路径/证书名称.pem;
                                                                    ssl_certificate_key /路径/证书名称.key;
                                                                    ssl_session_timeout 5m;
                                                                    # SSL协议配置
                                                                    ssl_protocols SSLv2 SSLv3 TLSv1.2; #表示使用TLS类型协议
                                                                    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; #表示使用加密套件的类型
                                                                    ssl_prefer_server_ciphers on;
                                                                        location / {
                                                                            proxy_redirect off;
                                                                            proxy_set_header Host $host;
                                                                            proxy_set_header X-Real-IP $remote_addr;
                                                                            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                                                            proxy_pass http://127.0.0.1:8080;
                                                                        }
                                                                }			   
                                                                }
                                                                 
                                                                server {
                                                                    listen 80;
                                                                    server_name your-domain.com;// 你的域名
                                                                    rewrite ^(.*)$ https://$host:443$1 permanent;// 把http的域名请求转成https且转发到443端口
                                                                }