Я пытаюсь создать клиент http на основе netty. Я написал код, основанный на примере HttpSnoopClient, приведенном на сайте Netty. Но проблема HttpResponse обрабатывается HttpSnoopClientHandler & HttpRequests отправляется в HttpSnoopClient и я хочу ее синхронизировать. как в случае, если я отправляю запрос, я хочу убедиться, что я отправлю следующий запрос, как только узнаю ответ на предыдущий. Но поскольку оба они обрабатываются в разных классах, становится трудно сделать то же самое.
Одна вещь, которую я сделал, это создать метод setResponse() в HttpTarget & HttpSnoopClientHandler будет устанавливать HttpResponse, когда он получит ответ от сервера. Но я не думаю, что это хороший подход, так как я не буду знать, что reposne был для этого запроса.
Поэтому в основном я хочу сделать это синхронно, то есть отправить запрос (channel.writeandFlush(req)) в HttpSnoopClient, а затем дождаться ответа ответа HttpSnoopCLientHandler и после получения HTTP 1.1 200 OK, а затем отправить следующий запрос.
Может ли кто-нибудь сказать мне хороший подход для этого. Заранее спасибо!
Когда вы создаете новый HttpSnoopClientHandler для каждого соединения, я бы рассмотрел возможность превращения HttpSnoopClientHandler в ChannelDuplexHandler. В методе write вы можете сохранить ссылку на исходящий HTTP-запрос. Когда ответ получен, вы можете вызвать метод setResponse с помощью (канал, запрос, ответ). Это должно обеспечить достаточный контекст, чтобы вы могли правильно обрабатывать ответ.
Если ваш клиент является чистым запросом/ответом, он не отправляет отдельные запросы отдельно, и вы хотите, чтобы поток вашего приложения обрабатывал ответы последовательно, вы можете использовать SynchronousQueue для координации ответов, позволяя продолжить основной поток. В качестве альтернативы ваш обратный вызов может обрабатывать ответы внутри страны.
Вы также можете расширить эту технику, чтобы использовать конвейерную обработку HTTP. Конвейерная обработка HTTP гарантирует, что ответы будут возвращены в том порядке, в котором будут выданы запросы. В HttpSnoopClientHandler вы поддерживаете очередь запросов. Когда каждый ответ возвращается, вы сопоставляете его с запросом в передней части очереди.
У меня был аналогичный вариант использования, когда мне приходилось блокировать одновременные запросы до завершения одного ресурса. Я реализовал ConcurrentHashMap<RequestKey, ArrayList<ChannelHandlerContext>>>
который будет содержать все параллельные запросы ChannelHandlerContext
(ctx) и по завершении первого запроса поднять событие, которое вызовет все остальные ctx, чтобы использовать кешированный ответ. Во всем этом я должен был убедиться, что для AUTO_READ
было установлено значение false
для тонкого контроля зерна по AUTO_READ
на каждом канале.
channelRead ->
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 ->
onCompletionEvent {
ctxList = map.get(reqKey).clone();
map.remove(reqKey);
for(blockedCtx : ctxList){
//respond back with cached response to each blockedCtx
}
}
@norman-maurer, ты бы дал тебе это!