nginx缓冲区排坑

问题回顾

近日,我们一个版本的分支上了预发,一个订单查询接口总是报错,后端服务器日志大概如下

一开始排查问题的方向肯定是后端出错了,但是看这个完整的异常栈,出错报在框架层,和业务代码无关,怀疑的方向就是后端数据量太大

然后通过抓包,发现每次前端报错的时候,那个http返回报文中body里的json被截断了,只有一部分,这时候就有点怀疑nginx了,毕竟这个请求是nginx代理请求的,极有可能nginx哪里配置出错了

那么就进服务器看nginx error日志,看到了如下日志

把/usr/local/nginx目录的权限设置为nginx,让nginx进程能够访问就行了,返回报文被截断的情况就再也没发生了,疯狂吐槽的App开发哥们终于能够测试了。

这个问题阻碍测试接近1天,调查问题进度也没上面写的那么顺风顺水,我觉得遇到问题首先要合理分析出问题出在哪里,问题的初期其实我经过百度,其实和运维提过排查下nginx日志这个虽然加错了,凡是方向对了,如果看了nginx日志,应该能立刻解决问题,但是没有看,我也没那台服务器权限第二天,我们抓包了,发现返回被截断,我更加怀疑nginx的问题

嗯,这次对了

一个小小的点,阻碍了这么多时间,这么多人力,可见细节决定成败,以及经验的重要性

所以以后遇到问题

合理分析问题原因

看日志,看日志,看日志

团队合作

出现这个问题的原因就是nginx对它的缓冲区目录没有权限,下面我们就来学习下这个缓冲区

缓冲区的作用

缓冲区的作用,就是为了协调客户端到nginx以及nginx到服务器的速度不同。如果这两条链路都非常快,那么没有缓冲区的事了。如果客户端到nginx速度快,nginx到服务器速度慢,没有缓冲区,一点点数据量就直接发到客户端,十分浪费性能。有了缓冲区,积累到一定量,再传输到客户端,减少了Tcp请求。相反,客户端到nginx速度慢,nginx到服务器速度快,没有缓冲区,nginx到服务器的连接就会一直保持在那边,直到客户端接受完毕。有了缓冲区,返回内容放到缓冲区后,nginx到服务器的连接就能断开了,客户端从缓冲区拉取即可。

缓冲区这个概念在很多地方都用到,你想到了那些地方?IO?MQ?

nginx缓冲区配置

nginx缓冲区的配置主要在location模块下面,主要配置参数如下

proxybuffersize

后端服务器的相应头会放到proxybuffersize当中,这个大小默认等于proxybuffers当中的设置单个缓冲区的大小。 proxybuffersize只是响应头的缓冲区,没有必要也跟着设置太大。 proxybuffer_size最好单独设置,一般设置个4k就够了。

proxy_buffers

proxybuffers的缓冲区大小一般会设置的比较大,以应付大网页。 proxybuffers当中单个缓冲区的大小是由系统的内存页面大小决定的,Linux系统中一般为4k。 proxy_buffers由缓冲区数量和缓冲区大小组成的。总的大小为number*size。

若某些请求的响应过大,则超过buffers的部分将被缓冲到硬盘(缓冲目录由temppath指令指定), 当然这将会使读取响应的速度减慢, 影响用户体验. 可以使用proxymaxtempfile_size指令关闭磁盘缓冲.

proxybusybuffers_size

proxybusybufferssize不是独立的空间,他是proxybuffers和proxybuffersize的一部分。nginx会在没有完全读完后端响应的时候就开始向客户端传送数据,所以它会划出一部分缓冲区来专门向客户端传送数据(这部分的大小是由proxybusybufferssize来控制的,建议为proxybuffers中单个缓冲区大小的2倍),然后它继续从后端取数据,缓冲区满了之后就写到磁盘的临时文件中。

proxymaxtempfilesize和proxytempfilewritesize

临时文件由proxymaxtempfilesize和proxytempfilewritesize这两个指令决定。 proxytempfilewritesize是一次访问能写入的临时文件的大小,默认是proxybuffersize和proxy_buffers中设置的缓冲区大小的2倍,Linux下一般是8k。

proxymaxtempfilesize指定当响应内容大于proxy_buffers指定的缓冲区时, 写入硬盘的临时文件的大小. 如果超过了这个值, Nginx将与Proxy服务器同步的传递内容, 而不再缓冲到硬盘. 设置为0时, 则直接关闭硬盘缓冲.

缓冲区分为内存和文件两部分,不可能所有Response都在内存中缓冲,毕竟需要用内存去建立更多连接,所以超过一定的量会刷到磁盘,我们出现的问题就是刷到磁盘这一步被权限阻碍了,导致客户端拿到的部分报文是内存中的

但是我们的Response并不是全部被截断,百分之60的Response是正常的,我猜测要么是这些Response没有超过缓冲区大小,要么写的缓冲目录部分存在权限

注意下上面的默认配置,缓冲区是默认开启的

nginx缓冲区使用

默认的配置应该够用,也可以根据应用平均的Response大小做优化,毕竟直接走内存肯定要比走IO快

最后

看到这里的观众,关注吧,关于技术的一切我都有可能分享

还有参考的文章https://www.cnblogs.com/me115/p/5698787.htmlhttps://www.cnblogs.com/bethal/p/5606062.htmlhttps://nginx.org/en/docs/http/ngxhttpproxymodule.html#proxytempfilewrite_size

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180719G02MRF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券