简体   繁体   中英

How to set a read timeout in netty that does not close the connection?

I have a netty server that receives requests from a client, makes a request to another server, and then uses the response from the second request in the response to the original clients request. I want to have a short timeout (~40ms) on the request to the second server so I can send a generic response in the event of a timeout, but I don't want to close the connection to the second server. Instead, I will simply discard the response to the timed out request when it arrives and then return the connection to my pool.

What's the best way to do this in netty? I've tried ReadTimeoutHandler but this seems to close the connection to the second server when a timeout occurs.

It appears that for your requirements you will need to write your own timing management around the connection to the second server. Furthermore, since you mention a connection pool that may imply that you also have a limit on how many connections you can establish simultaneously to the second server (well, there is always a limit, it just depends on whether you actually have to worry about it or not).

For the simple case where you are not worrying about queueing outbound requests, you should just be able to create a copy of ReadTimeoutHandler and modify it as you need, most likely by having it pull a callback from the context for it to invoke instead of closing the connection in its readTimedOut() method.

In the case where you are going to queue your outbound requests, you should consider the time spent on the queue as well as the time to receive a response, so your solution would require your own timer that starts as soon as you put an item into the outbound queue. Furthermore, you need a way to synchronize between the timer and a valid result being returned (you only want to send one response, not one when the timer times out, and one when the response from the second server comes in). To do this I imagine you would want to use some type of manager object that contains a reference to the channel, with your callbacks writing back through this manager.

Eg (in pseudo-ish code)

MyStateManager manager = new MyStateManager(channel);
// Scheduled a timer task for 40ms from now to invoke the callback
// method of your ReadTimedOutCallback and send a message through the manager
myTimer.schedule(new ReadTimedOutCallback(manager),40);
// Send an outbound request to server 2 through a class that queues
// and manages such requests asynchronously.  When the request is complete
// it invokes the callback method of RequestCompletedCallback which then
// sends a response through the manager.
myAsyncOutboundServerRequester.request(new RequestCompletedCallback(manager));
// ... finish and return the thread to Netty for use with other requests
// while the async tasks process

And the manager in simple form would be something like (excluding exception handling, channel state checking, etc):

public class MyStateManager
{
    private final Channel channel;
    private AtomicBoolean messageSent = new AtomicBoolean(false);
    public MyStateManager(Channel channel)
    {
        this.channel = channel;
    }

    // Called by the ReadTimeoutCallback
    public void sendGenericResponse()
    {
        if (messageSent.getAndSet(true))
        {
           //... write generic response to channel
           ChannelFuture future = channel.write... 
           // Add listeners to future, etc
        } 
    }

    // Called by the RequestCompletedCallback
    public void sendResponse(MyResponseObject response)
    {
        if (messageSent.getAndSet(true))
        {
            // write returned response to channel
            ChannelFuture future = channel.write(response);
            // Add listeners to future, etc
        }
    }

}

You would still probably want to put some type of timeout checking on your connection to the second server in order to close the connection if it is unresponsive for far too long (30 seconds or a minute or something).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM