Я написал базовый встроенный джет-сервер (с джерси для определения конечных точек), и мне нужно, чтобы он завершился изящно (в ответ на SIGINT). Я хотел бы, чтобы все запросы в полете завершили обработку и возвращали результаты запрашивающей стороне (вплоть до некоторого времени ожидания), не принимая новых подключений / запросов.
Текущее поведение, которое я наблюдаю, заключается в том, что запросы в полете выполняются правильно, но соединения с клиентами прерываются (поэтому они не получают ответы на свои запросы).
При создании экземпляра Server
я устанавливаю setStopAtShutdown
на true
и устанавливаю значение для setStopTimeout
. Я также настраиваю StatisticsHandler
. Из того, что я могу сказать из документов, это то, что требуется для включения изящного завершения.
Вот мой настроенный сервер:
// For additional Jetty configuration options see:
// https://www.eclipse.org/jetty/documentation/current/embedding-jetty.html#_like_jetty_xml
public static Server createServer(
int port, int shutdownGracePeriodMillis, int httpServerThreads, int httpIdleTimeoutMillis) {
// Create server
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(httpServerThreads);
Server server = new Server(threadPool);
HttpConfiguration config = new HttpConfiguration();
ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config));
http.setPort(port);
http.setIdleTimeout(httpIdleTimeoutMillis);
server.addConnector(http);
// Enable StatisticsHandler (required for graceful termination)
StatisticsHandler stats = new StatisticsHandler();
stats.setHandler(server.getHandler());
server.setHandler(stats);
ServerConnectionStatistics.addToAllConnectors(server);
// Configure graceful termination
server.setStopAtShutdown(true);
server.setStopTimeout(shutdownGracePeriodMillis);
// Associate Jersey with Jetty
JettyHttpContainer container =
ContainerFactory.createContainer(JettyHttpContainer.class, new AppResourceConfig());
server.setHandler(container);
return server;
}
Вот мой ресурс Джерси. Он использует Thread.sleep
для имитации некоторых длительных запросов, которые необходимо выполнить до выключения сервера.
@POST
@Consumes("application/json")
@Produces(MediaType.TEXT_PLAIN)
public String testEndpoint() {
for(int i = 0; i < 4; i++) {
try {
logger.info("Number: " + i);
Thread.sleep(5000);
} catch (Exception e) { }
}
logger.info("Request completed!");
return "Hello, world!\n";
}
Я запускаю сервер и запускаю следующую команду curl
curl -v --header "Content-Type: application/json" \
--request POST \
--data '' \
http://localhost:4200/testEndpoint
Когда я отправляю SIGINT процессу сервера, пока этот запрос все еще ожидает ответа, который я вижу на сервере:
INFO c.a.a.s.resources.Resource - Number: 0
INFO c.a.a.s.resources.Resource - Number: 1
^C {{NOTE: SIGINT issued here}}
[Thread-1] INFO o.e.jetty.server.AbstractConnector - Stopped ServerConnector@32c726ee{HTTP/1.1,[http/1.1]}{0.0.0.0:4200}
INFO c.a.a.s.resources.AuctionResource - Number: 2
INFO c.a.a.s.resources.AuctionResource - Number: 3
INFO c.a.a.s.resources.AuctionResource - Request completed!
Из журналов сервера видно, что запрос выполнен правильно. Команда curl никогда не получает ответ "Hello, world!" хотя (что он делает в обычном непрерывном запросе).
Вывод curl выглядит следующим образом:
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 4200 (#0)
> POST /testEndpoint HTTP/1.1
> Host: localhost:4200
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 0
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
Я ожидал, что получу правильный ответ от службы, но вместо этого получу пустой ответ от сервера. Какая дополнительная конфигурация требуется, чтобы не закрывать соединения запросов в полете во время корректного завершения для встроенного сервера Jetty?