【问题标题】:EclipseLink concurrency exceptionEclipseLink 并发异常
【发布时间】:2017-03-17 15:36:10
【问题描述】:

在 glassfish 服务器无响应后查看一些日志时,我遇到了这个错误:

{{[#|2016-06-02T08:37:51.737+0200|WARNING|oracle-
glassfish3.1.2|org.restlet.Component.ServiceDispatcher|_ThreadID=165;_ThreadName=http-thread-pool-37860(5);|Exception or error caught in status service
javax.ejb.EJBException
at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:5236)
at com.sun.ejb.containers.BaseContainer.checkExceptionNoTx(BaseContainer.java:5065)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4900)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2046)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1995)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
at com.sun.proxy.$Proxy228.getKpiValuesFlat(Unknown Source)
at com.business.renderer.TopSuppliers.getData(TopSuppliers.java:174)
at com.business.renderer.TopSuppliers.getDataAsJSONTopSuppliers.java:179)
at com.business.renderer.TopSuppliers.render(TopSuppliers.java:107)
at com.ui.renderer.engine.AbstractRenderingEngine.render(AbstractRenderingEngine.java:140)
at com.services.filter.ContainerAdapter.represent(ContainerAdapter.java:311)
at org.restlet.resource.Resource.getRepresentation(Resource.java:259)
at org.restlet.resource.Resource.handleGet(Resource.java:425)
at org.restlet.resource.Finder.handle(Finder.java:470)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.routing.Router.doHandle(Router.java:497)
at org.restlet.routing.Router.handle(Router.java:737)
at com.servlets.ServiceDispatcher$1.handle(ServiceDispatcher.java:55)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:151)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.engine.ChainHelper.handle(ChainHelper.java:111)
at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:72)
at org.restlet.Application.handle(Application.java:388)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.routing.Router.doHandle(Router.java:497)
at org.restlet.routing.Router.handle(Router.java:737)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.routing.Router.doHandle(Router.java:497)
at org.restlet.routing.Router.handle(Router.java:737)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
at org.restlet.routing.Filter.handle(Filter.java:203)
at org.restlet.engine.ChainHelper.handle(ChainHelper.java:111)
at org.restlet.Component.handle(Component.java:387)
at org.restlet.Server.handle(Server.java:488)
at org.restlet.engine.ServerHelper.handle(ServerHelper.java:71)
at org.restlet.engine.http.HttpServerHelper.handle(HttpServerHelper.java:150)
at org.restlet.ext.servlet.ServerServlet.service(ServerServlet.java:1037)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1554)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:339)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.jamonapi.JAMonFilter.doFilter(JAMonFilter.java:59)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:278)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:334)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:230)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:311)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:189)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:850)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:747)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1032)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:231)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:745)
Caused by: Exception [EclipseLink-2004] (Eclipse Persistence Services - 2.3.4.v20151027-346465e): org.eclipse.persistence.exceptions.ConcurrencyException
Exception Description: A signal was attempted before wait() on ConcurrencyManager. This normally means that an attempt was made to 
commit or rollback a transaction before it was started, or to rollback a transaction twice.
at org.eclipse.persistence.exceptions.ConcurrencyException.signalAttemptedBeforeWait(ConcurrencyException.java:84)
at org.eclipse.persistence.internal.helper.ConcurrencyManager.releaseReadLock(ConcurrencyManager.java:489)
at org.eclipse.persistence.internal.identitymaps.CacheKey.releaseReadLock(CacheKey.java:386)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:1018)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:929)
at org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:181)
at org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:120)
at org.eclipse.persistence.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:380)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3899)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3854)
at org.eclipse.persistence.mappings.CollectionMapping.buildElementUnitOfWorkClone(CollectionMapping.java:267)
at org.eclipse.persistence.mappings.CollectionMapping.buildElementClone(CollectionMapping.java:279)
at org.eclipse.persistence.internal.queries.ContainerPolicy.addNextValueFromIteratorInto(ContainerPolicy.java:213)
at org.eclipse.persistence.mappings.CollectionMapping.buildCloneForPartObject(CollectionMapping.java:205)
at org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder.buildCloneFor(UnitOfWorkQueryValueHolder.java:51)
at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiateImpl(UnitOfWorkValueHolder.java:161)
at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:222)
at org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88)
at org.eclipse.persistence.indirection.IndirectList.buildDelegate(IndirectList.java:244)
at org.eclipse.persistence.indirection.IndirectList.getDelegate(IndirectList.java:414)
at org.eclipse.persistence.indirection.IndirectList$1.<init>(IndirectList.java:542)
at org.eclipse.persistence.indirection.IndirectList.listIterator(IndirectList.java:541)
at org.eclipse.persistence.indirection.IndirectList.iterator(IndirectList.java:505)
at com.business.frontend.facade.impl.FrontEndBFBean.combineAllContainerKpis(FrontEndBFBean.java:515)
at com.business.frontend.facade.impl.FrontEndBFBean.getKpiValuesFlat(FrontEndBFBean.java:405)
at sun.reflect.GeneratedMethodAccessor237.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5409)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
at sun.reflect.GeneratedMethodAccessor170.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5381)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5369)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
... 75 more

