Розподілені обчислення для пошуку житла

Всі чули про distributed computing проектах, які намагаються вирішувати масштабні завдання, на зразок поиска позаземного життя, ліків від Сніду і раку, пошуку простих чисел і унікальних решений для Судоку. Все це дуже цікаво, але не більше, адже практичної користі для людини, який поділився ресурсами комп'ютера — ніякої.

Сьогодні я розповім про розподілених обчисленнях, які вирішують ваші проблеми. Ну не всі звичайно, а лише деякі, пов'язані з пошуком житла. Нещодавно я писав про проект Sobnik, розширення для Chrome, яке виявляє посередників на дошках оголошень. Два тижні тому була запущена нова версія програми, в якій робота зі сканування та аналізу оголошень розподіляється по комп'ютерах користувачів. За минулий час було опрацьовано близько мільйона оголошень з понад тисячі міст Росії, і це — тільки початок. Подробиці, технічні деталі і ще трохи цифр чекають вас під катом.



Навіщо тут розподілені обчислення?
Для того, щоб виявити посередника, програму потрібно завантажити оголошення, розпарсити його, проаналізувати фотографії, скласти результати в бази даних і виконати кілька видів пошуку, зокрема — за номерами телефонів. Спочатку користувачеві потрібно відкрити конкретне оголошення, щоб плагін виконав цей аналіз. Це незручно, адже оголошень сотні, і серед них майже всі — посередники. Від ручних операцій треба було позбавлятися, адже комп'ютери для того й існують, щоб діяти автоматично!

Першим планом стало створення централізованого сканера оголошень (далі — краулер). Беремо PhantomJS, допиливаем під нього JS-код плагіна, і запускаємо сканування на сервері. Авіто, звичайно, буде сердитися на масштабне сканування, і буде блокувати IP сервера, але на той випадок було вирішено накупити IP-адрес або використовувати купу проксі (Авіто — єдина поки дошка оголошень, з якою працює плагін). Але чим довше я працював і думав у цьому напрямку, тим більше розумів — погане рішення:
  1. Сервера коштують грошей, які витрачати не хотілося — проект адже безкоштовний, і я мрію залишити його таким.
  2. Надійності ніякої — змагатися з Avito в пошуку незабаненных проксі не було ніякого бажання.
  3. Масштабованість такого рішення впиралася в ще більші гроші, див. п.1.
Незабаром я прийшов до висновку, що єдиним рішенням, позбавленим згаданих недоліків, буде автоматичний краулер, вбудований плагін, і працює в браузерах користувачів навіть тоді, коли вони самі не зайняті пошуком житла.

Розподілений краулер
Активно з Avito в кожен момент часу працює лише невеликий відсоток користувачів, однак браузер з працюючим плагіном запущений майже весь день. Якщо в браузері кожного користувача сканировалось б, скажімо, одне оголошення в хвилину? Цих сумарних потужностей вистачило б, щоб швидко сканувати оголошення, з якими в даний момент працюють активні користувачі. І Авіто б не турбувався, адже перевантажень з певних IP ніколи б не виникало. Так, ймовірно, не всі захочуть ділитися потужностями своїх комп'ютерів, однак мені вірилося, що «свідомих громадян» буде все ж достатньо. Ідея виглядала дуже привабливо.

Заглибившись у технічну частину нового підходу я усвідомив, що з збільшеними навантаженнями поточний сервер просто не впорається. Обробка фотографій для виявлення номерів телефонів і так вже жрала майже весь CPU, а якщо потік оголошень зросте на порядок? Безкоштовний віртуальний сервер від AWS Free Tier повинен був справлятися, інакше життя проекту була під загрозою. Так що першим кроком стало перенесення роботи з зображеннями в масштабовану частина системи — на клієнта. Код плагіна відкритий, і звичайно були побоювання, що публікація алгоритму полегшить злим спамерам пошук слабких місць і шляхів для обману. Однак, інших варіантів для розвитку проекту я не бачив, і вирішив — будь що буде.

Отже, тепер Sobnik відкриває окрему вкладку в браузері. Періодично, приблизно раз на хвилину, він запитує з сервера завдання — адреса оголошення для сканування, завантажує це оголошення у своїй вкладці, парсити, обробляє зображення та відправляє результати до сервера. Завдання на перевірку створюються, коли хтось з користувачів відкриває список оголошень — заздалегідь і «запас» нічого не сканується, оголошення — продукт швидкопсувний.

Свідомих громадян, які виявили бажання поділитися потужностями свого ПК, поки що не так вже багато — близько кількох сотень. Однак, цього цілком достатньо, щоб обробляти 60 тисяч оголошень у день, забезпечуючи потреби тисячі користувачів плагіна. Відкритий на Авіто список із сотні оголошень обробляється в межах однієї хвилини.

