Jetty在sun.nio.ch.FileDispatcherImpl.read0(本机方法)上挂起100%CPU

时间:2013-12-04 15:20:13

标签: http file-upload amazon-ec2 request jetty

(更新:它与文件上传无关,底部有更多详细信息)

我在 jre-1.7.0-openjdk.x86_64 上运行 jetty-distribution-9.0.6.v20130930 服务器,在 EC2 linux <上运行< / strong>服务器。它是移动应用程序的后端,每天接收大约5万个请求。

大约每天一次,线程挂起100%CPU,直到我杀了它(在100%CPU上运行几个小时后)。

JavaMelody显示挂起线程的以下调用堆栈:

enter image description here

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)

问题

  1. 是什么原因引起的?

  2. 为什么没有触发超时来杀死这些悬挂的线程?

  3. 如何启用此类方案的超时?

  4. 更新

    原来它与文件上传无关,有时也会在不同的EC2服务器(相同配置)中发生,有时两个实例在完全相同的时间挂起,同样调用堆栈。

    其他服务器没有实现文件上传,因此排除了此选项。

2 个答案:

答案 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行为会导致长时间的选择器旋转,并且从不会出现涓涓细流的字节实际上跳过空闲超时(从技术上讲,连接不是空闲,仍有流量,但速度极慢)

您的选择:

  1. 由于您说这是一个移动应用程序(而不是移动浏览器),因此请从POST切换文件上传(以及您不需要的所有相关mime multipart/form-data废话) PUT带文件上传(这是一种更简单的请求内容类型)只是为了避免Apache Commons File-Upload层。当然,这需要App更新。
  2. 升级和/或重新配置服务器端实现,以使用Servlet 3.0(适用于Jetty 9.0.6)或Servlet 3.1(适用于Jetty 9.1.0)标准技术来处理请求多部分内容,目标是消除Apache Commons文件上传库。这将只是服务器端更新。
  3. 在文件上传servlet前面添加一个过滤器,指定请求应该占用多长时间的总体上限,如果时间过长则终止连接。
  4. 完全改变你从应用程序上传文件的方式,不要使用POST,对性能设置下限,如果上传时间过长,失败,通知用户,给他们一个选项来推迟上传在wifi等等(有些应用程序甚至有上传内容的配置选项,如“在手机或wifi上”与“只在wifi上”)

答案 1 :(得分:0)

升级到 Jetty 9.3 Java 8 后,我的问题在两台服务器中得到了解决。

直到那时,两台服务器(有两个不同的网络应用程序)几乎每天都在下午6:00-7:00发生这种情况,这些是传入流量的选择时间。

<强>更新

原因是一连串已打开的数据库连接耗尽了连接池,导致服务器中的某些线程挂起。

因此它与上传无关,但它可能是挂起线程而不是拒绝新连接的Jetty或Java错误。

这解释了为什么它发生在两个不同的服务器上,它们都连接到同一个RD2实例,该实例耗尽了它的连接池。