Java JMS性能和RemoteTCPConnection.receive

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.

在并行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.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();
        }

    }
}