Какая правильная технология / уровень сердцебиения / поддержания активности для Java REST? HTTP? TCP? Кодировка: фрагментированная?

Настройка:

У нас есть сайт https://Main.externaldomain/xmlservlet, который выполняет аутентификацию / проверку / геолокацию и прокси-запросы (слегка измененные) к http://London04.internaldomain/xmlservlet, например.

Прямого доступа к внутреннему домену для конечных пользователей нет вообще. Связь между сайтами иногда прерывается, а иногда узлы внутреннего домена становятся недоступными / мертвыми.

На основном сайте используется org.apache.http.impl.client.DefaultHttpClient (я знаю, что он устарел, мы постепенно обновляем этот устаревший код) с readTimeout, установленным на 10.000 миллисекунд. Запрос и ответ имеют полезную нагрузку / тело xml переменной длины, и используется Transfer-Encoding: chunked, также используется Keep-Alive: timeout=15.

Проблема:

Иногда для выполнения London04 требуется более 10 секунд (скажем, 2 минуты). Иногда он не изящно вылетает. Иногда случаются другие (сетевые) проблемы. Иногда в течение этих 2 минут - части response-xml-data заполняются настолько постепенно, что между частями нет 10-секундных промежутков, и поэтому readTimeout никогда не превышается, иногда есть 10-секундный промежуток, и HttpClient истекает ...

Мы могли бы попытаться увеличить тайм-аут на стороне Main, но это легко раздуло бы / перегрузило пул слушателей (просто из-за обычного трафика, даже не подвергаясь DDOS-атаке). Нам нужен способ отличать внутренний-сайт-все еще-работает-над-генерированием-ответом от случаев, когда он действительно дает сбой / network_lost / и т. Д. И самое лучшее - это какое-то сердцебиение (каждые 5 секунд) во время общения.

Мы думали, что Keep-Alive спасет нас, но, похоже, он только защищает промежутки между запросами (а не во время запросов) и, кажется, не делает никаких пульсаций во время разрыв (просто наличие / wait_for тайм-аута).

Мы думали, что фрагментированное кодирование может спасти нас, посылая некоторое сердцебиение (фрагменты размером 0 байт), чтобы другая сторона знала, но, похоже, нет такой / стандартной реализации поддержки любого сердцебиения таким образом и более того, поэтому кажется, что 0- Чанк размером в байты сам по себе является индикатором EOD ...

Вопрос (ы):

Если мы правы в предположении, что KeepAlive / ChunkedEncoding не поможет нам в достижении keepAlive / Hearbeat / fastDetectionOfDeadBackend, тогда:

1) на каком слое лучше реализовать такое сердцебиение? HTTP? TCP?

2) какой-либо стандартный фреймворк / библиотека / настройка / и т.д., уже реализующий его? (если возможно: Java, REST)


ОБНОВЛЕНИЕ

Я также изучил средства поддержки активности для WADL / WSDL, хотя не нашел ни одного для REST, проверил WebSockets ... Также изучил пакеты поддержки активности TCP, которые кажутся подходящими для задачи:

НО в соответствии с ними мне пришлось бы настроить что-то вроде:

  • tcp_keepalive_time = 5
  • tcp_keepalive_intvl = 1
  • tcp_keepalive_probes = 3

что кажется встречной рекомендацией (рекомендуется 2 часа, 10 минут уже представлены как нечетное значение, переходят к 5 с нормальным / безопасным? если это так - может быть, мое решение заранее ...)

также где я должен это настроить? только на London04 или на Main тоже? (если я настрою его на Main - не будет ли он затоплять клиента -> Main frontend-коммуникация? или могут ли NAT и т. д. между сайтами легко разрушить намерение / поддержку keepalive?)

P.S. любая ссылка на RTFM приветствуется - возможно, мне просто не хватает чего-то очевидного :)


person Vlad    schedule 25.02.2019    source источник


Ответы (2)


Я бы посоветовал не использовать сердцебиение. Ваш внешний API должен возвращать 303 See Other с заголовками, которые указывают, когда и где желаемый ответ может быть доступен.

Так что вы можете позвонить:

POST https://public.api/my/call

и вернуться

303 See Other
Location: "https://public.api/my/call/results"
Retry-After: 10

Если ваш сервер может угадать, сколько времени потребуется для построения ответа, он должен учитывать это в значении Retry-After. Если более поздний GET вызов сделан в новое место, а результаты еще не построены, верните ответ с обновленным значением Retry-After. Так что, возможно, вы попробуете 10, и если это не сработает, вы скажете клиенту подождать еще 110, что в общей сложности составит две минуты.

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

person Eric Stein    schedule 26.02.2019
comment
Опрос - не лучшее решение (особенно с накладными расходами ОЗУ для буферизации ответов и непредсказуемым Retry-After). Мы изучили WebSockets (см. Вопрос), но после того, как вы повторно подняли его как вариант, мы нашли хорошую реализацию по умолчанию (весеннюю) клиентской и серверной частей, которая может быть вполне совместима с нашим кодом (меняется только транспорт) - даст шанс, спасибо! - person Vlad; 28.02.2019
comment
Принимая часть ответа WebSocket, спасибо! - person Vlad; 28.02.2019

Взгляните на SSE

пример кода: https://github.com/rsvoboda/resteasy-sse

или автобус событий vertx: https://vertx.io/docs/apidocs/io/vertx/core/eventbus/EventBus.html

person HRgiger    schedule 26.02.2019
comment
Из stackoverflow.com/help/how-to-answer: укажите контекст для ссылок Ссылки на внешние ресурсы приветствуются, но, пожалуйста, добавьте контекст вокруг ссылки, чтобы ваши друзья-пользователи имели некоторое представление о том, что это такое и почему она там есть. Всегда указывайте наиболее релевантную часть важной ссылки, если целевой сайт недоступен или постоянно отключен. - person Eric Stein; 26.02.2019
comment
javax.ws.rs.sse выглядит очень жизнеспособным вариантом (за исключением того, что контрольный сигнал должен управляться сервером, а не клиентом, отвечающим сердцебиением "Я все еще здесь") - спасибо, проголосую "за". Хотя я не вижу актуальности EventBus. - person Vlad; 28.02.2019
comment
@Vlad взгляни sandny.com/2017/10/21/ - person HRgiger; 28.02.2019
comment
Теперь я следую тому, что вы имели в виду для EventBus (было бы интересно увидеть tcpdump их протокола связи поверх http), но, к сожалению, все функции vertx требуют, чтобы он запускал автономную службу / прослушиватель (отдельно от существующего webapp контейнер). Я нашел рабочий вариант для прокси / моста через контейнер Tomcat, но этот вариант, похоже, влияет на функции vertx из-за предварительной буферизации и т.д. накладных расходов поверх связи vertx: stackoverflow.com/questions/36432903/deploy-vert-x-on-tomcat Я буду придерживаться на ответ WebSockets из-за простоты переключения на него существующего кода, спасибо! - person Vlad; 28.02.2019