Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java WSO2ESB 4.8.1 PassThroughHttpSender不会在异常时将线程返回到工作线程池_Java_Multithreading_Thread Safety_Wso2esb_Endpoint - Fatal编程技术网

Java WSO2ESB 4.8.1 PassThroughHttpSender不会在异常时将线程返回到工作线程池

Java WSO2ESB 4.8.1 PassThroughHttpSender不会在异常时将线程返回到工作线程池,java,multithreading,thread-safety,wso2esb,endpoint,Java,Multithreading,Thread Safety,Wso2esb,Endpoint,我认为org.apache.synapse.transport.passthru.PassThroughHttpSender是wso2esb 4.8.1中http的默认传输发送器(不确定4.9.0稍后是否会检查它),在某些情况下不会在异常时将借用的线程返回到工作线程池 在我看来,当异常在外部序列中发生时(而不是在直接接受传入请求的代理中),就会发生这种情况。例如,当您使用存储和消息处理器实现存储转发模式时,就会发生这种情况 这是我的简单WSO2ESB 4.8.1配置,用于重现该问题: <?

我认为org.apache.synapse.transport.passthru.PassThroughHttpSender是wso2esb 4.8.1中http的默认传输发送器(不确定4.9.0稍后是否会检查它),在某些情况下不会在异常时将借用的线程返回到工作线程池

在我看来,当异常在外部序列中发生时(而不是在直接接受传入请求的代理中),就会发生这种情况。例如,当您使用存储和消息处理器实现存储转发模式时,就会发生这种情况

这是我的简单WSO2ESB 4.8.1配置,用于重现该问题:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
   <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
      <parameter name="cachableDuration">15000</parameter>
   </registry>
   <import name="fileconnector"
           package="org.wso2.carbon.connector"
           status="enabled"/>
   <proxy name="ProxyTest"
          transports="http https"
          startOnLoad="true"
          trace="disable">
      <target>
         <inSequence>
            <property name="FORCE_SC_ACCEPTED"
                      value="true"
                      scope="axis2"
                      type="STRING"/>
            <log level="custom">
               <property name="text" value="store message"/>
            </log>
            <store messageStore="TestXMS"/>
            <log level="custom">
               <property name="text" value="message stored"/>
            </log>
         </inSequence>
         <outSequence/>
         <faultSequence/>
      </target>
   </proxy>
   <localEntry key="ESBInstance">Test<description/>
   </localEntry>
   <endpoint name="HTTPEndpoint">
      <http method="post" uri-template="http://localhost/index.php">
         <timeout>
            <duration>10</duration>
            <responseAction>fault</responseAction>
         </timeout>
         <suspendOnFailure>
            <errorCodes>-1</errorCodes>
            <initialDuration>0</initialDuration>
            <progressionFactor>1.0</progressionFactor>
            <maximumDuration>0</maximumDuration>
         </suspendOnFailure>
         <markForSuspension>
            <errorCodes>-1</errorCodes>
         </markForSuspension>
      </http>
   </endpoint>
   <sequence name="fault">
      <log level="full">
         <property name="MESSAGE" value="Executing default 'fault' sequence"/>
         <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
         <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
      </log>
      <drop/>
   </sequence>
   <sequence name="TestSequence">
      <log level="full">
         <property name="text" value="message recieved"/>
      </log>
      <call>
         <endpoint key="HTTPEndpoint"/>
      </call>
      <log level="full">
         <property name="text" value="message processed"/>
      </log>
   </sequence>
   <sequence name="main">
      <in>
         <log level="full"/>
         <filter source="get-property('To')" regex="http://localhost:9000.*">
            <send/>
         </filter>
      </in>
      <out>
         <send/>
      </out>
      <description>The main sequence for the message mediation</description>
   </sequence>
   <messageStore name="TestXMS"/>
   <messageProcessor class="org.apache.synapse.message.processor.impl.sampler.SamplingProcessor"
                     name="TestMP"
                     messageStore="TestXMS">
      <parameter name="interval">1000</parameter>
      <parameter name="sequence">TestSequence</parameter>
      <parameter name="concurrency">1</parameter>
      <parameter name="is.active">true</parameter>
   </messageProcessor>
</definitions>
这是进程堆栈出错的地方。当异常发生(在另一个线程中)时,它“忘记”通知当前线程,而msgContext将永远等待(实际上直到服务器重新启动)

所以我稍微修改了同一个包中的另一个类-DeliveryAgent,MethodErrorConnection。此方法用于捕获来自用于连接到目标主机的线程的回调。。。因此,当我们捕获回调时,我们会通知msgContext并通过在targetErrorHandler之后添加新的同步块来通知它继续

public void errorConnecting(HttpRoute route, int errorCode, String message)
  {
    Queue<MessageContext> queue = (Queue)this.waitingMessages.get(route);
    if (queue != null)
    {
      MessageContext msgCtx = (MessageContext)queue.poll();
      if (msgCtx != null) {
        this.targetErrorHandler.handleError(msgCtx, errorCode, "Error connecting to the back end", null, ProtocolState.REQUEST_READY);
        synchronized (msgCtx)
        {
            log.info("errorConnecting: notify message context about error");
            msgCtx.setProperty("PASSTHRU_CONNECT_ERROR", Boolean.TRUE);
            msgCtx.notifyAll();
        }
      }
    }
    else
    {
      throw new IllegalStateException("Queue cannot be null for: " + route);
    }
  }
public void errorConnecting(HttpRoute路由、int errorCode、字符串消息)
{
Queue Queue=(Queue)this.waitingMessages.get(route);
if(队列!=null)
{
MessageContext msgCtx=(MessageContext)queue.poll();
如果(msgCtx!=null){
this.targetErrorHandler.handleError(msgCtx,错误代码,“连接后端时出错”,null,ProtocolState.REQUEST\u READY);
已同步(msgCtx)
{
info(“errorConnecting:notifymessagecontext关于错误”);
msgCtx.setProperty(“PASSTHRU\u CONNECT\u ERROR”,Boolean.TRUE);
msgCtx.notifyAll();
}
}
}
其他的
{
抛出新的IllegalStateException(“对于:+路由,队列不能为null”);
}
}
我做了一些测试,看起来它解决了“死”线程的问题。然而,我不确定这是否是一个适当的修复或不。。。欢迎提出任何建议


链接到反编译和修改的源文件-

我找到了问题的原因。如果后端应用程序接受请求并且不向ESB回复任何内容,就会发生这种情况。结果,连接因超时而关闭。在这种情况下,ESB工作线程不会返回到线程池

为了克服这个问题,需要修补org.apache.synapse.transport.passthru.TargetErrorHandler java类

synchronized (mc){ 
   log.info("notify message context about error");
   mc.setProperty("PASSTHRU_CONNECT_ERROR", Boolean.TRUE); 
   mc.notifyAll(); 
}
把它放在挡块前面

它将正确地将消息上下文设置为有错误,并通知所有等待的对象,从而允许ESB返回线程池中的请求处理线程。所有这些对于4.8.1都是正确的

我已经对其进行了修补,并将其置于生产环境中,该环境在2016年1月每天处理数百万个请求。从那时起就没有问题了

synchronized (mc){ 
   log.info("notify message context about error");
   mc.setProperty("PASSTHRU_CONNECT_ERROR", Boolean.TRUE); 
   mc.notifyAll(); 
}