我们在三个相同的WebLogic服务器上部署了一个Peoplesoft应用程序。 Netscaler设备在它们之间进行负载平衡并保持会话的粘性。交付的Peoplesoft ear应用程序由Oracle交付,未经我们任何方式定制。
三个Web服务器之一显示ConcurrentModificationExceptions。我们在企业中的许多其他服务器上部署了相同的耳朵,但这是唯一遇到此问题的服务器。这个问题是如此严重,以至于我们不得不使服务器停机并脱离服务器场。因此,现在我们在原始3台服务器中的2台上进行负载平衡。
作为Oracle的客户,我们无权访问任何源代码。这使得很难缩小问题的范围。
由于此耳朵与运行正常的服务器上的耳朵完全相同,所以我认为“差异”一定是引起问题的耳朵之外的东西。
这是我想出的:
当应用程序试图从JOLT连接池中获取线程时,发生异常。该池由一个Java链表对象管理。该线程尝试遍历链接列表,以查找可用的连接来连接到App Server。 (背景:Peoplesoft的耳朵(部署在WebLogic App Server中)使用JOLT连接到另一层(由C ++和Java代码组成的应用程序,它们通过Tuxedo控制的IPC对象(例如队列,共享内存...)进行通信。为提高效率而进行池化。在从池分配连接之前,该线程失败。另一个线程(我认为)在链表上进行迭代,然后导致ConcurrentModificationException。
某些线程能够从缓冲池成功获取连接,但是当流量增加时,会发生ConcurrentModificationException的可能性。
[当我说我检查了某件事时,我的意思是我将它们与服务器上相同的项目进行了比较,没有问题
我已经检查了很多东西以寻找原因:
我对要检查的内容没有足够的想法。
java.util.ConcurrentModificationException java.util.ConcurrentModificationException<br>^M
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:977)^M
at java.util.LinkedList$ListItr.next(LinkedList.java:899)^M
at psft.pt8.net.JoltSessionPool.getJoltSession(JoltSessionPool.java:276)^M
at psft.pt8.net.NetSession.getJoltSession(NetSession.java:693)^M
at psft.pt8.net.NetReqRepSvc.sendRequest(NetReqRepSvc.java:556)^M
at psft.pt8.net.NetService.requestService(NetService.java:167)^M
at psft.pt8.net.NetReqRepSvc.requestService(NetReqRepSvc.java:354)^M
at psft.pt8.jb.JBEntry.processRequest(JBEntry.java:673)^M
at psft.pt8.psc.onActionGen(psc.java:3045)^M
at psft.pt8.psc.onAction(psc.java:1753)^M
at psft.pt8.psc.onAction(psc.java:1742)^M
at psft.pt8.psc.service(psc.java:963)^M
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)^M
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)^M
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)^M
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)^M
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)^M
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)^M
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)^M
at weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilter.java:274)^M
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)^M
at psft.pt8.psfilter.doFilter(psfilter.java:88)^M
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)^M
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3706)^M
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3672)^M
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:328)^M
at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197)^M
at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203)^M
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71)^M
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2443)^M
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2291)^M
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2269)^M
at weblogic.servlet.internal.ServletRequestImpl.runInternal(ServletRequestImpl.java:1705)^M
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1665)^M
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:272)^M
at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:352)^M
at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:337)^M
at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:57)^M
at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41)^M
什么,在Java耳朵之外可能会影响此?
ConcurrentModificationException几乎总是编码错误。该代码没有为运行中的多个线程准备,或者存在缺陷。不幸的是,这可能是随机发生的,例如当两个线程试图同时修改资源时。另一种情况是单线程使用快速失败迭代器修改当前正在迭代的资源。第二种情况将可预测地发生。
另一个线程(我假设)遍历链表,然后导致ConcurrentModificationException。
另一个线程可能必须通过添加或删除元素来修改链表。这是一个编码疏忽。
psft.pt8.net.JoltSessionPool.getJoltSession(JoltSessionPool.java:276)
线程安全。为什么会在一台特定的服务器上发生?
如果是负载均衡的,请考虑服务器是否由于其相对于Web服务用户的物理位置而承担了大部分负载。更多的活动将增加线程竞争的机会。
夫妇:
我对要检查的内容没有足够的想法。
服务器硬件如何。是否有可能是服务器内存较少,CPU数量较少或较慢而导致负载不同的交互?
如果它从不在其他服务器上发生,则说明非常错误。您是否有办法将硬盘从工作中的服务器复制到损坏的服务器上?在我看来,这存在某种配置差异或某些差异。
另一个线程(我假设)在LinkedList上进行迭代,然后导致ConcurrentModificationException。
实际上,两个线程在相同的LinkedList
上进行迭代是很好的。不好的是,如果在线程对其进行迭代时列表发生了变化。实际上,对于单线程应用程序来说,查看CME通常是more。在可能导致迭代抛出的情况下,线程可以从列表中删除某些内容。
作为一个hack,根据您的绝望程度,您可以在类路径上提供一个不同的LinkedList
类并对其进行检测,甚至对其添加锁以了解甚至防御该问题。