(更新:它与文件上传无关,底部有更多详细信息)
我在 jre-1.7.0-openjdk.x86_64 上运行 jetty-distribution-9.0.6.v20130930 服务器,在 EC2 linux <上运行< / strong>服务器。它是移动应用程序的后端,每天接收大约5万个请求。
大约每天一次,线程挂起100%CPU,直到我杀了它(在100%CPU上运行几个小时后)。
JavaMelody显示挂起线程的以下调用堆栈:
Jetty HTTP连接器定义,来自etc / jetty-https.xml:
<Call id="httpsConnector" name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg name="server"><Ref refid="Server" /></Arg>
<Arg name="factories">
<Array type="org.eclipse.jetty.server.ConnectionFactory">
<Item>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
<Arg name="next">http/1.1</Arg>
<Arg name="sslContextFactory"><Ref refid="sslContextFactory"/></Arg>
</New>
</Item>
<Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config"><Ref refid="sslHttpConfig"/></Arg>
</New>
</Item>
</Array>
</Arg>
<Set name="host"><Property name="jetty.host" /></Set>
<Set name="port"><Property name="jetty.https.port" default="8443" /></Set>
<Set name="idleTimeout">30000</Set>
</New>
</Arg>
</Call>
Jetty HTTPS配置,来自start.ini:
jetty.https.port=8443
etc/jetty-https.xml
JVM版本 -
java version "1.7.0_45"
OpenJDK Runtime Environment (amzn-2.4.3.2.32.amzn1-x86_64 u45-b15)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)
一
问题
是什么原因引起的?
为什么没有触发超时来杀死这些悬挂的线程?
如何启用此类方案的超时?
更新
原来它与文件上传无关,有时也会在不同的EC2服务器(相同配置)中发生,有时两个实例在完全相同的时间挂起,同样调用堆栈。
其他服务器没有实现文件上传,因此排除了此选项。
答案 0 :(得分:2)
您已配置30秒超时,并且正在从移动设备进行Mime /文件上传。
感觉卡住线程。由于您正在使用移动客户端和servlet 3.0,因此您应该考虑放弃使用Apache Commons File Upload并使用默认的Servlet 3.0 HttpServletRequest.getParts()逻辑。这将允许Jetty本身使用各种可用的异步I / O技术来管理缓慢或有问题的客户端(这在移动客户端及其移动网络中非常常见)。
Apache Commons文件上传使用旧技术,要求服务器切换到阻塞模式I / O,对于慢速客户端而言,这意味着阻塞I / O行为会导致长时间的选择器旋转,并且从不会出现涓涓细流的字节实际上跳过空闲超时(从技术上讲,连接不是空闲,仍有流量,但速度极慢)
您的选择:
POST
切换文件上传(以及您不需要的所有相关mime multipart/form-data
废话) PUT
带文件上传(这是一种更简单的请求内容类型)只是为了避免Apache Commons File-Upload层。当然,这需要App更新。答案 1 :(得分:0)
升级到 Jetty 9.3 和 Java 8 后,我的问题在两台服务器中得到了解决。
直到那时,两台服务器(有两个不同的网络应用程序)几乎每天都在下午6:00-7:00发生这种情况,这些是传入流量的选择时间。
<强>更新强>
原因是一连串已打开的数据库连接耗尽了连接池,导致服务器中的某些线程挂起。
因此它与上传无关,但它可能是挂起线程而不是拒绝新连接的Jetty或Java错误。
这解释了为什么它发生在两个不同的服务器上,它们都连接到同一个RD2实例,该实例耗尽了它的连接池。