SpringCloud部署的坑之feign转发导致nginx502

起因

公司上线一个新的项目, 业务层使用了spring cloud, 本地调试都好好的, 但是却在部署上服务端, 加了一层nginx后; 发现请求没响应; 但奇怪的是, 并不是所有的api请求都是没响应, 有部分可行;

排查

1.首先查看下有响应的和无响应的代码有何不同, 发现有响应的都是比较简单的接口, 没有经过服务间调用的, 而无响应的那些, 都是需要请求多个服务来进行了, 我们使用的是spring cloud的feign组件, 那是不是这部分的坑呢? 导致请求不通呢?
2.但是查看日志, 所有服务的记录都是有返回的, 并且如果使用ip加端口, 不经过nginx的话, 那就可以得到正常的响应; 难道这个锅要nginx来背?

nginx排查

1.首先请求下经过nginx代理的服务; 果不其然得不到回应, 客户端请求抛504, 然后查看nginx日志, 查看/var/log/nginx/error.log, 可以发现有这样的日志

1
*132 upstream sent invalid chunked response while reading upstream, client: xx.xx.xx.xxx, server:

2.从描述上看, 就是说服务请求没有返回数据, 于是关闭连接; 于是google一下, 发现这种情况大多是因为配置回传时间过短,导致nginx断开这部分连接; 于是加了下面的配置;

1
2
3
4
5
6
#表示与后端服务器连接的超时时间,即发起握手等候响应的超时时间。一般建议不要超过75s,默认时间60s。
proxy_connect_timeout 90;
#表示后端服务器的数据回传时间,即在规定时间之内后端服务器必须传完所有的数据,否则,Nginx将断开这个连接。默认时间60s。
proxy_send_timeout 90;
#设置Nginx从代理的后端服务器获取信息的时间,表示连接建立成功后,Nginx等待后端服务器的响应时间,其实是Nginx已经进入后端的排队之中等候处理的时间。默认时间60s。
proxy_read_timeout 90;

3.心想, 这下行了吧, 于是自信reload, 然后再自信访问, 可是得到的还是无响应, 错误依旧, 那么还有另外一种想法, 缓存区太小, 导致nginx关闭了整个response,于是再次自信加下配置:

1
2
3
4
5
6
#设置缓冲区大小,默认该缓冲区大小等于指令proxy_buffers设置的大小。
proxy_buffer_size 4k;
#设置缓冲区的数量和大小。Nginx从代理的后端服务器获取的响应信息,会放置到缓冲区。
proxy_buffers 4 32k;
#用于设置系统很忙时可以使用的 proxy_buffers 大小, 官方推荐的大小为 proxy_buffers*2。
proxy_busy_buffers_size 64k;

4.可惜reload后依旧打脸, 不行的还是不行, 这个时候就有点怀疑人生了;
5.再次google加百度, 得到的基本上都是上面的答案, 并没有其他信息;
6.就这样过了一天, 然后在翻阅资料的时候, 发现了一个点, 就是nginx使用了http1.0协议从后端返回响应体的, 但是http1.0不支持keeplive, 因此需要配置

1
2
proxy_http_version 1.1; 
proxy_set_header Connection "";

来开启http1.1的支持;
7.立马试了一下, 果然可行, 返回就正常了;

原因

1.一开始请求那些有响应的, 是因为并没有经过中转, 一下子就有了响应, 因此用http1.0中转就没有什么问题;
2.可是如果立马有经过了中转, 就会导致产生一个新的连接, 而原有的连接并没有返回一个响应, 所以就出了这种现象;

反思

都9102年了, 除非是很老的服务或者无法支持的, http请求还是默认要配上http1.1协议的, 如果有开了https的话, 都尽量上了http2.0

一篇类似的文章

一次nginx引起的线上502故障

hyhcoder wechat
扫码关注我的个人订阅号