分布式系统架构:技术栈详解与快速进阶
上QQ阅读APP看书,第一时间看更新

4.8.2 核心配置优化

4.3节中的Nginx配置可进行的优化如下。

1)worker_processes:表示worker进程数量。worker_processes默认情况下为1,官方的建议是修改成CPU的内核数,增加worker_processes数量,充分利用I/O带宽,以减小机器I/O带来的影响。

服务器A 2C/4G,测试运行结果如下:

  • 设置worker_processes=1,打开2个线程,其中有一个是主线程,运行很稳定;
  • 设置worker_processes=2,打开3个线程,其中有一个是主线程,运行相对较稳,高并发请求时会出现502的错误;
  • 设置worker_processes=4,打开5个线程,其中有一个是主线程,运行很稳定。

2)worker_connections:表示work进程连接数量,默认是1024。worker_connections优化需要考量两个指标,即内存和操作系统级别的“进程最大可打开文件数”。建议设置到65535,可根据内存自行调整。

  • 内存:每个连接数分别对应一个read_event、一个write_event事件。一个连接数大概占用232B,2个事件共占用96B,所以一个连接总共占用328B。100W连接大概占用100W*328/1024/1024~=310MB。
  • 进程最大可打开文件数:受限于操作系统,通过ulimit -n命令可查询,默认是1024,建议设置为65535。

3)keepalive_timeout:表示KeepAlive的超时时间,指定每个TCP连接最多可以保持多长时间。Nginx的默认值是75秒。

【示例】 以电商网站上传附件功能为例,客户端使用Nginx反向代理。

对于电商后台管理模块来说,运营人员每天会定时上传商品的附件,有时上传的附件较大,需要等待很久服务器才响应,有时候超过默认值后会提示“超时”等现象。经日志分析请求发现,超时等问题和Nginx的keepalive_timeout配置项相关。页面请求后端采用HTTP方式。由于HTTP底层采用TCP协议网络传输,故当上传附件时页面会向服务端发送一个请求,由于附件过大,上传处理时间超过了TCP连接最多可以保持时间,从而导致“超时”等异常。

评估附件上传的平均时长后,更改keepalive_timeout默认配置项,将其调整到500,运行过程中不再出现“超时”等现象。在后续运行过程中,发现批量上传的视频数量较多时,会出现部分视频上传失败的问题,日志提示“socket() failed (24: Too many open files) while connecting to upstream”。分析可知,是连接数不够,于是调制worker_connections默认连接数到8729。之后批量上传视频时,在视频的大小均衡且总数量偏小的情况下功能正常。但当出现视频大小不均衡并且总数量偏大情况,部分视频还会上传失败。

继续分析日志,发现由于keepalive_timeout设置过长,在上传视频时,有些请求传输的过程会很快执行完毕,如果超时时间设置过长,因处理完毕的请求连接没有被释放掉,所以会导致请求过多积累后会出现异常。

那么如何合理设置keepalive_timeout的时间呢?

优化思路:在存在一些业务功能比较耗时的情况下,可以优化程序,比如采用同步转异步、多线程等优化手段,这样可提高应用程序整体的执行效率,减少响应时间。不要因为业务功能而牺牲其他网络、系统、代理相关的服务,由于部分浏览器仅支持最多保持在60s左右,所以把keepalive_timeout调整到60s左右比较合理,如keepalive_timeout 60。

4)gzip:表示Nginx采用Gzip压缩的形式发送数据。这将减少我们发送的数据量,建议开启该功能,即gzip on。

5)gzip_proxied:允许或者禁止压缩基于请求和响应的响应流。比如,gzip_proxied any表示压缩所有的请求。

6)gzip_min_length:表示数据启用压缩的最少字节数,建议请求大于1KB及以上时进行压缩,如gzip_min_length 1000。压缩过小的数据会降低处理此请求的所有进程的速度。

7)gzip_comp_level:表示开启Gzip压缩。Gzip的压缩参数值的范围是1到9,那么,将其设置为多少合适呢?

【示例】 静态文件包括4个H5文件、4个JS、2个CSS文件,合计大小为380KB,设置gzip_comp_level参数从1到9的结果如下:

  • gzip_comp_level=1,资源文件大小为160KB;
  • gzip_comp_level=2,资源文件大小为150KB;
  • gzip_comp_level=3,资源文件大小为142KB;
  • gzip_comp_level=4,资源文件大小为127KB;
  • gzip_comp_level=5,资源文件大小为119KB;
  • gzip_comp_level=6,资源文件大小为102KB;
  • gzip_comp_level=7,资源文件大小为102KB;
  • gzip_comp_level=8,资源文件大小为97KB;
  • gzip_comp_level=9,资源文件大小为97KB。

随着压缩比例升高,CPU消耗也不断升高,正常虚拟机2C/4G建议设置为4,4C/8G建设设置为5。建议根据服务器的配置取值4或5即可。

8)gzip_type:设置需要压缩的数据格式。如gzip_type text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript。

9)access_log:设置Nginx是否存储访问日志。如有其他日志记录,建议关闭这个选项,这样可以有效让读取磁盘的I/O操作执行得更快,如access_log off。

10)sendfile:表示是否使用sendfile来传输文件,若使用,可实现在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免数据在内核缓冲区和用户缓冲区之间的重复拷贝,提高操作效率,被称为零拷贝。建议开启,即sendfile on。

11)tcp_nopush:表示Nginx在一个数据包里发送所有头文件,而不是一个接一个地发送。建议开启,即tcp_nopush on。

12)tcp_nodelay:表示Nginx不要缓存数据,而是一段一段地发送。当需要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能立即得到返回值。建议开启,即tcp_nodelay on。

13)reset_timeout_connection:关闭不响应的客户端连接,释放客户端占有的内存空间。

14)client_header_buffer_size:表示为请求头分配一个缓冲区,这样能减少一次内存分配。当大部分请求头很大时,建议设置client_header_buffer_size。

15)large_client_header_buffers:表示请求中只有少量请求头很大,仅需在处理大头部时分配更多的空间,从而减少无谓的内存浪费。

16)client_body_buffer_size:表示处理客户端请求体buffer的大小。设置缓冲区buffer大小,可用来处理POST请求数据、上传文件。缓冲区过小会导致Nginx把内容写到磁盘,使用临时文件存储response,会引起磁盘读写I/O。