Устойчивость RSocket webflux к запросам-ответам

#spring-webflux #project-reactor #reactive #rsocket #netifi

#весна-webflux #проект-реактор #реактивный #rsocket #netifi

Вопрос:

Учитывая следующий код (с использованием Spring Webflux и RSocket):

 @MessageMapping("hello.{name}")
public Mono<String> greet(@DestinationVariable String name) {
    return Mono.just("Hello "   name); // or assume this is making a slow http call
}
  

Вопросы:

  1. Когда сервер находится под большой нагрузкой, будет ли клиент просто отправлять запрос на сервер, а сервер будет буферизировать этот запрос? Или на самом деле существует какой-то механизм, который заставляет клиента ждать, пока сервер не отправит сигнал клиенту?

  2. Если клиент все равно отправит запрос, то в какой-то момент серверу не хватит памяти для буферизации всех избыточных запросов. Как мы обычно с этим справляемся? Может ли брокер netifi помочь в этой ситуации? (Предположим, что это массовый трафик, и мы не можем своевременно масштабировать или расширять серверы)

Ответ №1:

Реальная устойчивость с RSocket

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

Устойчивость благодаря управлению потоком (также известному как противодавление)

Если вы выполняете потоковую передачу, ваш подписчик может контролировать количество доставляемых элементов, поэтому ваш подписчик не будет перегружен сервером. Приведенная ниже анимация показывает, как спецификация реактивных потоков реализована на уровне протокола RSocket:

RSocket и реактивные потоки

Как можно заметить, как и в реактивных потоках, Subscriber данные (левой стороны) request s через its Subscription , этот запрос преобразуется в двоичный кадр, отправляется по сети, и как только получатель получает этот кадр, он декодирует его и затем доставляет в соответствующую подписку на удаленном сайте, чтобыудаленный издатель может создавать точное количество сообщений.

Устойчивость через лизинг

С другой стороны, наряду с потоковой передачей сервер, который обычно управляет несколькими соединениями, должен выдерживать нагрузку, и в случае сбоя он должен быть в состоянии предотвратить любые дальнейшие взаимодействия. Для этой цели RSocket предоставляет встроенную функцию протокола, называемую Leasing . В двух словах, Leasing это встроенное в протокол ограничение скорости, где ограничение запроса является чем-то динамическим и полностью контролируется стороной Ответчика.

В этом процессе можно выделить несколько фраз:

  1. Этап настройки — этот этап происходит, когда клиент подключается к серверу, и обе стороны должны предоставить определенные флаги, чтобы согласиться с тем, что они оба готовы соблюдать условия аренды.
  2. Фаза молчания — на этом этапе запрашивающая сторона ничего не может сделать. Существует строгая взаимосвязь — запросу не разрешается ничего делать, если ответчик не разрешает это делать. Если запрашивающая сторона попытается отправить какие-либо запросы, такие запросы будут немедленно завершаться ошибкой без отправки какого-либо фрейма на удаленный сервер.
  3. Фаза предоставления аренды — после того, как ответчик согласовал свою пропускную способность и готов принимать запросы от Отправителя запроса, он отправляет определенный вызываемый фрейм Lease . Этот фрейм содержит 2 критических значения: Number of Requests и Time to Live . Первое значение указывает отправителю запроса количество запросов, которые он может отправить Ответчику. Второе значение указывает, как долго действует такое разрешение. Поэтому, если Запрашивающий не использовал все из них к тому времени, такое разрешение будет считаться недействительным, и любые дальнейшие запросы будут отклонены Отправителем запроса.

Это взаимодействие изображено в следующей анимации:

RSocket и лизинг

Примечание

Стратегия аренды работает на per connection основе, что означает, что если вы оформляете аренду, вы оформляете ее для одного конкретного удаленного отправителя запроса, а не для всех отправителей запросов, подключенных к вашему серверу. С другой стороны, математика может быть применена для совместного использования всей емкости сервера между всеми подключенными запросчиками, Зависит от некоторых показателей и т. Д.

Где найти пример обоих

Есть несколько хороших примеров, демонстрирующих, как управление потоками и аренда могут использоваться с RSocket. Все они могут быть найдены в официальном репозитории git проекта RSocket-Java здесь

Комментарии:

1. Настраивается ли это вручную на уровне приложения для аренды (количество запросов и время выхода)? Является ли аренда общей для всех участников запроса?

2. Стратегия аренды может быть настроена отдельно с обеих сторон (на клиенте и сервере, поскольку протокол является одноранговым, поэтому логика ответчика может быть реализована здесь и там). Для сервера стратегия аренды создается для каждого соединения, таким образом, механизм, который отправляет договоры аренды, определяется для каждого соединения. Тем не менее, если вы предоставили 100 запросов, разрешенных для отправки для соединения A, и у вас всего 150, тогда вы можете выполнить математику и выдать, например, только 50 или 25 другому

3. кстати, я думаю, что довольно сложно подсчитать количество запросов в лизинге. И это еще сложнее в сочетании со временем жизни. Считаете ли вы хорошей практикой вычисления для каждого запроса (также мы можем это сделать, возможно, с 0 TTL)? Будет ли это значительно замедлять обмен данными, потому что нам нужно выполнять все этапы аренды для каждого запроса?

4. Это можно легко сделать с помощью библиотеки Netflix с ограничением параллелизма. У нас выполняется PR, который изменяет некоторые внутренние компоненты и добавляет ряд примеров, показывающих, как рассчитать аренду при наличии нескольких подключений github.com/rsocket/rsocket-java/pull/885

5. Кроме того, мы работаем над новыми изменениями в аренде, но их еще нет -> github.com/rsocket/rsocket/pull/311