Какова правильная технология сердечного ритма / поддержки активности для 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-данных заполняются так постепенно, что между порциями нет 10-секундного промежутка, и поэтому readTimeout никогда не превышается, иногда есть 10-секундный интервал и время ожидания HttpClient...
Мы могли бы попытаться увеличить время ожидания на главной стороне, но это могло бы легко увеличить / перегрузить пул слушателей (просто обычным трафиком, даже не будучи DDOSed). Нам нужен способ различать внутренний сайт, который все еще работает над генерацией ответа, и случаи, когда он действительно аварийно завершился / network_lost / etc. И самое лучшее во время общения - это биение сердца (каждые 5 секунд).
Мы думали, что Keep-Alive спасет нас, но, похоже, он защищает только промежутки между запросами (не во время запросов), и, похоже, он не делает сердцебиение в течение промежутка (просто имея / wait_for timeout).
Мы думали, что chunked-кодирование может спасти нас, посылая некоторые тактовые импульсы (0-bytes-size-chunks), чтобы дать понять другой стороне, но, похоже, нет такой реализации по умолчанию для поддержки любого тактового импульса таким образом, и тем более кажется, что 0- блок размером в байты сам по себе является индикатором EOD...
Вопросы):
Если мы правы в предположении, что KeepAlive/ChunkedEncoding не поможет нам в достижении keepAlive/hearbeat/fastDetectionOfDeadBackend, тогда:
1) в каком слое должно быть реализовано такое сердцебиение? Http? Tcp?
2) какие-нибудь стандартные фреймворки / библиотеки / настройки / и т. Д. Уже реализуют это? (если возможно: Java, REST)
ОБНОВИТЬ
Я также изучил реализации heartbeat для WADL/WSDL, хотя не нашел ни одного для REST, проверил WebSockets... Также посмотрел TCP-keepalive, которые, кажется, подходят для этой задачи:
- https://en.wikipedia.org/wiki/Keepalive
- http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
- Сокращение сердцебиения против keepalive
- Пинг / понг WebSockets, почему не TCP keepalive?
НО в соответствии с теми, что я должен был бы настроить что-то вроде:
- tcp_keepalive_time = 5
- tcp_keepalive_intvl = 1
- tcp_keepalive_probes = 3
что кажется контррекомендованием (рекомендуется 2 часа, 10 минут, уже представленных как нечетное значение, переходят в 5 с вменяемым / безопасным, если это так - может быть, мое решение заранее...)
также где я должен настроить это? на London04 один или на мэйн тоже? (если я настрою его на Main - не затопит ли он клиента ->Main frontend communication? или могут ли NAT / etc между сайтами легко испортить намерение / поддержку keepalive?)
PS любая ссылка на RTFM приветствуется - я мог бы просто упустить что-то очевидное:)
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.
Посмотрите SSE
пример кода: https://github.com/rsvoboda/resteasy-sse
или vertx event-bus: https://vertx.io/docs/apidocs/io/vertx/core/eventbus/EventBus.html