Announcement Announcement Module
Collapse
No announcement yet.
Using tcp outbound gateway with single-use="false" Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using tcp outbound gateway with single-use="false"

    Hello.

    I'm using tcp outbound gateway with client connection factory, that does not declare single-use attribute (so it means false by default). Thus it means that we use one connection and "each request is blocked until the previous response is received (or times out)".

    Consider, that timeouts are default (10 sec afak) but the remote server needs 12 sec to respond. TcpOutboundGateway connected to Gateway over some transformers, so we have a java interface to some remote server over TCP. Alice and Bob call that interface in a quite same time. Alice's request goes first, Bob's request is blocked. Then timeout occures, Alice gets the TimeoutException on the java interface and Bob's request has been sent. Couple of seconds later the remote server will respond to Alice's request (it doesn't know about our 10 seconds timeout).

    Will Bob get that response to Alice's request in this case?

    Regards,
    -- Alexey

  • #2
    No it will not. All gateways in Spring Integration implement correlation strategy to ensure that each request is correlated with the appropriate response. It would be very awkward if you could get someone else's response and would essentially violate the concept of Messaging in general so NO Bob will not get Alice's response.

    Comment


    • #3
      What this correlation strategy is rely on (when I'm using single connection for all requests)? Could you please shortly describe it or refer to some source code?

      Comment


      • #4
        It actually quite simple. Each gateway request generates a temporary reply channel which is set as a header of the Message. When the response comes back from the remote system the temporary reply channel is re-injected back into the response Message.
        So in short each request travels with the dedicated reply channel.

        With remote systems there is an additional variable that needs to be considered and that is some type of correlation identifier that can correlate the message sent with the message received. For example in JMS its JmsHeaders.CORRELATION_ID and with TCP/IP its IpHeaders.CONNECTION_ID which is then set as "correlationId" header of the Message and so on.

        Comment


        • #5
          What Oleg says is correct for inbound-gateways; however for TCP outbound gateways there is a complication.

          Given that no correlation data is transmitted with the message (unless it is in the payload, which the framework knows nothing about), the socket has to be "reserved" (not used again) until the response is received. This can be a performance bottleneck for high volume environments (and slow servers). The manual discusses this in length in the 'TCP Message Correlation' section: http://static.springsource.org/sprin...ip-correlation.

          There are two techniques that can used; the first is to use a pair of collaborating channel adapters and then the single socket can be used for multiple concurrent messages but the application is required to do the correlation This is explored in the 'tcp-client-server-multiplex' sample https://github.com/SpringSource/spri...rver-multiplex; as you will see, the sample adds correlation data to the payload which is later used with an aggregator to correlate the response with a copy of the request, so the replyHeader can be restored.

          In addition, in 2.2 (recently released), we now support connection caching - you wrap the non single-use connection factory in a CachingConnectionFactory, which provides a pool of connections; thus avoiding the performance issue (as long as the pool is large enough for the required number of concurrent requests).

          I am traveling for another week so my responses may continue to be sporadic.
          Last edited by Gary Russell; Dec 8th, 2012, 03:42 PM.

          Comment


          • #6
            However, referring to your original question, there is an (undocumented) assumption that the socket timeout is set to less than the remoteTimeout so the socket is closed when the SO timeout occurs (before Alice times out). So, the situation you describe is possible; we should force close the socket when Alice times out so there's no possibility of anyone getting her response.

            Please open a JIRA issue for this: https://jira.springsource.org/browse/INT

            Comment


            • #7
              Thank you Gary for detailed answer. Please correct my understanding: if so-timeout is bigger (I've set it to 1min) than gateway response timeout (I've forgot to set it, so it is 10 sec), and i don't add any correlation information to the payload, than the late response for the first request (that fits in so-timeout) can be returned as answer to the second request?
              And the issue, you've mentioned is about to close the socket in this case to avoid that awkward situation?

              Comment


              • #8
                That is correct. Setting the timeout appropriately is a work around but we should close the socket when the gateway times out.

                Comment


                • #9
                  FYI, this issue is now resolved in 2.2.1 and 2.1.5.

                  http://www.springsource.org/node/3793

                  Comment

                  Working...
                  X