mykyta_p ([personal profile] mprotsenko) wrote in [personal profile] malyj_gorgan 2021-12-31 12:04 am (UTC)

Я трохи не зрозумів про "пишемо нормально". Ось в нас є 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мс...)

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting