Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Netty HTTP客户端重试请求_Java_Http_Netty - Fatal编程技术网

Java 使用Netty HTTP客户端重试请求

Java 使用Netty HTTP客户端重试请求,java,http,netty,Java,Http,Netty,如何在基于Netty的HTTP客户端中重试HTTP请求 考虑以下处理程序,如果收到HTTP响应代码503,该处理程序将在1秒后重试HTTP请求: public class RetryChannelHandler extends ChannelDuplexHandler { List<HttpObject> requestParts; @Override public void write(ChannelHandlerContext ctx, Object m

如何在基于Netty的HTTP客户端中重试HTTP请求

考虑以下处理程序,如果收到HTTP响应代码503,该处理程序将在1秒后重试HTTP请求:

public class RetryChannelHandler extends ChannelDuplexHandler {
    List<HttpObject> requestParts;

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof HttpRequest) {
            requestParts = new ArrayList<>();
            requestParts.add((HttpRequest)msg);
        } else if (msg instanceof HttpObject) {
            requestParts.add((HttpObject)msg);
        }

        super.write(ctx, msg, promise);
    }

    @Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpResponse) {
            HttpResponse res = (HttpResponse)msg;
            if (res.status().code() == 503) {
                ctx.executor().schedule(new Runnable() {
                    @Override
                    public void run() {
                        for (HttpObject obj : requestParts) {
                            ctx.channel().write(obj);
                        }
                    }
                }, 1000, TimeUnit.MILLISECONDS);
            } else {
                super.channelRead(ctx, msg);
            }
        } else {
            super.channelRead(ctx, msg);
        }
    }
}
公共类RetryChannelHandler扩展ChannelDuplexHandler{
列出所需零件;
@凌驾
public void write(ChannelHandlerContext ctx、对象消息、ChannelPromise承诺)引发异常{
if(HttpRequest的消息实例){
requestParts=newarraylist();
add((HttpRequest)msg);
}else if(HttpObject的消息instanceof){
add((HttpObject)msg);
}
super.write(ctx、msg、promise);
}
@凌驾
public void channelRead(最终ChannelHandlerContext ctx,对象消息)引发异常{
if(HttpResponse的消息实例){
HttpResponse res=(HttpResponse)msg;
if(res.status().code()==503){
ctx.executor().schedule(新的Runnable()){
@凌驾
公开募捐{
用于(HttpObject对象:requestParts){
ctx.channel().write(obj);
}
}
},1000,时间单位为毫秒);
}否则{
超级通道读取(ctx、msg);
}
}否则{
超级通道读取(ctx、msg);
}
}
}
在本例中,当我写入通道时,管道中的其他处理程序会看到HttpObjects,但HttpRequest实际上不会再次执行——只接收到一个HttpResponse

我认为在这种情况下我只是误用了通道,我需要创建一个新通道(表示到服务器的新连接)来执行重试。我不清楚的是如何从处理程序的上下文中创建新的通道,以及我是否真的在Netty的正确层中执行这种逻辑


任何关于如何实现我描述的行为的指导都将不胜感激。

您还需要在调用
write(…)
后调用
flush()
,否则它将不会刷新通道。此外,您还需要确保可能保留()和复制()
HttpContent
,否则您可能会尝试编写一个已发布的
HttpContent
对象

类似于此(未经测试):

公共类RetryChannelHandler扩展ChannelDuplexHandler{
队列请求部分;
@凌驾
public void write(ChannelHandlerContext ctx、对象消息、ChannelPromise承诺)引发异常{
if(HttpRequest的消息实例){
requestParts=newarraydeque();
add((HttpRequest)msg);
}else if(HttpContent的消息实例){
add((HttpContent)msg.duplicate().retain());
}
super.write(ctx、msg、promise);
}
@凌驾
public void channelRead(最终ChannelHandlerContext ctx,对象消息)引发异常{
if(HttpResponse的消息实例){
HttpResponse res=(HttpResponse)msg;
if(res.status().code()==503){
ctx.executor().schedule(新的Runnable()){
@凌驾
公开募捐{
httpobjectobj;
而((obj=requestParts.poll())!=null){
ctx.write(obj);
}
ctx.flush();
}
},1000,时间单位为毫秒);
}否则{
httpobjectobj;
而((obj=requestParts.poll())!=null){
ReferenceCountUtil.release(obj);
}
超级通道读取(ctx、msg);
}
}否则{
超级通道读取(ctx、msg);
}
}
}

谢谢!这解决了我的问题后,一个小的调整,以执行。
public class RetryChannelHandler extends ChannelDuplexHandler {
    Queue<HttpObject> requestParts;

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof HttpRequest) {
            requestParts = new ArrayDeque<>();
            requestParts.add((HttpRequest)msg);
        } else if (msg instanceof HttpContent) {
            requestParts.add(((HttpContent)msg).duplicate().retain());
        }

        super.write(ctx, msg, promise);
    }

    @Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpResponse) {
            HttpResponse res = (HttpResponse)msg;
            if (res.status().code() == 503) {
                ctx.executor().schedule(new Runnable() {
                    @Override
                    public void run() {
                        HttpObject obj;
                        while ((obj = requestParts.poll()) != null) {
                            ctx.write(obj);
                        }
                        ctx.flush();
                    }
                }, 1000, TimeUnit.MILLISECONDS);
            } else {
                HttpObject obj;
                while ((obj = requestParts.poll()) != null) {
                    ReferenceCountUtil.release(obj);
                }
                super.channelRead(ctx, msg);
            }
        } else {
            super.channelRead(ctx, msg);
        }
    }
}