Я трохи не зрозумів про "пишемо нормально". Ось в нас є CompletableFuture, який поверне результат через 60 секунд. Усе, що йдеться далі - пишеться в асинхронному стилі, через thenApply, що код таки ускладнює.
Отримуємо в найпростішому випадку:
// ... спочатку звичайний синхронний код
// потім
return CompletableFuture.supplyAsync(longRunningTask, separateExecutor)
.thenApply(response -> process(response));
(Тут, звісно, треба фрейморк, який вміє працювати з такими відповідями, не викликаючи .get, а ціпляючи це до, наприклад, Netty, який крутиться під капотом.)
Собсна, тому що код далі виконується по факту відповіді 3rd party service - то виходить, що частина коду в нас таки реактивна, і єдина різниця в тому, що ми загортаємо "довгу" частину в окремий таск і виконуємо його на окремому тредпулі, який швидко насичується.
Але чому в такому випадку не використати non-blocking IO, раз в нас вже і так код реактивний?
Беремо
// ... спочатку звичайний синхронний код
// потім
return reactiveClient.someCall(someArguments)
.map(response -> process(response));
Різниці в складності коду нема, а різниця в throughput - якщо я правильно пам'ятаю лоад-тести, які я робив як раз, коли в біллінгу працював - раза в два-три.
(Бо в non-blocking IO немає проблем з насиченим thread pool та нудною оптимізацією його розміру, підтримкою переліку тасків, що виконуються, і ще купою дрібничок - одна лише оптимізація garbage collection нас починає вбивати, бо на 60 секундах це вже зовсім інша справа, ніж на 50мс...)
no subject
Date: 2021-12-31 12:04 am (UTC)Отримуємо в найпростішому випадку:
(Тут, звісно, треба фрейморк, який вміє працювати з такими відповідями, не викликаючи .get, а ціпляючи це до, наприклад, Netty, який крутиться під капотом.)
Собсна, тому що код далі виконується по факту відповіді 3rd party service - то виходить, що частина коду в нас таки реактивна, і єдина різниця в тому, що ми загортаємо "довгу" частину в окремий таск і виконуємо його на окремому тредпулі, який швидко насичується.
Але чому в такому випадку не використати non-blocking IO, раз в нас вже і так код реактивний?
Беремо
Різниці в складності коду нема, а різниця в throughput - якщо я правильно пам'ятаю лоад-тести, які я робив як раз, коли в біллінгу працював - раза в два-три.
(Бо в non-blocking IO немає проблем з насиченим thread pool та нудною оптимізацією його розміру, підтримкою переліку тасків, що виконуються, і ще купою дрібничок - одна лише оптимізація garbage collection нас починає вбивати, бо на 60 секундах це вже зовсім інша справа, ніж на 50мс...)