Announcement Announcement Module
Collapse
No announcement yet.
Behaviour of the 'default-reply-timeout' of the 'int:gateway' Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Behaviour of the 'default-reply-timeout' of the 'int:gateway'

    Code:
    <int:channel id="channel.request" />
    <int:channel id="channel.reply" />
    
    <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" message-converter="marshallingMessageConverter"
    	reply-timeout="10000"/>
    
    <int:gateway id="gatewayService" service-interface="com.gatewayservice.GatewayService" default-reply-timeout="6000">
    	<int:method name="calculateLoanAmount" request-channel="channel.request" reply-channel="channel.reply" />
    </int:gateway>
    
    
    <int-amqp:outbound-gateway amqp-template="rabbitTemplate" exchange-name-expression="headers.exchange" routing-key-expression="headers.routingKey" 
    	request-channel="channel.request" reply-channel="channel.reply"/>

    Hi,

    In our spring integration as shown above, we have configured the 'default-reply-timeout' attribute of the 'int:gateway' and 'reply-timeout' attribute of the 'rabbit:template'.

    Our observations are as follows :

    1. When there is no reply on AMQP for the request, 'calculateLoanAmount' method of the 'GatewayService.java' returns null after it waits
    for 16000 milliseconds. It seems that 16000 milliseconds is built of (default-reply-timeout="6000" + reply-timeout="10000").

    2. If we don't configure the 'default-reply-timeout' attribute of the 'int:gateway', we noticed that the invoking thread gets parked
    forever until the server is restarted.

    3. If we set a minus value (-1) for either attributes ('default-reply-timeout' & 'reply-timeout'), we noticed that the invoking thread gets parked
    forever until the server is restarted.

    4. If there is a reply after 10000 milliseconds which is after the 'reply-timeout' attribute of the 'rabbit:template', it seems that the gateway doesn't pick that
    reply. The Gateway waits for another 6000 milliseconds and returns null.

    Ex. If a reply comes after 12000 milliseconds, it seems that the 'gateway' doesn't pick that reply. It simply waits 6000 milliseconds after the AMQP timeout which
    is 10000 milliseconds and returns null.

    It would be great if you could verify and answer the questions that are listed below :


    Is our understanding correct on the following?

    1. When the down stream process ('amqp:outbound-gateway') times out (in 10000 milliseconds) and it hands over
    the control to the gateway ('int:gateway') at which point the 'default-reply-timeout' counter is started in the gateway.
    On completion of the 'default-reply-timeout' counter (in 6000 milliseconds) a null is returned from the 'calculateLoanAmount' method.
    Simply the 'calculateLoanAmount' method returns null after the 16000 milliseconds.

    2. If we configured only 'reply-timeout' attribute of the 'rabbit:template' and the down stream process ('amqp:outbound-gateway')
    times out (in 10000 milliseconds) and it hands over the control to the gateway ('int:gateway'). As we don't configure 'default-reply-timeout'
    attribute of the 'int:gateway', it doesn't start the timeout counter and it hangs forever.

    3. If we configured only 'default-reply-timeout' attribute of the 'int:gateway' and and the down stream process ('amqp:outbound-gateway')
    doesn't find the reply and as of that it doesn't hand over the control to the gateway. Then the execution thread is hung forever in the down stream process.

    4. When the down stream process ('amqp:outbound-gateway') times out (in 10000 milliseconds) and it hands over
    the control to the gateway ('int:gateway') at which point the 'default-reply-timeout' counter is started in the gateway. If the reply comes after
    the counter has begun, the 'gateway' doesn't pick that reply. So there is no point to configured a large timeout value for the 'default-reply-timeout' as it just waits for the configured timeout time period and returns null.

    Thanks in advance
    Varuna

  • #2
    Hi Varuna,

    Thanks for your questions. When dealing with timeouts, it is very important to understand how the message flow is executed: asynchronously or synchronously. Or expressed differently, are you crossing thread-boundaries.

    In your case, you have declared your channels to be synchronous. Therefore, your entire message flow is executed on the same thread single. This is happening in your message flow:

    1)
    You are sending your message via the Gateway and the Request Channel to the AMQP Outbound Gateway. As noted above, everything is executed on the same thread:

    - We send the message first. However, you defined a 10000ms reply-timeout on the RabbitTemplate. Consequently, the send operation will only complete after 10000ms.
    - Now the receive is executed (Trying to retrieve the reply from the reply channel) and with it, the 'default-reply-timeout' of 6000ms kicks in. So yes, in this particular use-case you will observe a total time-out of 16000ms.

    For more details, please take a look at the source code of the "org.springframework.integration.core.MessagingTem plate":

    https://github.com/SpringSource/spri...late.java#L318

    As you are sending+receiving on a single thread, having the reply-timeout probably does not make much sense. The reply will be available as soon as the send operation has been finished.

    2) That is the default behavior - by default the Gateway will wait indefinitely to get a response back.
    3) Negative values indicate 'infinity'.
    4) Correct. Basically, the Gateways "send" encompasses the sending of the message via the "amqp:outbound-gateway" ("rabbitTemplate") which includes waiting for the AMQP response message (10000 ms timeout). Therefore, the 6000ms reply-timeout has essentially no effect.

    I hope this provides some meaningful insights to the observed behavior.

    Cheers,

    Gunnar

    Comment


    • #3
      Created a Jira to improve the respective Reference documentation for Gateways in regards to timeout settings - https://jira.springsource.org/browse/INT-2849

      Comment


      • #4
        Hi Gunnar,

        Thank you very much for the explanation, but I still have a few unclear areas on this. Yes, all our communication are done synchronously. We don't cross thread-boundaries.

        We send RabbitMQ messages using 'int-amqp:outbound-gateway' and those messages are processed by another module. It takes bit of time to process a request, so, that is why we have to set the 'reply-timeout' attribute of the 'rabbit:template' as the 'DEFAULT_REPLY_TIMEOUT' of 'RabbitTemplate.java' is 5000 milliseconds. (Sometimes 5000 milliseconds is not enough)

        If we don't configure the 'default-reply-timeout' attribute of the 'int:gateway', we noticed that the invoking thread gets parked
        forever until the server is restarted. In the real scenario we hope to configure a very small value for it.

        But in the Jira task (INT-2849) that you created for improving the documentation, it is mentioned
        'Add a note that users should not set the reply-timeout attribute when using a DirectChannel-based reply channel'. Could you explain this ?

        As in our scenario we require to set a 'default-reply-timeout' attribute of the 'int:gateway' else we see the issue mentioned in point 2.

        We also have a question on the below configuration. In this scenario we have used 'int-ws:outbound-gateway' instead of 'int-amqp:outbound-gateway'. Please see the configuration below.

        Code:
        <int:channel id="channel.request" />
        <int:channel id="channel.reply" />
        
        <int:gateway id="gatewayService" service-interface="com.gatewayservice.GatewayService" default-reply-timeout="6000">
        	<int:method name="calculateLoanAmount" request-channel="channel.request" reply-channel="channel.reply" />
        </int:gateway>
        
        <bean id="httpMessageSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender" >
        	<property name="connectionTimeout" value="60000"/>
        	<property name="readTimeout" value="120000"/>
        </bean>
        
        <int-ws:outbound-gateway marshaller="marshallingMessageConverter" unmarshaller="marshallingMessageConverter" uri="service-ws-url"
        	request-channel="channel.request" reply-channel="channel.reply" message-sender="httpMessageSender"/>

        Some responses coming from the external service to the 'int-ws:outbound-gateway' are having 202 (ACCEPTED) HTTP Status. Here also, if we don't configure the default-reply-timeout' attribute of the 'int:gateway', we noticed that the invoking thread gets parked forever. Can you verify if our approach is correct with this configuration as well?

        Thanks in advance
        Varuna
        Last edited by varuna; Dec 7th, 2012, 06:23 AM.

        Comment


        • #5
          Hello

          I suggest to take a look into sources: MessagingGatewaySupport#registerReplyMessageCorrel ator
          So, as you can see the 'replyTimeout' is applied only when you provide:
          Code:
          this.replyChannel instanceof PollableChannel
          You should change your 'channel.reply' to this one:
          HTML Code:
          <int:channel id="channel.reply">
             <int:queue/>
          </int:channel id="channel.reply">
          Take care,
          Artem

          Comment

          Working...
          X