Переход с Spring MVC на Spring Webflux - блокировка и подписка - PullRequest
2 голосов
/ 23 октября 2019

Давайте представим сценарий, в котором есть старое приложение, написанное с использованием стека сервлетов, и вы решаете перенести его в Spring Webflux. Скажем также, что первое, что нужно перенести - это RestTemplate на WebClient.

Какой предпочтительный способ обработки Mono или Flux, который возвращает WebClient? Вызов block кажется правильным решением, так как приложение использует RestTemplate, который блокирует в любом случае. subscribe должно быть немного лучше, поскольку он имеет функцию обратного вызова, но, возможно, вам придется подождать, чтобы продолжить. Кроме того, с subscribe нужно ли нам обрабатывать Disposable и, если да, то как, потому что я не уверен, где лучше всего позвонить dispose на него?

И одинЕще вопрос по поводу JDBC. Насколько опасно использовать Schedulers.boundedElastic()? Насколько я понимаю, наличие отдельного пула потоков должно помочь, особенно если используется Netty. Это не идеально, но может ли это быть временным решением, пока драйверы R2DBC не достигнут 1.0.0? Что если приложение использует Tomcat? Ситуация лучше, так как Tomcat по умолчанию имеет больше потоков?

1 Ответ

2 голосов
/ 23 октября 2019

Какой предпочтительный способ обработки Mono или Flux, который возвращает WebClient?

Учитывая, что вы намереваетесь использовать Webflux, окончательный предпочтительный способ заключается вРазберитесь с этими издателями на 1007 * весь путь вверх по вашей реактивной цепочке. Это означает, что вы не будете в конечном итоге вызывать подписку на что-либо напрямую, потому что ваш контроллер сам вернет Mono (и все, включая вызовы WebClient, будет просто включено в этот Mono через серию реактивных операций. в цепочке.)

Однако, как вы указали, вы не можете реально перенести все сразу.

Если это только WebClient, что вы 'мигрируйте сейчас, затем просто позвоните block(), чтобы обработать его так же, как ваш RestController. Нет смысла звонить по номеру subscribe(), а затем ждать завершения подписки - это всего лишь менее очевидный и более многословный способ блокировки.

Как только вы все больше и больше переносите свой стек в реактивный, выможет делать все больше и больше реактивным образом, а затем начать «двигать» ваши block() вызовы дальше по цепочке в результате (пока блок не окажется на уровне контроллера, а затем вы можете просто переключиться на возврат Mono.)

Кроме того, при подписке мы должны обрабатывать одноразовые

Только если вам необходимо отменить подписчика (и он поддерживает это). Это довольно редкое явление в моем опыте.

И еще один вопрос относительно JDBC. Насколько опасно использовать Schedulers.boundedElastic()?

boundedElastic(), предназначенный для использования в качестве оболочки для блокировки ввода-вывода, поэтому нет ничего плохого в использовании этого на стороне реактора. Единственная «опасность» будет на стороне JDBC / приложения в отношении того, соответствует ли она вашим требованиям:

  • Он ограничен в 10 раз числом ядер ЦП
  • Количество «в очереди»"Задачи ограничены 100K

Если у вас достаточно долго выполняющихся запросов к БД, этого недостаточно, то вы можете вместо этого использовать newBoundedElastic() и указать threadCap и queuedTaskCap вручную.

Что если приложение использует Tomcat? Ситуация лучше, поскольку у Tomcat по умолчанию больше потоков?

Я бы не советовал полагаться на это. Tomcat по-прежнему использует один поток на запрос (даже с Webflux), поэтому существует опасность, что вы в конечном итоге заблокируете поток, который не должны делать, и в конечном итоге не поймете и затем будете полагаться на это поведение (которое тогда все рухнет, когдаВы перешли на Нетти.)

...