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

时间:2013-04-10 18:05:52

标签: java netty

我有一个netty服务器,它接收来自客户端的请求,向另一个服务器发出请求,然后在对原始客户端请求的响应中使用第二个请求的响应。我希望对第二个服务器的请求有一个短暂的超时(~40ms),因此我可以在超时的情况下发送一般响应,但我不想关闭与第二个服务器的连接。相反,我只是在它到达时丢弃对超时请求的响应,然后将连接返回到我的池中。

在netty中执行此操作的最佳方法是什么?我已经尝试过ReadTimeoutHandler,但是当发生超时时,这似乎关闭了与第二台服务器的连接。

1 个答案:

答案 0 :(得分:4)

看来根据您的要求,您需要围绕与第二台服务器的连接编写自己的时序管理。此外,既然你提到了一个连接池,这可能意味着你也可以限制你可以同时建立到第二台服务器的连接数量(好吧,总有一个限制,它只取决于你是否真的要担心它或不)。

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

在您要对出站请求进行排队的情况下,您应该考虑在队列上花费的时间以及接收响应的时间,因此您的解决方案需要您自己的计时器,一旦您放入一个项目进入出站队列。此外,您需要一种在计时器和返回的有效结果之间进行同步的方法(您只想发送一个响应,而不是在计时器超时时发送一个响应,而在第二个服务器的响应进入时发送一个响应)。要做到这一点,我想你会想要使用某种类型的经理对象,其中包含对频道的引用,你的回调通过这个经理回写。

E.g。 (在伪代码中)

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

简单形式的管理器就像(不包括异常处理,通道状态检查等):

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
        }
    }

}

您可能仍希望对第二台服务器的连接进行某种类型的超时检查,以便在连接时间过长(30秒或一分钟或更长时间)无响应时关闭连接。