Звучить все це досить просто, проте мене досі заворожує можливість використовувати сотні чужих комп'ютерів для вирішення загальної задачі. Браузер — ідеальна платформа для програм такого роду:
  1. JavaScript нині вміє майже все.
  2. JS-код — багатоплатформовий (за винятком звернень до API браузера).
  3. Розширення встановлюється в один клік.
  4. Поширенням оновлення займається Webstore.
  5. Браузер запущено більшу частину дня.
Якщо ви задумали свої власні SETI@HOME — придивіться, може вам пора вивчати API улюбленого браузера. Про це вже багато писали, але розквіту розподілених обчислень, вирішують практичні проблеми волонтерів, а не абстрактної людської цивілізації — поки не видно.

Варто звернути увагу на один нюанс — людей дуже напружує, коли в браузері самостійно відкриваються вкладки. І якщо вже відкривати їх необхідно, варто витратити достатньо зусиль на те, щоб така поведінка було очікуваним для користувачів (інструкції, faq, зрозумілі інформаційні повідомлення). Користуючись нагодою, приношу вибачення всім, хто був здивований поведінкою плагіна після виходу нової версії програми — мені слід було витратити більше часу на інформування вас про таких істотних нововведеннях.

Ефективний сервер
Сервер, що координує роботу в розподіленій обчислювальній системі, повинен бути дуже ефективним, адже його не так легко масштабувати. Сервер проекту Sobnik займається не тільки координацією, але і рішенням прикладної задачі — пошуку по базі даних, тому вимоги до нього ще вище. І якщо функціональність клієнтської частини, була просто злегка розширена, сервер був перероблений майже повністю (нагадаю, він написаний на Go).

Спочатку за зберігання даних і виконання пошуків відповідала MongoDB, тепер всі дані зберігаються в ОЗП. На сервері запущено два процесу — фронтенд і бекенд. Фронтенд взаємодіє з клієнтами, веде чергу завдань для розподіленого краулера, чергу оголошень для передачі в бекенд, і невеликий кеш з інформацією про статус оголошень (посередник/власник). Бекенд зберігає дані в ОЗП (витяги з вхідних оголошень), виконує за ним пошуки, асинхронно пише вхідні оголошення в MongoDB, асинхронно виконує запити фронтенда. Взаємодіють процеси за допомогою ZeroMQ.

MongoDB використовується в максимально ефективних режимах — для послідовного запису вхідних оголошень, і для послідовного читання при перезапуску бек-ендом, в один потік. При старті, бекенд читає з СУБД актуальні оголошення, виконує ті ж пошуки та аналіз, як і при штатному надходженні даних від клієнтів, і наповнює свою базу в оперативній пам'яті. Такий підхід дозволяє легко модифікувати алгоритм виявлення посередників, і застосовувати його до всієї бази простим перезапуском бек-ендом.

Поки бекенд запускається, наповнюючи свою базу, фронтенд продовжує обслуговувати клієнтів — вхідні оголошення складає в чергу, запити статусу оголошень обслуговує з кешу, завдання роздає зі своєї черги.

В системі з майже десятком паралельних потоків (goroutine) немає жодного м'ютексу. Кожен потік має ексклюзивний доступ до своїх даних, і обслуговує інші потоки через канали (їх наявність в Go просто невимовно радує).

Всі межпроцессные і міжпотокові взаємодії виконуються в неблокирующем режимі. Якщо приймаюча сторона не встигає читати, дані яких складаються в чергу (вхідні оголошення на фронтенде), або відкидаються (інші запити). Всі черги і кеш мають обмеження на розмір, і при заповненні найбільш старі записи відкидаються — клієнтам Власника остання інформація більш цінна. У разі неможливості виконати запит (канал з даними зайнятий) клієнту надсилається відповідний відповідь, при цьому клієнт пробує знову, з зростаючим інтервалом.

Така архітектура створювалася з метою забезпечити максимальну надійність і доступність сервісу. І поки що вона себе виправдовує — маючи в базі майже мільйон оголошень і обробляючи до мільйона http-запитів в день, load_average на віртуальному сервері стабільно тримається нижче 10%.

Шукаємо житло по-новому!
Sobnik успішно пережив друге народження — «розподілився» і зміцнів. Місяць тому це була лише цікава ідея, прототип, який багато встановили щоб побалуватися. Тепер — це працюючий інструмент, яким зручно користуватися і який реально допомагає фільтрувати спам. Це стало можливим завдяки вам, Шановні Користувачі, адже це ваші комп'ютери вирішують загальну задачу.

Звичайно, система працює далеко не ідеально, є багато питань до детектора для фотографій, і є проблеми з аналізом тексту оголошень. Однак, тепер ясно — у Власника є достатньо ресурсів для вирішення цих питань. Залишається тільки підживлювати ентузіазм автора, чого Ви можете досягти критикою, пропозиціями та цінними коментарями.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.