有两台服务器,一台上运行着PHP服务,另一台运行Java服务。两台服务器之间通过HTTP进行接口调用。查看Java服务端的日志发现,有很多往PHP服务的HTTP请求都超时。
于是在PHP服务器端用 netstat
命令查看了一下网络套接字连接情况。
命令 netstat -atp
运行结果:
1 | ... |
发现大量的端口处于TIME_WAIT状态,而且都是与mysql连接相关.
运行命令 netstat -at | grep 'mysql' | awk '{print $6}' | sort | uniq -c
。发现有差不多3000个端口处于TIME_WAIT。看来PHP服务打开的MySQL连接还真多。鉴于自己对PHP开发不了解,只是直觉上感觉打开这么多MySQL连接会影响服务性能。接下来主要想看一下HTTP调用的端口情况。用netstat检查发现端口连接不多,于是打算抓一下http端口的数据包看看。用tcpdump抓包,wireshark分析没有发现问题。然后又在Java服务端抓取双方通信的数据包,分析也没看出问题。It’s so strange!!!
既然日志是Java服务报出来的,看来应该在Java服务上去找原因。查看了Java服务的代码,发现Java服务中使用了Vertx框架中的HttpClient来进行Http请求。HttpClient配置如下:
1 | { |
当keepAlive设置为true的时候,HttpClient会重用建立的连接进行HTTP请求。idleTimeout参数控制连接空闲时间,当空闲时间达到idleTimout,该连接会被关闭。maxPoolSize指定了最大的连接数,当连接数没有达到maxPoolSize时,HttpClient会为新的请求新建连接,当达到maxPoolSize,HttpClient不再新建连接,而是把请求放进等待队列,等待队列的大小由maxWaitQueueSize来指定。connectTimeOut指定了连接超时时间。从日志看到的超时并不是连接超时。而是请求超时,请求超时是在HttpClientRequest里设置的。当一个请求达到设置的timeout且没有返回任何数据,就会一个java.util.concurrent.TimeoutException
传递给异常处理方法。
通过运行命令netstat -at | grep -E '172.19.126.49' -c
发现当前连接已经达到了50,也就是达到了maxPoolSize的设置。
统计Java服务发起的请求,1秒钟有差不多接近三千个请求。
综合上述信息,问题还是出现在PHP服务,PHP服务提供的HTTP接口处理速度不够快,导致Java服务端产生大量的HTTP请求堆积超时。而且从PHP服务端一开始发现的大量MySQL连接也证实了PHP服务提供的接口实现会去直接访问数据库,没有采用缓存之类的操作,导致接口更慢。看来还得找PHP研发打架去。。。