Может ли AsyncHttpClient выполнять неблокирующие асинхронные вызовы HTTP?

Все,

Я пытаюсь решить, использовать ли NodeJS или Java для своего приложения. Я буду общаться с CouchDB через HTTP и хотел бы асинхронный неблокирующий дизайн, в котором поток моего приложения может обрабатывать дополнительные запросы, ожидая ответа на запрос от CouchDB.

Я бы предпочел использовать Java, и я несколько дней рассматривал AsyncHttpClient как потенциальное решение. Однако у меня возникли проблемы с пониманием библиотеки, и я думаю, что у меня может быть фундаментальное непонимание чего-то.

Я разместил суть здесь: https://gist.github.com/conorgil/5505603

Я ожидаю, что этот смысл распечатает «Запрос X отправлен!» И «Ответ X: что-то» для каждого запроса. Однако похоже, что вызов HTTP не выполняется (и, следовательно, обработчик не выполняется) до тех пор, пока каждый Future не вызовет get(). Раскомментирование строки 23 f.get() приводит к тому, что код работает как положено, но вызов Future#get() блокируется, верно? Есть ли способ просто предоставить функцию обратного вызова, которая выполняется после полного получения ответа HTTP без блокировки?

Что-то вроде следующего: 1) запрос поступает в основной поток 2) выполняется асинхронный неблокирующий HTTP-вызов CouchDB. Обработчик завершения регистрируется для обработки ответа от CouchDB 3) основной поток теперь свободен для обработки следующего запроса 4) HTTP-ответ от CouchDB поступает в какой-то момент, и зарегистрированный обработчик вызывается для выполнения некоторой бизнес-логики 5) основной поток продолжается просто обработка запросов (для запросов, которые не нужно попадать в CouchDB, на них можно ответить очень быстро)

Я что-то принципиально неправильно понимаю здесь? Возможно ли сделать что-то подобное на Java? Является ли AsyncHttpClient ответом? Этот вопрос связан, но не уверен, что что-то изменилось с 2011 года (Выполнить асинхронное подключение с библиотекой Java AsyncHttpClient?)

Поскольку NodeJS запускает цикл обработки событий, такое неблокирующее асинхронное поведение является стандартным. Вы просто зарегистрируете функцию обратного вызова для обработки ответа БД, когда он будет получен, а цикл событий тем временем просто обработает другие вещи.

Любые советы приветствуются.

Спасибо, Конор


person conorgil    schedule 03.05.2013    source источник
comment
Да, это. Посмотрите на vert.x   -  person Adam Gent    schedule 06.05.2013
comment
node.js вполне приличный в качестве легкого обратного прокси/шлюза с незначительной логикой приложения с coachdb просто из-за http-интерфейса дивана и простого асинхронного http-узла, встроенного в него. Java более эффективен для тяжелой логики приложения.   -  person Gabe Rainbow    schedule 05.12.2015


Ответы (2)


Основная цель AsyncHttpClient — неблокирующий HTTP, и я успешно использовал его для этого. Например, я запустил эту упрощенную версию вашего кода:

public class MyAsyncHttpClientTest {
  public static void main(String[] args) throws Exception {
    AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
    for (int i = 0; i < 10; i++) {
      asyncHttpClient.prepareGet("http://www.google.com")
        .execute(new CompletionHandler(i));
      System.out.println(String.format("Request %d sent! ", i));
      System.out.flush();
    }
  }
  static class CompletionHandler extends AsyncCompletionHandler<Void> {
    private final int reqNumber;
    public CompletionHandler(int reqNumber) { this.reqNumber = reqNumber; }
    @Override public Void onCompleted(Response response) throws Exception {
      System.out.println(String.format("Response %d: %s", reqNumber,
          response.getResponseBody()));
      return null;
    }
  }
}

Обратите внимание, что фьючерсы не задействованы. Он производит следующий вывод, как и следовало ожидать:

Request 0 sent! 
Request 1 sent! 
Request 2 sent! 
Request 3 sent! 
Request 4 sent! 
Request 5 sent! 
Request 6 sent! 
Request 7 sent! 
Request 8 sent! 
Request 9 sent! 
Response 1: <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.hr/">here</A>.
</BODY></HTML>

Response 0: <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.hr/">here</A>.
</BODY></HTML>

...

Беда только в том, что процесс висит, потому что нет кода, закрывающего клиент, но это отдельная история.

person Marko Topolnik    schedule 06.05.2013
comment
1) В документе AsyncCompletionHandler говорится, что значение T будет возвращено соответствующим Future, поэтому даже если вы не видите фьючерсы, они задействованы. 2) Я не думаю, что вы демонстрируете здесь неблокирующую часть. вы только что показали, что это на самом деле асинхронно. Для неблокировки нужно показать, что ahc-поток, выпустивший запрос, не всегда совпадает с тем, который обрабатывает ответ. Неблокирующие потоки должны запускать запрос и возвращаться в пул, а не ждать ответа. - person stelios.anastasakis; 18.07.2020
comment
you need to show that the ahc-thread that fired the request is not always the same as the one that processes the response -- один поток может запустить запрос, заблокировать необработанный ответ, а затем позволить другому потоку обработать его, так что он снова ничего не докажет. Окончательным доказательством здесь будет количество запросов, превышающее количество потоков, но этот ответ на самом деле не о таком уровне недоверия к AHC. - person Marko Topolnik; 18.07.2020
comment
Что касается комментария о фьючерсах, то это скорее придирка, показанный код не использует какие-либо фьючерсы. - person Marko Topolnik; 18.07.2020

Если вы можете улучшить свой http-сервер БД для поддержки асинхронного запроса, я предлагаю сделать это.

Обычно запросы Http Async реализуются с использованием REQUEST SUBMIT-> REQUEST ACCEPTED-> JOB POLLING -> JOB RESPONSE.

Запрос Asyn реализуется с использованием POST/PUT, где вы отправляете запрос и получаете 202 Accepted вместе с URL-адресом опроса в заголовке HTTP для асинхронного получения результата. Теперь вы можете опросить это, чтобы получить результат, если результат доступен, вы должны получить 200 OK с некоторым результатом в виде вывода xml/json/text, иначе вы можете получить HTTP-код ошибки, такой как 503 Service Unreachable.

person Juned Ahsan    schedule 03.05.2013