线程在读取Zip文件时被阻止

时间:2017-11-01 16:48:13

标签: java multithreading jar jetty thread-dump

我们的Java巨石存在生产问题。用户抱怨缓慢和网站无法使用。线程转储显示在下面的线程获得的锁上有大约400个线程被阻塞。

所有这些被阻止的线程都具有与阻塞线程(+ - 1最后一帧)几乎相同的堆栈跟踪 - 尝试从应用程序JAR文件加载VAADIN资源文件。

这是否意味着线程在从JAR读取静态文件时被绞死?还有其他人正在等待一个帖子完成阅读吗?

任何人都知道为什么会这样,我们怎么能阻止这种情况?

Java版本:1.8.0_131

Jetty版本:9.2.z-SNAPSHOT

"qtp489279267-42356" #42356 prio=5 os_prio=0 tid=0x00007fe7e4054800 nid=0x6f37 waiting for monitor entry [0x00007fe776831000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.util.zip.ZipFile$ZipEntryIterator.hasNext(ZipFile.java:492)
    - waiting to lock <0x0000000700002e80> (a sun.net.www.protocol.jar.URLJarFile)
    at java.util.zip.ZipFile$ZipEntryIterator.hasMoreElements(ZipFile.java:488)
    at java.util.jar.JarFile$JarEntryIterator.hasNext(JarFile.java:253)
    at java.util.jar.JarFile$JarEntryIterator.hasMoreElements(JarFile.java:262)
    at org.eclipse.jetty.util.resource.JarFileResource.exists(JarFileResource.java:191)
    at org.eclipse.jetty.webapp.WebAppContext.getResource(WebAppContext.java:372)
    at org.eclipse.jetty.webapp.WebAppContext$Context.getResource(WebAppContext.java:1459)
    at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.serveStaticResourcesInVAADIN(AbstractApplicationServlet.java:1276)
    at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.serveStaticResources(AbstractApplicationServlet.java:1246)
    at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:423)
    at example.ApplicationServlet.service(ApplicationServlet.java:37)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:499)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:748)

1 个答案:

答案 0 :(得分:0)

你可能猜对了,你似乎面临着争论。

我们可以从两个相关的角度来看待它:

  1. 锁定争用
  2. 它可能不适用于当前的用例,但也可能是负载下的生产系统中的问题:I / O争用。
  3. 我们到目前为止从堆栈跟踪中出现的症状似乎是锁争用。

    您似乎在同时阅读的多个读者之间共享相同的文件(在Java ZipFile对象的意义上)。这带来了缓存的想法 - 尽管根据您的使用情况考虑它可能完全错误,例如:如果您读取的文件大小超过1千兆字节。

    因此,了解

    会很有用
    1. 您可以阅读的文件总数;
    2. 这些文件的中位数和最大尺寸;
    3. 这些文件的平均TTL,即一旦加载到内存中需要多长时间;
    4. 如果我们在任何给定的时间段内都有合理数量的数据要缓存(即我们不会遇到来自客户的需求激增,这将使我们需要在几秒钟内获取1 TB的新数据)并管理一个相对较小的&#34; ad-hoc软件系统,一个简单的解决方案就是缓存。