Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni
🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!27.03.2023
Паралелізація запитів в Ruby
Хочу висловити похвалу моделі одночасного виконання в Ruby, а саме, класу Thread. Ruby так зневажливо відносять до повільних мов, що яка вже там одночасність! Тут же ж навіть багатопотоковості немає. (До речі, справжня багатоядерна паралелізація в Ruby 3 теж вже є, з класом Ractor).
Насправді є сценарій, в якому одночасне виконання дуже допомагає, та він всім нам добре відомий — це звертання до мережевих ресурсів. Будь то запити до API, чи завантаження сторінок, чи надсилання листів по SMTP - всілякі операції через Інтернет можна робити паралельно в декількох потоках, бо під час запиту програма все одно стоїть та чекає відповіді. (Єдине, що треба мати на увазі — не робіть з потоків звертань до бази даних, бо це вичерпає пул підключень. Або пул треба збільшити, або роботу з базою винести з потоку.)
# Паралельне завантаження сторінок
urls.map { |url| Thread.new { Net::HTTP.get(url) } }.map(&:join)
Так на минулому тижні мені вдалося замінити процес, що займав дві години, та опитував кожний ресурс послідовно, на паралелізоване рішення, якому потрібно двадцять хвилин. І це мені поки боязно робити надто багато запитів — можливо, в майбутньому зробимо ще швидше.
Для більш поглибленого використання можливостей одночасності можу порадити гем concurrent-ruby. В ньому реалізовані класи для всього, що можна собі уявити. Я, наприклад. завжди маю на увазі пул тредів для обмеженої паралелізації.