Java JMS性能和RemoteTCPConnection.receive
在并行JMS用户线程之后,我没有得到期望的性能提升。Java JMS性能和RemoteTCPConnection.receive,java,ibm-mq,Java,Ibm Mq,在并行JMS用户线程之后,我没有得到期望的性能提升。 在jvisualvm中,我可以看到以下jms内容在self-time CPU专栏中成为“赢家” com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection.receive() 下面是线程实际执行的完整堆栈跟踪 "RcvThread: com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection@9167029[qmid=MWTEST53_2019-06-10_12.32.
在jvisualvm中,我可以看到以下jms内容在self-time CPU专栏中成为“赢家”
com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection.receive()
下面是线程实际执行的完整堆栈跟踪
"RcvThread: com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection@9167029[qmid=MWTEST53_2019-06-10_12.32.59,fap=12,channel=MA ,ccsid=1208,sharecnv=10,hbint=300,peer=MWTEST/162.11.56.86(1453),localport=61965,ssl=no,hConns=0,LastDataSend=1583310588163 (16ms ago),LastDataRecv=1583310588163 (16ms ago),]" - Thread t@651
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at com.ibm.mq.jmqi.remote.impl.RemoteTCPConnection.receive(RemoteTCPConnection.java:1535)
at com.ibm.mq.jmqi.remote.impl.RemoteRcvThread.receiveBuffer(RemoteRcvThread.java:794)
at com.ibm.mq.jmqi.remote.impl.RemoteRcvThread.receiveOneTSH(RemoteRcvThread.java:757)
at com.ibm.mq.jmqi.remote.impl.RemoteRcvThread.run(RemoteRcvThread.java:150)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
"jms_reader_thread_9" - Thread t@63
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
- waiting on <711f08> (a com.ibm.mq.jmqi.remote.impl.RemoteProxyQueue$GetterEventMonitor)
at com.ibm.mq.jmqi.remote.impl.RemoteProxyQueue.proxyMQGET(RemoteProxyQueue.java:2492)
at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiGetInternalWithRecon(RemoteFAP.java:6536)
at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiGetInternal(RemoteFAP.java:6432)
at com.ibm.mq.jmqi.internal.JmqiTools.getMessage(JmqiTools.java:1259)
at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiGet(RemoteFAP.java:6395)
at com.ibm.mq.ese.jmqi.InterceptedJmqiImpl.jmqiGet(InterceptedJmqiImpl.java:910)
at com.ibm.mq.ese.jmqi.ESEJMQI.jmqiGet(ESEJMQI.java:362)
at com.ibm.mq.MQDestination.internalGetMessage(MQDestination.java:1012)
- locked <1a7d0fa> (a com.ibm.mq.MQQueue)
at com.ibm.mq.MQDestination.getInt(MQDestination.java:585)
- locked <1a7d0fa> (a com.ibm.mq.MQQueue)
at com.ibm.mq.MQDestination.get(MQDestination.java:456)
at com.company.app.connection.MqConnection.nextRecordObject(MqConnection.java:351)
at com.company.app.source.AppMqReader.next(AppMqReader.java:37)
at com.company.app.source.AppJMSReadConnector.delegateNext(AppJMSReadConnector.java:202)
at com.company.app.source.LegacyReadConnector.readNextWithRetry(LegacyReadConnector.java:114)
at com.company.app.source.LegacyReadConnector.processNext(LegacyReadConnector.java:68)
at com.company.app.source.AppJMSReadConnector.processNext(AppJMSReadConnector.java:435)
at com.company.app.source.AppReadConnector.next(AppReadConnector.java:131)
at com.company.app.source.AppReadConnector.next(AppReadConnector.java:114)
at com.company.app.configuration.jaxb.ReadPipeline.run(ReadPipeline.java:262)
at com.company.app.configuration.jaxb.AppAdaptor.run(AppAdaptor.java:684)
at com.company.app.configuration.jaxb.RouteService.runOneIteration(RouteService.java:78)
at com.google.common.util.concurrent.AbstractScheduledService$ServiceDelegate$Task.run(AbstractScheduledService.java:195)
at com.google.common.util.concurrent.AbstractScheduledService$CustomScheduler$ReschedulableCallable.call(AbstractScheduledService.java:482)
at com.google.common.util.concurrent.AbstractScheduledService$CustomScheduler$ReschedulableCallable.call(AbstractScheduledService.java:448)
at com.google.common.util.concurrent.Callables$3.call(Callables.java:89)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- locked <cc8421> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
- locked <15571ee> (a java.util.concurrent.ThreadPoolExecutor$Worker)
状态0x4应该是有信号的ST\u GETTER\u
问题:等待
ST_GETTER_发出信号的状态背后的逻辑是什么,线程实际在做什么,以及如何使其更快?这比一个注释多一点,而且,嗯,比一个答案少一点,但因为这里的注释文本太多
你真的需要描述你的线程是何时产生的,何时有工作要做,因为很难找出哪里出了问题,但是根据你的陈述,线程大多处于等待状态,然后
。。。可能发生的情况是,如果所有10个线程共享相同的同步
逻辑,那么在任何给定点,其中9个线程将被锁定在此逻辑之外。10号将等待您在(this.status&0x4)==0)
上的检查成功
也就是说,如果你的第10个线程在这个逻辑中等待,那么其他9个线程将等待第10个线程停止等待
我认为您需要重新设计逻辑,让一个dispatcher线程监视事件,然后将一个工作单元分配给等待的线程 您需要了解性能的基本知识。。。
一项工作要么正在运行(使用CPU),要么正在等待(不使用CPU)
如果没有工作要做,那么线程将处于等待状态。在内部,它可能会定期醒来检查状态,然后再次进入睡眠状态。在这种情况下,使用CPU的“热”例程将与定时相关。通常,MQ应用程序执行定时等待—MQGET等待10秒—因此您将看到“处于定时等待状态”
如果您看到线程处于等待状态,那么您需要找到消息没有传递到线程的原因。如果您的线程很忙,并且使用CPU的时间超过了25%,那么您可能需要检查它们为什么使用这么多CPU,例如,它们正在进行数据转换或解密
一些基础知识
我认为这些线程正在使用消息。
是否有可供it使用的消息—例如,显示队列的深度。如果小于10,那么您的一些线程将等待。如果curdepth大于10,那么所有线程都应该能够运行和处理消息
消息是持久的还是非持久的。
如果它们是非持久性的,那么就没有磁盘日志记录,获取一条消息需要几毫秒的时间,因此您应该能够每秒看到队列上处理的100条消息。
如果它们是持久性的,则在退出同步点或提交时会涉及磁盘日志记录-这可能是1-10(或更多)毫秒。因此,您的任务将花费大部分时间等待
下降一级。取决于您的MQ版本。如果您在同步点之外(分布式MQ上)执行持久消息的put或get操作,则会在整个请求中持有一个锁,以序列化对队列的访问。这可能会限制您每秒发送不到100条消息。看这里
您还需要考虑这些消息是“获取特定信息”还是“获取任何信息”
例如,应用程序向服务器执行MQPUT,然后等待回复。(所谓的请求-应答或客户机模型)。即使队列中有消息,线程也将等待特定消息。
如果您的应用程序是服务器,“获取队列上的第一条消息,对其进行处理并将回复发送回”。然后就可以处理任何可用的消息。据我所知,IBM MQ是一个封闭源代码的软件,所以我不确定这里有多少人会理解,更不用说能够公开评论实现细节了。另外,看起来您实际上并没有使用JMS。是否有消息等待队列中的消息被使用?我建议将SVRCONN
频道设置为具有SHARECNV(1)
。默认情况下,IBM MQ将其设置为10,这意味着每个通道有10个对话(意味着每个TCP连接),这意味着事物被多路复用。将其设置为1会为每个会话提供TCP连接。另外,如果这是一个JMS异步侦听器,只要Qmgr是v7.0或更高版本,它就会在回调模式下工作,因此如果没有消息,它将只在QM上等待,客户端没有任何活动。Josh,您的评论非常有用,但我还没有找到问题的根本原因,所以我没有任何东西可以共享。我确信输入队列中有消息,所以这不是线程状态的原因。事实上,默认情况下SHARECNV为10,我试图将其设为1,但运气不好,因为我正在处理为其编写dsl的某个自定义应用程序,我唯一能做的就是更改应用程序配置并配置“路由”。我没有找到将该配置应用于测试的方法,因此,我无法共享任何有用的内容。贾斯汀是完全正确的,但他的评论没有多大帮助。在这几天里,我发现了同步日志记录和DB调用的瓶颈,这是我两天来一直关注的问题,我将在最后一起编译所有内容。
synchronized (this.getterEventMonitor) {
if ((this.status & 0x4) == 0) {
if (waitInterval > 0) {
this.getterEventMonitor.wait(waitInterval);
}
else {
this.getterEventMonitor.wait();
}
}
}