Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / HttpServer - утечка соектов / 18 сообщений из 18, страница 1 из 1
02.12.2018, 21:37
    #39741766
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Есть такое вот поделие.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
    @Override
    public void handle(HttpExchange httpExchange) throws IOException {
        ....
        ....
                WebTarget webTarget = httpClientHolder.getClient().target(url);
                try (Response response = webTarget.request().get()) {
                    if (response.getStatusInfo().getStatusCode() != HttpStatus.SC_OK) {
                        logger.warn("Failed to download resource, url = " + url + " code = " +
                                response.getStatusInfo().getStatusCode());
                        throw new HttpException("Not found", 404);
                    }
                    httpExchange.sendResponseHeaders(200, response.getLength());
                    final InputStream is = response.readEntity(InputStream.class);
                    try (final OutputStream os = httpExchange.getResponseBody()) {
                        IOUtils.copy(is, os, 128);
                    } catch (IOException e) {
                        logger.warn("Error proxy data: " + e.getMessage());
                    }
                }
        ....
    }



Проблема в том, что иногда выпадает исключение при попытке закрыть OutputStream

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
java.io.IOException: Broken pipe
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method) ~[?:1.8.0_191]
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47) ~[?:1.8.0_191]
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[?:1.8.0_191]
        at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[?:1.8.0_191]
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[?:1.8.0_191]
        at sun.net.httpserver.Request$WriteStream.write(Request.java:391) ~[?:1.8.0_191]
        at sun.net.httpserver.FixedLengthOutputStream.write(FixedLengthOutputStream.java:78) ~[?:1.8.0_191]
        at sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:444) ~[?:1.8.0_191]
        at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2315) ~[cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
        at org.apache.commons.io.IOUtils.copy(IOUtils.java:2270) ~[cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
        at server.TimelineVttHandler.handle(TimelineVttHandler.java:129) [cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
        at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
        at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) [?:1.8.0_191]
        at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) [?:1.8.0_191]
        at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) [?:1.8.0_191]
        at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
        at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) [?:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]
        Suppressed: java.io.IOException: insufficient bytes written to stream
                at sun.net.httpserver.FixedLengthOutputStream.close(FixedLengthOutputStream.java:89) ~[?:1.8.0_191]
                at sun.net.httpserver.PlaceholderOutputStream.close(ExchangeImpl.java:454) ~[?:1.8.0_191]
                at server.TimelineVttHandler.handle(TimelineVttHandler.java:130) [cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
                at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
                at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) [?:1.8.0_191]
                at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) [?:1.8.0_191]
                at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) [?:1.8.0_191]
                at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
                at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) [?:1.8.0_191]
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
                at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]



Как я понял, проблема в том, что пока мы пишем - клиент отваливается и дописать не получается.

Оно происходит редко и в общем-то никто не жаловался. Вот только сокет остается жить в таком виде до завершения работы программы:

Код: plaintext
1.
2.
3.
4.
lsof -n -p 14121  | grep TCPv6
java    13161 cache  143u     sock                0,9      0t0 3617991518 protocol: TCPv6
java    13161 cache  180u     sock                0,9      0t0 3618027565 protocol: TCPv6
java    13161 cache  184u     sock                0,9      0t0 3618017649 protocol: TCPv6

Виден он только в lsof, в netstat - отсутствует, но думаю это не важно.

Естественно в конце концов упираемся в ulimit.
Как правильно обработать эту ситуацию?
...
Рейтинг: 0 / 0
02.12.2018, 22:39
    #39741777
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Про исключение я не правильно наверное написал. Сначала ошибка записи, а потом при закрытии еще одно исключение, которое поглощено?
...
Рейтинг: 0 / 0
03.12.2018, 08:38
    #39741825
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettКак правильно обработать эту ситуацию?- показать тут строку на которой исключение.
- сделать тест именно на.... Клиент отвалился.
- убрать автоматическое освобождение ресурсов и пробу ручного закрытия канала и ресурсов.
- пробовать и сравнить с другими библиотеками и версиями.
...
Рейтинг: 0 / 0
03.12.2018, 08:47
    #39741826
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Вроде вот так решилось:


Код: java
1.
2.
3.
4.
5.
6.
                    try (final OutputStream os = httpExchange.getResponseBody()) {
                        IOUtils.copy(is, os, 128);
                    } catch (IOException e) {
                        logger.warn("Error proxy data", e);
                        throw e;
                    }



Т.е. выбрасываем IOException из хендлера. На этму мысль меня навел контракт метода `handle`.

Вчера с десяток примеров пересмотрел и доку оракловскую читал, ничего такого не нашел (хотя может и не обратил внимания).
...
Рейтинг: 0 / 0
03.12.2018, 08:52
    #39741827
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Как-то можно настроить log4j2 так, чтобы он не записывал stacktrace на проде ?

Код: java
1.
logger.warn("Error proxy data", e);
...
Рейтинг: 0 / 0
03.12.2018, 08:57
    #39741828
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettТ.е. выбрасываем IOException из хендлера.скорее ты его сам подавил и выше блок с try( ничего не знал об этом.
...
Рейтинг: 0 / 0
03.12.2018, 09:00
    #39741829
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Petro123HettТ.е. выбрасываем IOException из хендлера.скорее ты его сам подавил и выше блок с try( ничего не знал об этом.
Ну как бы да, но я же все ресурсы закрыл.
...
Рейтинг: 0 / 0
03.12.2018, 09:00
    #39741830
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettКак-то можно настроить log4j2 так, чтобы он не записывал stacktrace на проде ?

Код: java
1.
logger.warn("Error proxy data", e);

на проде свой конфиг или в конфине переменная окружения операционки.
...
Рейтинг: 0 / 0
03.12.2018, 09:03
    #39741831
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettНу как бы да, но я же все ресурсы закрыл.фиг знает. Значит автомат не работает если в catch ничего нет кроме логирования.
...
Рейтинг: 0 / 0
03.12.2018, 09:04
    #39741832
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Petro123HettКак-то можно настроить log4j2 так, чтобы он не записывал stacktrace на проде ?

Код: java
1.
logger.warn("Error proxy data", e);

на проде свой конфиг или в конфине переменная окружения операционки.

Понятно что свой. Собственно вопрос в этом и был, как в конфиге указать чтобы он стек-трейсы не валил в лог.
...
Рейтинг: 0 / 0
03.12.2018, 09:07
    #39741833
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Hett,
Конфиг не знаю, тему создай.
Я бы warn поменял на info или debug.
Удачи!
...
Рейтинг: 0 / 0
03.12.2018, 09:28
    #39741841
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettКак-то можно настроить log4j2 так, чтобы он не записывал stacktrace на проде ?

Код: java
1.
logger.warn("Error proxy data", e);



а в логге была просто запись Error proxy data?
...
Рейтинг: 0 / 0
03.12.2018, 09:29
    #39741842
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettЕсть такое вот поделие.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
    @Override
    public void handle(HttpExchange httpExchange) throws IOException {
        ....
        ....
                WebTarget webTarget = httpClientHolder.getClient().target(url);
                try (Response response = webTarget.request().get()) {
                    if (response.getStatusInfo().getStatusCode() != HttpStatus.SC_OK) {
                        logger.warn("Failed to download resource, url = " + url + " code = " +
                                response.getStatusInfo().getStatusCode());
                        throw new HttpException("Not found", 404);
                    }
                    httpExchange.sendResponseHeaders(200, response.getLength());
                    final InputStream is = response.readEntity(InputStream.class);
                    try (final OutputStream os = httpExchange.getResponseBody()) {
                        IOUtils.copy(is, os, 128);
                    } catch (IOException e) {
                        logger.warn("Error proxy data: " + e.getMessage());
                    }
                }
        ....
    }



Проблема в том, что иногда выпадает исключение при попытке закрыть OutputStream

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
java.io.IOException: Broken pipe
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method) ~[?:1.8.0_191]
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47) ~[?:1.8.0_191]
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[?:1.8.0_191]
        at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[?:1.8.0_191]
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[?:1.8.0_191]
        at sun.net.httpserver.Request$WriteStream.write(Request.java:391) ~[?:1.8.0_191]
        at sun.net.httpserver.FixedLengthOutputStream.write(FixedLengthOutputStream.java:78) ~[?:1.8.0_191]
        at sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:444) ~[?:1.8.0_191]
        at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2315) ~[cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
        at org.apache.commons.io.IOUtils.copy(IOUtils.java:2270) ~[cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
        at server.TimelineVttHandler.handle(TimelineVttHandler.java:129) [cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
        at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
        at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) [?:1.8.0_191]
        at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) [?:1.8.0_191]
        at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) [?:1.8.0_191]
        at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
        at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) [?:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]
        Suppressed: java.io.IOException: insufficient bytes written to stream
                at sun.net.httpserver.FixedLengthOutputStream.close(FixedLengthOutputStream.java:89) ~[?:1.8.0_191]
                at sun.net.httpserver.PlaceholderOutputStream.close(ExchangeImpl.java:454) ~[?:1.8.0_191]
                at server.TimelineVttHandler.handle(TimelineVttHandler.java:130) [cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
                at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
                at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) [?:1.8.0_191]
                at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) [?:1.8.0_191]
                at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) [?:1.8.0_191]
                at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
                at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) [?:1.8.0_191]
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
                at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]



