Java 使用Netty HTTP客户端重试请求
如何在基于Netty的HTTP客户端中重试HTTP请求 考虑以下处理程序,如果收到HTTP响应代码503,该处理程序将在1秒后重试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
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);
}
}
}