简体   繁体   English

如何在netty中设置不关闭连接的读取超时?

[英]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. 我有一个netty服务器接收来自客户端的请求,向另一个服务器发出请求,然后在响应原始客户端请求时使用第二个请求的响应。 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. 我希望对第二个服务器的请求有一个短暂的超时(~40ms),因此我可以在超时的情况下发送一般响应,但我不想关闭与第二个服务器的连接。 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? 在netty中执行此操作的最佳方法是什么? I've tried ReadTimeoutHandler but this seems to close the connection to the second server when a timeout occurs. 我已经尝试过ReadTimeoutHandler,但是当发生超时时,这似乎会关闭与第二台服务器的连接。

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. 对于您不担心排队出站请求的简单情况,您应该能够创建ReadTimeoutHandler的副本并根据需要进行修改,最有可能的方法是让它从上下文中获取回调,以便调用而不是关闭readTimedOut()方法中的连接。

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). 您可能仍然希望对第二台服务器的连接进行某种类型的超时检查,以便在连接时间过长(30秒或一分钟等)时无法响应连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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