我正在尝试基于netty创建一个http客户端。我已经根据Netty站点中给出的HttpSnoopClient example编写了代码。但问题是HttpResponse由HttpSnoopClientHandler&处理。 HttpRequests在HttpSnoopClient&我想同步它。如果我发送请求,我想确保一旦我知道对前一个的响应,我将发送下一个请求。但由于两者都是在不同的阶层处理,因此也很难做到这一点。
我做的一件事是在HttpTarget&中创建一个setResponse()方法。当HttpSnoopClientHandler从服务器接收到响应时,它将设置HttpResponse。但我不认为这是一个很好的方法,因为我无法知道reposne是针对哪个请求。
所以基本上我想同步这样做,即在HttpSnoopClient中发送请求(channel.writeandFlush(req)),然后等待HttpSnoopCLientHandler&收到响应。一旦收到HTTP 1.1 200 OK,就发送下一个请求。
任何人都可以告诉我这样做的好方法。提前谢谢!
答案 0 :(得分:0)
我有一个类似的用例,我必须阻止并发请求,直到一个资源完成。我实现了一个ConcurrentHashMap<RequestKey, ArrayList<ChannelHandlerContext>>>
,它将保存所有并发请求ChannelHandlerContext
(ctx),并在第一个请求完成时引发一个事件,该事件将触发所有其他ctx使用缓存的响应。在所有这些中,我必须确保将AUTO_READ
设置为false
,以便对每个通道上的读取进行细粒度控制。
channelRead - &gt;
if(map.contains(reqKey)){
map.add(reqKey, list.add(ctx))
//do nothing with AUTO_READ = false and do not initiate any ctx.* methods
}else{
//firstRequest
map.add(reqKey, new ArrayList<CTX>(){{ add(ctx);}})
//continue with request execution
//cache response and raise event on completion
}
userEventTriggered - &gt;
onCompletionEvent {
ctxList = map.get(reqKey).clone();
map.remove(reqKey);
for(blockedCtx : ctxList){
//respond back with cached response to each blockedCtx
}
}
@ norman-maurer你愿意接受这个!!! //
答案 1 :(得分:0)
当你为每个连接创建一个新的HttpSnoopClientHandler时,我会考虑将HttpSnoopClientHandler转换为ChannelDuplexHandler。在write方法中,您可以存储对传出http请求的引用。收到响应后,您可以使用(通道,请求,响应)调用setResponse方法。这应该提供足够的上下文,以便您可以正确处理响应。
如果您的客户端是纯请求/响应,不会单独发出不相关的请求,并且您希望应用程序线程按顺序处理响应,那么您可以使用SynchronousQueue协调响应并允许主线程继续。或者,您的回调可以在内部处理响应。
您还可以扩展此技术以使用HTTP流水线。 HTTP流水线保证响应按发出请求的顺序返回。在HttpSnoopClientHandler中,您维护一个请求队列。返回每个响应时,您将其与队列前面的请求进行匹配。