在进一步检查中,我注意到了这些线条:

_ThreadID=165;_ThreadName=http-thread-pool-37860(5);

Exception [EclipseLink-2004] (Eclipse Persistence Services - 2.3.4.v20151027-346465e)

我最初的想法是 HTTP 线程超时等待 DB 调用完成,然后 HTTP 线程中断了 EclipseLink,使 ConcurrencyManager 处于意外状态(使用后实际上没有释放 DeferredLock)。我做了一个小应用程序,通过调整服务器设置和长时间调用数据库并在数据库调用准备好之前终止 http 调用来测试我的假设,但这似乎并没有重现问题。还有一个事实是发生异常时调用的方法不使用任何类型的JPA(ORM),调用使用JDBC。大多数应用程序使用 EclipseLink 和 JPA,但不是这部分。此外,应用程序使用大量数据库的情况并不少见。

所以我在想,从描述性 (This normally means that an attempt was made to commit or rollback a transaction before it was started, or to rollback a transaction twice) 来看,这个错误背后的原因是什么,我很确定代码没有做这样的事情。

所以一定是一些延迟加载冲突,但我不知道什么条件会导致这个问题。

从现在开始,我不知道在哪里进行调查。欢迎任何想法:)

【问题讨论】:

  • 错误来自 JPA - 您正在触发从 EntityManager 读取的实体上的惰性关系。这会触发它重新使用从中读取实体的上下文来获取数据,并为您提供此异常。检查您的 FrontEndBFBean 以查看它是如何读取它在 combineAllContainerKpis 方法中使用的数据的 - 您可能希望在此关系上使用 fetch join 以便急切地获取它。您也可能在多线程环境中使用这些数据 - EM 和获取的实体并不是真正的线程安全的。
  • @Chris 这似乎是合理的问题,因为那里有延迟加载。您能否更具体地了解延迟加载如何触发“在 ConcurrencyManager 上的 wait() 之前尝试了 A 信号”错误。我不明白为什么一些简单的阅读(没有写作)会触发这样的错误。同样FrontEndBFBean 只是一个不成熟的 bean,因此容器在不同的实例上同时处理 bean 上的两个方法调用。您可以将其发布为答案,以便我将其标记为正确答案。
  • @Chris '这会触发它重新使用读取实体的上下文来获取数据,并给你这个异常。'你能澄清一下吗?谢谢你:)
  • EntityManager 不是并发的,从它读取的实体不应该在线程之间共享。我不能说这些线程实际上是在做什么来获得这个异常 - EntityManager 是一个事务上下文,所以这可能是异常措辞的原因。原始线程可能已在事务中读取了这些实体,并且该事务处理可能干扰了该线程的读取尝试。我只能猜测,直到你追踪这个对象是从哪里读取的。
  • @Chris 谢谢。您能否将其发布为答案,以便我奖励您的赏金。

标签: multithreading jpa jakarta-ee glassfish eclipselink


【解决方案1】:

在这种错误情况下,并发异常的确切原因是未知的——我们只能看到一个线程通过触发实体上的惰性关系来访问上下文。这个实体是如何被读入的以及在其他线程中发生的事情,这些线程可能也在使用这个 EntityManager 从中读取实体(直接或间接通过访问从中读取的实体)需要跟踪,但通常可以避免。

EntityManager 不应该被多个线程访问,因此不处理并发访问。从 EntityManagers 读取的实体有许多挂钩到它们被读取的上下文;这些钩子允许惰性关系、更改跟踪等对应用程序透明地发生。这样做的后果是这些实体也不能被同时访问——它们不应该被应用程序缓存或传递,而不需要仔细考虑。在许多情况下,应用程序最好让 JPA 处理缓存,并根据需要从上下文中访问实体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 2013-03-28
    相关资源
    最近更新 更多