Netty клиент с синхронным ответом на запрос

1

Я пытаюсь создать клиент http на основе netty. Я написал код, основанный на примере HttpSnoopClient, приведенном на сайте Netty. Но проблема HttpResponse обрабатывается HttpSnoopClientHandler & HttpRequests отправляется в HttpSnoopClient и я хочу ее синхронизировать. как в случае, если я отправляю запрос, я хочу убедиться, что я отправлю следующий запрос, как только узнаю ответ на предыдущий. Но поскольку оба они обрабатываются в разных классах, становится трудно сделать то же самое.

Одна вещь, которую я сделал, это создать метод setResponse() в HttpTarget & HttpSnoopClientHandler будет устанавливать HttpResponse, когда он получит ответ от сервера. Но я не думаю, что это хороший подход, так как я не буду знать, что reposne был для этого запроса.

Поэтому в основном я хочу сделать это синхронно, то есть отправить запрос (channel.writeandFlush(req)) в HttpSnoopClient, а затем дождаться ответа ответа HttpSnoopCLientHandler и после получения HTTP 1.1 200 OK, а затем отправить следующий запрос.

Может ли кто-нибудь сказать мне хороший подход для этого. Заранее спасибо!

  • 1
    ПОЖАЛУЙСТА, НЕ УДАЛЯЙТЕ (я исправил это для вас в этом случае.)
Теги:
http
netty
httprequest
synchronization

2 ответа

0

Когда вы создаете новый HttpSnoopClientHandler для каждого соединения, я бы рассмотрел возможность превращения HttpSnoopClientHandler в ChannelDuplexHandler. В методе write вы можете сохранить ссылку на исходящий HTTP-запрос. Когда ответ получен, вы можете вызвать метод setResponse с помощью (канал, запрос, ответ). Это должно обеспечить достаточный контекст, чтобы вы могли правильно обрабатывать ответ.

Если ваш клиент является чистым запросом/ответом, он не отправляет отдельные запросы отдельно, и вы хотите, чтобы поток вашего приложения обрабатывал ответы последовательно, вы можете использовать SynchronousQueue для координации ответов, позволяя продолжить основной поток. В качестве альтернативы ваш обратный вызов может обрабатывать ответы внутри страны.

Вы также можете расширить эту технику, чтобы использовать конвейерную обработку HTTP. Конвейерная обработка HTTP гарантирует, что ответы будут возвращены в том порядке, в котором будут выданы запросы. В HttpSnoopClientHandler вы поддерживаете очередь запросов. Когда каждый ответ возвращается, вы сопоставляете его с запросом в передней части очереди.

  • 0
    Разве SynchronousQueue не будет блокировать событие EventLoop?
  • 0
    Я не очень хорошо себя объяснил. Я предполагаю, что вы хотите обрабатывать запросы / ответ синхронно в вашем основном потоке, поэтому ваш основной поток отправляет запрос, а затем сразу же запрашивает (и блокирует) ответ. Хэндовер между циклом событий и основным потоком будет происходить за время, необходимое для выполнения соответствующего переключения контекста. Этого может быть достаточно, особенно если вы не обрабатываете параллельные запросы.
0

У меня был аналогичный вариант использования, когда мне приходилось блокировать одновременные запросы до завершения одного ресурса. Я реализовал 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, ты бы дал тебе это!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню