Сброс соединения с помощью однорангового узла с асинхронным http-клиентом и netty

У меня странная проблема с асинхронным http-клиентом с netty в качестве http-провайдера, это игровое приложение, вызывающее удаленный веб-сервис, к которому у нас нет доступа. Также важно отметить, что служба находится в домене с шифрованием SSL и отвечает только на этот домен, а не на IP-адрес. Трассировки стека:

java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.read0(Native Method) ~[na:1.7.0_60]
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) ~[na:1.7.0_60]
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) ~[na:1.7.0_60]
at sun.nio.ch.IOUtil.read(IOUtil.java:192) ~[na:1.7.0_60]
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:379) ~[na:1.7.0_60]
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:64) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:108) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178) ~[netty-3.9.2.Final.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_60]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_60]

Самое странное, что это произошло внезапно (это тестовая среда, используемая клиентом), что заставляет меня поверить, что что-то не так либо с принимающей службой, либо с сетью, но я не могу понять, что не так, потому что вызов того же URL-адреса с помощью curl работает отлично.

Я попытался изолировать проблему, используя асинхронный http-клиент (который игра использует для своего интерфейса WS) локально и получил ту же ошибку, curl работает, также работает javas URL-api. Кроме того, когда я использую JDKAsyncHttpProvider в качестве поставщика http, он также отлично работает.

   try {
        AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder().build();
        // works if I use JDKAsyncHttpProvider..
        //AsyncHttpClient asyncHttpClient = new AsyncHttpClient(new JDKAsyncHttpProvider(cf));
        AsyncHttpClient asyncHttpClient = new AsyncHttpClient(cf);

        Future<Response> f = asyncHttpClient.prepareGet(nw).execute();
        Response r = f.get();

        System.out.println(r.getResponseBody());
    } catch(Exception e) {
        e.printStackTrace();
    }

Поскольку я использую игровую среду, я не могу изменить поставщика.

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

Обновление: со всеми параметрами отладки я получаю следующую ошибку:

Extension ec_point_formats, formats: [uncompressed]
***
[write] MD5 and SHA1 hashes:  len = 149
0000: 01 00 00 91 03 01 53 AD   17 DD 91 78 24 7E 9A 58  ......S....x$..X
0010: 0E CA D9 ED 22 5A A9 DF   3F 4C DD 25 58 E1 E6 C1  ...."Z..?L.%X...
0020: 4C 63 3E 11 78 1E 00 00   2A C0 09 C0 13 00 2F C0  Lc>.x...*...../.
0030: 04 C0 0E 00 33 00 32 C0   07 C0 11 00 05 C0 02 C0  ....3.2.........
0040: 0C C0 08 C0 12 00 0A C0   03 C0 0D 00 16 00 13 00  ................
0050: 04 00 FF 01 00 00 3E 00   0A 00 34 00 32 00 17 00  ......>...4.2...
0060: 01 00 03 00 13 00 15 00   06 00 07 00 09 00 0A 00  ................
0070: 18 00 0B 00 0C 00 19 00   0D 00 0E 00 0F 00 10 00  ................
0080: 11 00 02 00 12 00 04 00   05 00 14 00 08 00 16 00  ................
0090: 0B 00 02 01 00                                     .....
New I/O worker #2, WRITE: TLSv1 Handshake, length = 149
[Raw write]: length = 154
0000: 16 03 01 00 95 01 00 00   91 03 01 53 AD 17 DD 91  ...........S....
0010: 78 24 7E 9A 58 0E CA D9   ED 22 5A A9 DF 3F 4C DD  x$..X...."Z..?L.
0020: 25 58 E1 E6 C1 4C 63 3E   11 78 1E 00 00 2A C0 09  %X...Lc>.x...*..
0030: C0 13 00 2F C0 04 C0 0E   00 33 00 32 C0 07 C0 11  .../.....3.2....
0040: 00 05 C0 02 C0 0C C0 08   C0 12 00 0A C0 03 C0 0D  ................
0050: 00 16 00 13 00 04 00 FF   01 00 00 3E 00 0A 00 34  ...........>...4
0060: 00 32 00 17 00 01 00 03   00 13 00 15 00 06 00 07  .2..............
0070: 00 09 00 0A 00 18 00 0B   00 0C 00 19 00 0D 00 0E  ................
0080: 00 0F 00 10 00 11 00 02   00 12 00 04 00 05 00 14  ................
0090: 00 08 00 16 00 0B 00 02   01 00                    ..........
09:06:05.883 [New I/O worker #2] DEBUG c.n.h.c.p.n.NettyAsyncHttpProvider - Unexpected I/O exception on channel [id: 0x9820cfc1, /192.168.101.123:41411 => domain/148.136.157.62:443]
java.io.IOException: Connection reset by peer

Итак, что-то не так с рукопожатием TLS, есть ли что-то еще, что я могу сделать при отладке этой проблемы без доступа к удаленной службе?

Обновите снова, на этот раз появилось новое сообщение об ошибке:

[write] MD5 and SHA1 hashes:  len = 149
0000: 01 00 00 91 03 01 53 AD   1C 54 D6 57 05 7A 89 E5  ......S..T.W.z..
0010: 55 60 01 2F 48 A5 BA EB   4C E6 96 68 E7 B8 2B 67  U`./H...L..h..+g
0020: A2 4C AF C8 9D 10 00 00   2A C0 09 C0 13 00 2F C0  .L......*...../.
0030: 04 C0 0E 00 33 00 32 C0   07 C0 11 00 05 C0 02 C0  ....3.2.........
0040: 0C C0 08 C0 12 00 0A C0   03 C0 0D 00 16 00 13 00  ................
0050: 04 00 FF 01 00 00 3E 00   0A 00 34 00 32 00 17 00  ......>...4.2...
0060: 01 00 03 00 13 00 15 00   06 00 07 00 09 00 0A 00  ................
0070: 18 00 0B 00 0C 00 19 00   0D 00 0E 00 0F 00 10 00  ................
0080: 11 00 02 00 12 00 04 00   05 00 14 00 08 00 16 00  ................
0090: 0B 00 02 01 00                                     .....
New I/O worker #2, WRITE: TLSv1 Handshake, length = 149
[Raw write]: length = 154
0000: 16 03 01 00 95 01 00 00   91 03 01 53 AD 1C 54 D6  ...........S..T.
0010: 57 05 7A 89 E5 55 60 01   2F 48 A5 BA EB 4C E6 96  W.z..U`./H...L..
0020: 68 E7 B8 2B 67 A2 4C AF   C8 9D 10 00 00 2A C0 09  h..+g.L......*..
0030: C0 13 00 2F C0 04 C0 0E   00 33 00 32 C0 07 C0 11  .../.....3.2....
0040: 00 05 C0 02 C0 0C C0 08   C0 12 00 0A C0 03 C0 0D  ................
0050: 00 16 00 13 00 04 00 FF   01 00 00 3E 00 0A 00 34  ...........>...4
0060: 00 32 00 17 00 01 00 03   00 13 00 15 00 06 00 07  .2..............
0070: 00 09 00 0A 00 18 00 0B   00 0C 00 19 00 0D 00 0E  ................
0080: 00 0F 00 10 00 11 00 02   00 12 00 04 00 05 00 14  ................
0090: 00 08 00 16 00 0B 00 02   01 00                    ..........
Hashed wheel timer #2, called closeOutbound()
Hashed wheel timer #2, closeOutboundInternal()
Hashed wheel timer #2, SEND TLSv1 ALERT:  warning, description = close_notify
Hashed wheel timer #2, WRITE: TLSv1 Alert, length = 2
Hashed wheel timer #2, called closeInbound()
Hashed wheel timer #2, fatal error: 80: Inbound closed before receiving peer's close_notify: possible truncation attack?
javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
Hashed wheel timer #2, SEND TLSv1 ALERT:  fatal, description = internal_error
Hashed wheel timer #2, Exception sending alert: java.io.IOException: writer side was already closed.

Обновлено, исправлено:

Удаленный хост настроил https-сертификат для использования индикации имени сервера, SNI, что привело к сбою сетевого провайдера. Я предполагаю, что сетевой провайдер еще не поддерживает SNI.


person r0stig    schedule 26.06.2014    source источник
comment
Сброс соединения узлом означает, что удаленный конец соединения закрыл его. Вам нужно выяснить, почему удаленное программное обеспечение разрывает соединение.   -  person Kenster    schedule 26.06.2014
comment
Это я выяснил, но почему я получаю сообщение об ошибке только тогда, когда я использую провайдера Netty, а не когда я использую завиток в терминале или как в моем примере с JDKAsyncHttpProvider?   -  person r0stig    schedule 26.06.2014
comment
Я не знаю, но выяснить, почему удаленное программное обеспечение разрывает соединение, было бы большой подсказкой.   -  person Kenster    schedule 26.06.2014
comment
Удаленная служба принадлежит другой компании, и единственное, что я от них узнал, это то, что ничего не регистрируется (я думаю, что они используют IIS с .Net webAPI). Думаю, я спрашиваю, могу ли я убедиться, что это не вина с моей стороны.   -  person r0stig    schedule 26.06.2014


Ответы (2)


Когда вы говорите «зашифрованный домен SSL», вы имеете в виду HTTPS?

Если это так, вы можете использовать функцию отладки в WS SSL: http://www.playframework.com/documentation/2.3.x/DebuggingSSL

или установите флаги отладки JSSE напрямую с помощью -Djavax.net.debug=all.

Также включите logger.play.api.libs.ws=DEBUG и logger.org.asynchttpclient=DEBUG в application.conf для максимальной детализации.

Вы также можете изменить провайдера напрямую, если хотите использовать AsyncHttpClient напрямую, без использования WS. Это будет означать, что вам, возможно, придется возиться с обещанием в обратном вызове onSuccess(), но вы создаете ограниченный WS-подобный интерфейс, который вернет вам будущее, если это проблема.

person Will Sargent    schedule 27.06.2014
comment
Спасибо, у меня есть более интересные результаты отладки. Я обновил вопрос. - person r0stig; 27.06.2014

У меня такая же проблема. Я смог решить эту проблему, переключившись с Java 6 на Java 7. Это проблема с указанием имени сервера (SNI), которая не поддерживается в Java 6, но поддерживается в Java 7.

person Roger Chang    schedule 03.10.2014