【问题标题】:multi-threaded calls from a client to EJBs on Glassfish从客户端到 Glassfish 上的 EJB 的多线程调用
【发布时间】:2015-10-23 05:45:59
【问题描述】:

我正在运行一项操作,该操作涉及对 glassfish 上托管的服务的大量远程 EJB 调用。

客户端和服务器之间有很高的延迟,所以我试图通过多线程请求来加速操作。

不幸的是,我似乎没有通过多线程请求获得任何速度改进 - 相反 - 我的线程请求正在排队。

我的问题是我无法弄清楚他们为什么要排队。

我检查了服务器上的线程池配置 - 并在它运行时检查了它 - 我看到服务器上的线程数与我在客户端上进行 EJB 调用的线程数相对应。这些线程中的大多数都是空闲的,但大多数时候 - 请求根本就没有到达这里。

我觉得我的调用在客户端被阻塞了——从我在服务器上看到的——从查看 jVisualVM 中的线程——以及从查看服务器上的资源使用情况来看(它几乎是空闲的) .

在客户端,我正在为每个线程创建一个完整的、新的 InitialContext 对象/连接。

在客户端,我看到我的大部分线程都在 corba 中被阻塞:

    "p: default-threadpool; w: 29" daemon prio=10 tid=0x00007f18b4001000 nid=0x608f in Object.wait() [0x00007f19ae32b000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000000f2ef5388> (a java.util.LinkedList)
    at java.lang.Object.wait(Object.java:503)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.resumeOptimizedReadProcessing(CorbaMessageMediatorImpl.java:791)
    - locked <0x00000000f2ef5388> (a java.util.LinkedList)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.setWorkThenReadOrResumeOptimizedRead(CorbaMessageMediatorImpl.java:869)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1326)
    at com.sun.corba.ee.impl.protocol.giopmsgheaders.FragmentMessage_1_2.callback(FragmentMessage_1_2.java:122)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:742)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:539)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2324)
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)

我的线程被阻塞了

"Pool-27" daemon prio=10 tid=0x00007f19b403c800 nid=0x4ef8 waiting on condition [0x00007f19ac70e000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000f2f66078> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
    at com.sun.corba.ee.impl.transport.CorbaResponseWaitingRoomImpl.waitForResponse(CorbaResponseWaitingRoomImpl.java:173)
    at com.sun.corba.ee.impl.transport.SocketOrChannelConnectionImpl.waitForResponse(SocketOrChannelConnectionImpl.java:1021)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.waitForResponse(CorbaMessageMediatorImpl.java:279)
    at com.sun.corba.ee.impl.protocol.CorbaClientRequestDispatcherImpl.marshalingComplete1(CorbaClientRequestDispatcherImpl.java:407)
    at com.sun.corba.ee.impl.protocol.CorbaClientRequestDispatcherImpl.marshalingComplete(CorbaClientRequestDispatcherImpl.java:368)
    at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.invoke(CorbaClientDelegateImpl.java:273)
    at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:200)
    at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:152)
    at com.sun.corba.ee.impl.presentation.rmi.codegen.CodegenStubBase.invoke(CodegenStubBase.java:227)

令我烦恼的其他事情是,无论我在客户端上运行多少线程 - 我只得到一个 - 有时是 2 个 - 'RMI TCP Connection' 线程。但我不确定这是否涉及 EJB 远程处理。

为什么/我的客户端线程在这些远程调用中被阻塞?

请注意,这不是带宽问题 - 正在传输的数据量很小 - 但存在高延迟。因此,并行提出更多请求应该会给我带来改进。相反 - 我的总时间大致保持不变 - 但个别请求会从 500 毫秒变为 5000 毫秒,例如,随着我增加客户端线程数。

任何超过 2 或 3 个线程的线程对总时间都没有影响。

如果我不考虑延迟,通过在与 GlassFish 服务器相同的系统上运行相同的本地进程,性能达到预期 - 速度太快,甚至无法真正调试 - 所以服务器能够运行毫无疑问处理工作量。

我似乎无法从客户端并行发出请求。

【问题讨论】:

    标签: multithreading glassfish ejb client


    【解决方案1】:

    检查您的 EJB 是什么类型。如果您调用相同的 Stateful 或 Singleton EJB,则您的调用是同步的 - 默认情况下一次只允许单个调用,无论您调用相同的方法还是不同的方法。对于无状态 EJB,情况并非如此,但如果您的池耗尽,您的调用可能会被阻止 - 检查您服务器上 EJB 池的大小并增加它。

    使用 Stateful,您无法更改行为(请参阅 this answer,但您可以为每个远程客户端实例化一个新的 EJB。使用 Singleton,您应该考虑使用 adjusting concurrency management 以提高吞吐量。

    【讨论】:

    • 嗯,我检查了 bean 类型 - 我确实找到了一个无意中设置为 Singleton 的类型。修复该问题并没有太大影响,但是,我正在访问的大多数 bean 已经设置为 StatelessSessionBean 类型。系统中有几个 bean 在设计上是单例的 - 但我假设如果无状态 bean 引用单例 bean - 在内部,它应该只同步那些接触单例的调用 - 而不是同步整个无状态 bean,是吗?
    • 您是对的 - 每个请求都为无状态 EJB 分配一个,因此它们不会阻止其他请求。 Singleton 只能在其方法运行时阻塞。也许您的客户端出于任何原因同步 EJB 执行 - 检查是否可以在客户端中配置 CORBA/RMI 线程池。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多