Джерси: закрыть ресурсы ввода / вывода после ответа HTTP - PullRequest
0 голосов
/ 22 ноября 2018

Мои настройки: Я создал службу REST (Jersey / Dropwizard), которая транслирует большой контент из базы данных.Во время операции GET служба подключается к базе данных через пул соединений, упаковывает данные в поток и выполняет некоторое оперативное преобразование для отображения запрошенных данных в различных кодировках (CSV, JSON, ...).Время жизни соединения с базой данных связано с временем жизни потока, и только когда поток закрыт, соединение с базой данных освобождается.

Преобразование потока выполняется классом Encoder, который возвращает StreamingOutput , который затем передается объекту Response.Кодировщик в настоящее время обрабатывает закрытие ресурса, когда поток полностью используется.

Моя проблема: Поскольку StreamingOutput не реализует AutoCloseable , утечки соединения могут возникать, когда выход используется только частично.

Иногда я наблюдаю, как устаревшие активные соединения накапливаются в пуле соединений, и я подозреваю, что они возникают из-за прерванных HTTP-соединений.Как вы можете видеть ниже, текущий код обрабатывает исключения, возникающие в блоке try .Я не могу обработать исключения, возникающие после оператора return, и я не знаю, как прикрепить какие-либо инструкции по закрытию ресурса к объекту Response .

Мой вопрос: Как я могу сообщить объекту Response о закрытии определенных ресурсов после завершения запроса (регулярно или из-за ошибки)?Или: есть ли лучший способ безопасно закрыть любые связанные ресурсы, когда контекст запроса заканчивается?

 @GET
 //@Produces(...)
 public Response streamData(
        @PathParam("key") String key,
        // ... other params
        ) {

    //decode and validate params
    Stream<Pojo> ps = null;
    try {
        // connect to db and obtain data stream for <key>
        ps = loadData(db, key);
        // apply detailed encoding instrunctions and create a StreamingOutput
        final StreamingOutput stream = Encoder.encodeData(ps, encodingArgs);
        return Response.ok(stream).build();
    } catch (Exception e) {
        closeOnException(ps); // wrapper for ps.close();
        throw e;
    }
 }

Ответы [ 2 ]

0 голосов
/ 23 марта 2019

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

https://groups.google.com/forum/#!topic/dropwizard-user/62GoLDBrQuo

Цитирование от ШонаОтвет:

Джерси поддерживает CloseableService , что позволяет регистрировать закрываемые объекты, которые будут закрыты после завершения запроса:

public Response streamData(..., @Context CloseableService closer) {
  ...
  closer.add(closeable);
  return Response.ok(...).build();
}
0 голосов
/ 22 ноября 2018

Вы можете добавить в свой метод HttpServletResponse:

@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Object streamData(
            @PathParam("key") String key,
            @Context HttpServletResponse response,
            // ... other params
            ) {
  ...
  response.getOutputStream().write(....)
  response.flushBuffer();
  response.getOutputStream().close();
  return null;
}
...