#vert.x #vertx-httpclient
Вопрос:
Мне нужно установить тайм-аут запроса для нисходящего внутреннего вызова. Однако класс WebClient в Vert.x 3.9, похоже, работает не так, как я ожидал. Вот для этого есть некоторый тестовый код:
package client;
import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.ext.web.client.WebClient;
public class Timeout extends AbstractVerticle {
private static final int port = 8080;
private static final String host = "localhost";
private static final int timeoutMilliseconds = 50;
@Override
public void start() {
WebClient client = WebClient.create(vertx);
for (int i = 0; i < 100; i ) {
client.get(port, host, "/").timeout(timeoutMilliseconds).send(
ar -> {
if (ar.succeeded()) {
System.out.println("Success!");
} else {
System.out.println("Fail: " ar.cause().getMessage());
}
});
}
vertx.timerStream(1000).handler(aLong -> { vertx.close(); });
}
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new Timeout());
}
}
Я запускаю следующий сервер Go на том же хосте для тестирования:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", HelloServer)
http.ListenAndServe(":8080", nil)
}
func HelloServer(w http.ResponseWriter, r *http.Request) {
fmt.Println("Saying hello!")
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
Вывод для моего тестового сервера показывает, что WebClient открывает 5 одновременных подключений, и каждый запрос останавливается по времени ожидания. Что я здесь делаю не так? Как я должен установить время ожидания соединения для запросов? Вывод от клиента является:
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
...
Я ожидал бы увидеть только «Успех!», так как сервер Go, работающий на том же хосте, должен хорошо реагировать в течение 50 мс.
ИЗМЕНИТЬ: Удалил vertx.close() и уточнил исходный вопрос… На самом деле в моем исходном тестовом коде не было vertx.close (), но я добавил его при редактировании сообщения SO, чтобы людям, которые его запускают, не нужно было нажимать CTRL-C.
Комментарии:
1. какой смысл запускать vertx и убивать его сразу после этого? Вам скорее нужен простой сценарий запуска, чтобы выполнить некоторые запросы веб-клиента…
Ответ №1:
Он зависает, потому что вы блокируете основной поток.
Удалите это:
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
vertx.close();
Приложение будет работать до тех пор, пока vert.x жив.
Если вы действительно хотите закрыть vert.x самостоятельно, сделайте это в отдельном потоке.
Или, в качестве альтернативы, сделайте это с помощью самого Vert.x:
vertx.timerStream(1000).handler(aLong -> {
vertx.close();
});
Ответ №2:
не уверен, что вы пытаетесь там сделать, но есть несколько вещей, которые там неверны:
- в
AbstractVerticle.start()
вас только начинается логика. кроме того, если у вас асинхронная логика, вам необходимо использовать асинхронный интерфейс, напримерstart(Promise<Void> startPromise)
, и правильно сообщать о завершении, чтобы Vertx ждал завершения вашей начальной логики. - вы блокируете процесс запуска здесь:
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
пока это выполняется, ваша вершина на самом деле не запущена, и основной поток vertx заблокирован.
- вы никогда не закрываете vertx в начале вертикали! поэтому удалите эту строку
vertx.close()
и закройте запущенное приложение другим способом.
в общем, проверьте документы, чтобы понять процесс и использование вершин.
Комментарии:
1. Прояснил вопрос. Я вижу, как запускаются подобные запросы, например, здесь, поэтому я не думаю, что тайм-ауты вызваны блокировкой потока: how-to.vertx.io/http-client-howto
2. не знаю, что вы видите в ссылке, но на этой странице нет запроса, отправленного в методе запуска. операция отправки выполняется в периодическом таймере, который запускается вне основного потока.
3. @eof Исключили ли вы возможность того, что запрос просто занял более 50 мс (по какой-либо причине)? Сохраняется ли такое же поведение с такими значениями, как 500 или даже 1000?