远程服务器重启后远程 EJB 的 InitialContext.lookup 失败
Posted
技术标签:
【中文标题】远程服务器重启后远程 EJB 的 InitialContext.lookup 失败【英文标题】:InitialContext.lookup of remote EJB fails after remote server restart 【发布时间】:2010-10-14 19:20:16 【问题描述】:我们有一个设置,其中 EJB A 在服务器 A 上运行,另一个 EJB B 在服务器 B 上运行。EJB A 通过 IIOP 连接到 EJB B。此设置正常工作,但如果服务器 B 重新启动,EJB A 将失败,直到服务器 A 也重新启动。
问题在于,如果服务器 B 重新启动,则 EJB A 对 InitialContext.lookup 的所有调用都会失败,并出现“java.io.IOException: End-of-stream”异常,直到服务器 A 重新启动。我无法找到有关我们的应用服务器 (GlassFish) 是否对 InitialContext.lookup 进行任何类型缓存的信息。在服务器重新启动之前,还有其他原因导致查找失败吗?如果 InitialContext.lookup 确实缓存连接,我将如何解决这个问题?
我们的服务器运行 Sun Application Server 9.1。查找实际上是通过 org.springframework.jndi.JndiTemplate 完成的,但堆栈跟踪显示 JndiTemplate 正在调用 InitialContext.lookup()。
感谢您的任何见解。
附:我应该澄清一下,我正在尝试弄清楚是否有可能避免每次重新启动服务器 B 时都必须重新启动服务器 A。
JndiTemplate 的定义(部分文本用 'x's 和 '#'s 涂黑)
<bean id="xxxxxxxxxx" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.url.pkgs">com.sun.enterprise.naming</prop>
<prop key="java.naming.factory.initial">com.sun.enterprise.naming.SerialInitContextFactory</prop>
<prop key="java.naming.provider.url">iiop://xxxxxxxxxx:####</prop>
<prop key="java.naming.factory.state">com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl</prop>
<prop key="org.omg.CORBA.ORBInitialHost">xxxxxxxxxx</prop>
<prop key="org.omg.CORBA.ORBInitialPort">####</prop>
</props>
</property>
</bean>
还有堆栈跟踪(其中一部分替换为“[应用程序方法]”):
NAM0004: Exception during name lookup : 0
java.rmi.MarshalException: CORBA COMM_FAILURE 1398079696 Maybe; nested exception is:
org.omg.CORBA.COMM_FAILURE: vmcid: SUN minor code: 208 completed: Maybe
at com.sun.corba.ee.impl.javax.rmi.CORBA.Util.mapSystemException(Util.java:271)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:205)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:152)
at com.sun.corba.ee.impl.presentation.rmi.bcel.BCELStubBase.invoke(BCELStubBase.java:225)
at com.sun.enterprise.naming._SerialContextProvider_DynamicStub.lookup(com/sun/enterprise/naming/_SerialContextProvider_DynamicStub.java)
at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:398)
at javax.naming.InitialContext.lookup(InitialContext.java:351)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:155)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:88)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:153)
at [application methods]
at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:267)
at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:265)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:299)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLReadTask.process(SSLReadTask.java:440)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLReadTask.doTask(SSLReadTask.java:228)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: org.omg.CORBA.COMM_FAILURE: vmcid: SUN minor code: 208 completed: Maybe
at com.sun.corba.ee.impl.logging.ORBUtilSystemException.connectionAbort(ORBUtilSystemException.java:2862)
at com.sun.corba.ee.impl.logging.ORBUtilSystemException.connectionAbort(ORBUtilSystemException.java:2880)
at com.sun.corba.ee.impl.transport.SocketOrChannelConnectionImpl.doOptimizedReadStrategy(SocketOrChannelConnectionImpl.java:1788)
at com.sun.corba.ee.impl.transport.SocketOrChannelConnectionImpl.doWork(SocketOrChannelConnectionImpl.java:1263)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
Caused by: org.omg.CORBA.COMM_FAILURE: vmcid: SUN minor code: 211 completed: No
at com.sun.corba.ee.impl.logging.ORBUtilSystemException.ioexceptionWhenReadingConnection(ORBUtilSystemException.java:2946)
at com.sun.corba.ee.impl.logging.ORBUtilSystemException.ioexceptionWhenReadingConnection(ORBUtilSystemException.java:2965)
at com.sun.corba.ee.impl.transport.SocketOrChannelConnectionImpl.nonBlockingRead(SocketOrChannelConnectionImpl.java:2000)
at com.sun.corba.ee.impl.transport.SocketOrChannelConnectionImpl.doOptimizedReadStrategy(SocketOrChannelConnectionImpl.java:1713)
... 2 more
Caused by: java.io.IOException: End-of-stream
at com.sun.corba.ee.impl.transport.SocketOrChannelConnectionImpl.nonBlockingRead(SocketOrChannelConnectionImpl.java:1989)
... 3 more
【问题讨论】:
我意识到只有在服务器 A 尝试连接到 EJB B 而 服务器 B 正在重新启动时才会出现此问题。如果在服务器 B 重新启动时尝试调用,则服务器 A 将永远无法连接,直到服务器 A 重新启动。如果服务器 A 在服务器 B 重新启动之前一直在调用 EJB B,则在服务器 B 重新启动时它不会对 EJB B 进行任何调用,然后在服务器 B 备份后再次开始调用,一切正常。 我遇到了同样的问题(在停止访问后无法永远重新连接) - 你解决了这个问题吗? 不,我从来没有真正解决过这个问题。不过,我并没有在这个问题上花太多时间。如果服务器 B 重新启动,我们总是通过重新启动服务器 A 来“修复”它。 【参考方案1】:通过堆栈跟踪,我可以得出结论,Spring Framework 本身不缓存 - 它实际上调用了InitialContext.lookup()
。不过,堆栈跟踪和错误代码暗示存在连接中断。
WebSphere 过去曾经有过类似的错误,后来得到了修复。原来是应用服务器自己做的缓存问题。我怀疑 SunAS 在 9.1 中也有类似的错误...
艾萨克
【讨论】:
我肯定怀疑这是一个应用程序服务器错误。我还没有设法测试可能的代码变通方法。【参考方案2】:方法 syncChanges() 定期运行以进行同步。主要思想是在发生错误时关闭上下文(在为示例重新启动服务器之后)并重新初始化它。使用方法 context.close() 关闭上下文后,您应该将其值设为空。
public class SyncOperationsService
private InitialContext context;
private SyncOperationsRemote syncOperationsRemote = null; //RemoteBean
public String syncChanges()
try
if (context == null)
context = new InitialContext(properties);
if (context != null)
syncOperationsRemote = (SyncOperationsRemote) context.lookup("PathToYourRemoteBean");
result = syncOperationsRemote.syncChanges(dbImportList); //Try execute remote bean
catch (Exception e)
log.error(e.getMessage());
try
context.close();
catch (Exception e2)
log.error(e2.getMessage());
context = null;
【讨论】:
以上是关于远程服务器重启后远程 EJB 的 InitialContext.lookup 失败的主要内容,如果未能解决你的问题,请参考以下文章