Как я понял, проблема в том, что пока мы пишем - клиент отваливается и дописать не получается.

Оно происходит редко и в общем-то никто не жаловался. Вот только сокет остается жить в таком виде до завершения работы программы:

Код: plaintext
1.
2.
3.
4.
lsof -n -p 14121  | grep TCPv6
java    13161 cache  143u     sock                0,9      0t0 3617991518 protocol: TCPv6
java    13161 cache  180u     sock                0,9      0t0 3618027565 protocol: TCPv6
java    13161 cache  184u     sock                0,9      0t0 3618017649 protocol: TCPv6

Виден он только в lsof, в netstat - отсутствует, но думаю это не важно.

Естественно в конце концов упираемся в ulimit.
Как правильно обработать эту ситуацию?

а как часто такие запросы происходят?
...
Рейтинг: 0 / 0
03.12.2018, 09:43
    #39741845
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
ОзверинHettКак-то можно настроить log4j2 так, чтобы он не записывал stacktrace на проде ?

Код: java
1.
logger.warn("Error proxy data", e);



а в логге была просто запись Error proxy data?

Ну запись и стек-трейс, я привел в первом посте это :)
...
Рейтинг: 0 / 0
03.12.2018, 09:45
    #39741846
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
автора как часто такие запросы происходят?
Около 1000 в сутки на одну ноду. Как я понял просто клиент прерывает соединение до того, как получил данные, вот и вся "проблема".
...
Рейтинг: 0 / 0
03.12.2018, 18:00
    #39742120
qasta
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
Озверин,

Не знаю, может ли с этим быть связано - вы не закрываете InputStream - его тоже надо добавить в try() {} (в try-with-resources можно добавлять сразу несколько записей). То есть получится что-то вроде
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
@Override
    public void handle(HttpExchange httpExchange) throws IOException {
        ....
        ....
                WebTarget webTarget = httpClientHolder.getClient().target(url);
                try (Response response = webTarget.request().get()) {
                    if (response.getStatusInfo().getStatusCode() != HttpStatus.SC_OK) {
                        logger.warn("Failed to download resource, url = " + url + " code = " +
                                response.getStatusInfo().getStatusCode());
                        throw new HttpException("Not found", 404);
                    }
                    httpExchange.sendResponseHeaders(200, response.getLength());
                    
                    try (final InputStream is = response.readEntity(InputStream.class);
                          final OutputStream os = httpExchange.getResponseBody()) {
                        IOUtils.copy(is, os, 128);
                    } catch (IOException e) {
                        logger.warn("Error proxy data: " + e.getMessage());
                    }
                }
        ....
    }



Ну, раз проблему уже решили, причем через другой способ работы с httpExchange, то и так гуд - видать утекали "серверные" сокеты, а не "клиентские". Тем более, что Response.close() должен по-идее закрыть и InputStream.
...
Рейтинг: 0 / 0
03.12.2018, 18:32
    #39742128
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
авторТем более, что Response.close() должен по-идее закрыть и InputStream.
Да, он закрывается.
Я кстати пробовал и вариант с его закрытим даже сначала. Но ничего не изменилось.

Стоит ли закрывать инпут стрим из чисто эстетических соображений?
...
Рейтинг: 0 / 0
03.12.2018, 19:48
    #39742148
qasta
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpServer - утечка соектов
HettСтоит ли закрывать инпут стрим из чисто эстетических соображений?

Часто применяется правило - где "открыл/создал" ресурс - там и закрывай (на том же "уровне").
Поэтому, я бы его закрывал - раз лишних try-catch-ей это не тянет за собой. Но это реально "вкусовщина" и "эстетство" :)

P.S. Оффтоп. Вообще, это правило здорово помогает. Например, при работе с JDBC ресурсами при закрытии Connection-а автоматически закрываются связанные с ним PreparedStatement-ы, ResultSet-ы и т.п. Казалось бы - закрывай только connection и всё. Но это не срабатывает при использовании пула соединений, т.к. физически соединение не закрывается, а возвращается в пул.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / HttpServer - утечка соектов / 18 сообщений из 18, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]