log4j ?

Dec. 24th, 2021 01:04 pm
malyj_gorgan: (Default)
[personal profile] malyj_gorgan
Слухайте, а хтось може в парі абзаців пояснити, що то таке сабж і з чим його їдят? Дідько з нею, з його vulterability'ею, я хочу зрозуміти, чим був такий хороший чи зручний чи потрібний сам log4j, що та вульнерабіліті виявилася такою проблємною? Тільки пояснити так, на хлопский розум, без відсилань в непотрібні абревіатури.
Дякую!

Date: 2021-12-30 10:25 pm (UTC)
From: [personal profile] mprotsenko
і введемо thread pools обмеженого розміру та черги, де б запити проводили решту часу, тобто, 49ms

Перечитав і подумав - чи не є реактивною моделлю, але вже без blocking IO? Ні, звісно, так теж можна, але це теж ускладнює код, ні?

Date: 2021-12-30 11:34 pm (UTC)
From: [personal profile] sassa_nf
Так, ускладнює, але в одному добре визначеному місці, і ускладнення обмежено, тоді як реактивне/CPS is contagious.

Скажімо, взаємодія із дуже повільним сервісом - в цьому місці вводимо CompletableFuture, продовження якого буде виконано в окремому thread pool, а решту пишемо "нормально".

Тому випадок номер 2 із 60 секунд - там якраз thread per request most of the way.

Date: 2021-12-31 12:04 am (UTC)
From: [personal profile] mprotsenko
Я трохи не зрозумів про "пишемо нормально". Ось в нас є 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мс...)
Edited Date: 2021-12-31 02:43 am (UTC)

Date: 2021-12-31 10:16 am (UTC)
From: [personal profile] sassa_nf
> Усе, що йдеться далі - пишеться в асинхронному стилі

так, оце і є "CPS is contagious". Але якраз якщо ми не змушені всі blocking operations переписувати в реактив, то тоді не "Усе, що йдеться далі".
public void blah(@Suspended AsyncResponse response) {
   ...
   client.rx().get("/slow").whenCompleteAsync((r, th) -> { // так, в цьому місці асинхрон
      ...
      try(DBConn conn = pool.borrow()) { // але в цьому нам нормально і без асинхрону
        ...
      }
      response.resume("hello world");
   }, myExecutor);
}


> в non-blocking IO немає проблем з насиченим thread pool та нудною оптимізацією його розміру, підтримкою переліку тасків, що виконуються, і ще купою дрібничок

а от якраз перелік тасків, що виконуються, є проблемою асинхрону :) а насичення thread pool - це ніщо в порівнянні з необмеженим ростом задач, загубленим continuation та боротьбою із error propagation та resource management.

щодо нудної оптимізації розміру - так, вона нудна, але це підлягає автоматизації.


> а різниця в throughput - ... - раза в два-три

цікаво. я такого ще не бачив. а в порівнянні з чим?

Date: 2021-12-31 05:31 pm (UTC)
From: [personal profile] mprotsenko
      try(DBConn conn = pool.borrow()) { // але в цьому нам нормально і без асинхрону
        ...
      }


Якщо ми не влітаємо в 5 сек затримки (бо локі, насичений пул, неоптимальні індекси) - то, так, згоден.

Але якщо в нас і БД реактивна, то http worker ми можемо прив'язати до конкретного cpu core і мати два threadpool-а замість трьох.

(Бо синхронний код з цього прикладу не можна виконувати на http worker - інакше сервер просто не буде реагувати на нові запити. я підозрюю, що тут йдеться про стандартну модель http worker thread pool - framework threadpool - separate threadpool for slow operations.)

А якщо ми додаємо HTTP/2 multiplexing і позбавляємося необхідності обробляти кожен новий запит до нашого сервісу як окремий запит з власним connection (чи боротися з connection pooling)... ;)




Різниця в throughput в порівнянні з виконанням

blockingClient.get("/someReallySlowStuff")


в окремому threadpool (який все одно насичується і примушує чекати батьківській threadpool). Черга тут теоретично може допомогти, а практично в нас є власний SLA і чекати безкінечно в черзі теж не можна - як мінімум, в тому випадку, що я тестував.

Звісно, якщо, наприклад, йдеться не про купівлю товара на сайті, а про відновлення щомісячної переплати, то там інша картинка буде, бо там не буде вимог до нашого latency.



а от якраз перелік тасків, що виконуються, є проблемою асинхрону :)

Але, слава Творцю, це проблема людей, що пишуть асинхронні фреймворкі. :)
Edited Date: 2021-12-31 05:47 pm (UTC)

Date: 2022-01-03 01:35 pm (UTC)
From: [personal profile] sassa_nf
Зрозуміло. Дякую.

Profile

malyj_gorgan: (Default)
malyj_gorgan

June 2025

S M T W T F S
12 345 67
89 1011 121314
15161718192021
22232425262728
2930     

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 18th, 2025 06:00 am
Powered by Dreamwidth Studios