最近项目上线配置nginx遇到一个问题,试了几乎全部的方法,最终解决,在这里记录一下心得。
nginx error.log日志输出报错信息:upstream timed out (110: Connection timed out) while reading response header from upstream, client: 36.110.27.18, server: yqxc.folkspace.cn, request: "POST /api/v1/user/login/BySms HTTP/2.0", upstream: "http://127.0.0.1:8080/api/v1/user/login/BySms", host: "test.myweb.com"
首先这个报错不是接口大批量报错,而是偶尔一个接口报错,发生在我服务器的保错接口是发送腾讯云短信报错,前端响应504 getway time out,短信并不是没有发送成功,而是会延迟四到五个小时才会发送成功,导致排查错误被引导其他方向。
这个错误的大概意思是 获取上游服务器的返回值超时,也就是等待响应时间太长了,那按照这个意思那我把超时时间设置长一点,是否可以解决问题呢,所以试了第一步,改变proxy的时间,重新加载nginx,并没有解决问题,
解决过程:
因为是java项目所以和php相关的参数可以忽略,并不会影响到我的项目。
第一步:
关于proxy的配置:
proxy_temp_path /etc/nginx/proxy_temp_dir; # 临时文件目录
proxy_cache_path /etc/nginx/proxy_cache_dir levels=1:2 keys_zone=cache_one:20m inactive=1d max_size=5g; #缓存区大小和缓存时间
client_body_buffer_size 512k;
proxy_connect_timeout 600; #连接超时时间 默认60s
proxy_read_timeout 600;#后端处理请求时间 默认60s
proxy_send_timeout 600;#后端服务数据回传时间 默认60s
proxy_buffer_size 32k; #缓冲区大小
proxy_buffers 4 64k; #缓冲区数目和大小
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;#写入临时文件的数据大小
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
proxy_cache cache_one;
其中网上的关于连接超时的更改方式都是改大连接时间,这个并没有解决我的问题。
第二步:既然没有解决问题,那第二步就是从业务考虑,毕竟是这一个接口单独报错,那也许是腾讯云的问题,在腾讯云api explorer测试了是可以发送短信的,说明也不是这个问题,那只能从其他方面考虑了。
在linux 执行 ps -ef | grep java 查看java进程,jstack -l <pid进程id> 查看线程使用情况,是否为线程占用问题,仔细看了一下日志,有几个线程的状态是 java.lang.Thread.State:RUNABLE ,看详细日志终于找到了报错的地方,定位到问题所在,是代码的原因。
这句代码导致整个线程处于阻塞状态,无法返回结果。
Random random = SecureRandom.getInstanceStrong();
为什么会用这个代码呢? 项目在要上线的时候使用了 sonar扫描了代码漏洞,检测到使用Random随机函数不安全,new Random();不推荐使用,推荐使用SecureRandom.getInstanceStrong();替换,没有考虑是否会存在隐患,直接替换,最终在调用next方法的时候在linux服务器产生较长时间的阻塞。
如果遇到同类型问题,推荐使用 new SecureRandom()创建Random,无参构造函数默认算法SHA1PRNG。
到此问题解决。
后面会测试一下为什么使用SecureRandom,它的安全性在哪里。
有些问题并不是表面日志信息可以解决的,这个时候要换一种思路,或者想方设法获取到其他信息,从而了解具体的bug发生地,从根源解决问题。