Add-on до Авіто. Стартап або приклад архітектури



Передісторія
Чесно кажучи, ніколи раніше не купував б/в речі на дошках оголошень. Але коли трапився черговий економічна криза та потреба змусила, довелося звернути свою увагу на Авіто.

При огляді пропозицій відразу кинулося в очі, що частина оголошень виглядає сумнівними по ряду ознак: занижена ціна, неточне опис і т. п., з яких складалося враження, що або продають не те, що пропонують, або самі не знають, що продають. У пам'яті відразу виник образ з минулого — барахолки 90-х років, з яких можна було повернутися з покупками, так і з порожніми кишенями або порізаної сумкою.

Як відомо, Авіто не дає інформацію про інших оголошеннях продавця, тому в тексті оголошення часто використовують ключові слова або хештегі, які покупець може використовувати для пошуку. Але треба зауважити, що адміністрація Авіто не вітає наявність в тексті оголошення будь-якої інформації, що не відноситься до предмета продажу, про що йдеться у правилах розміщення. При порушенні правил розміщення Авіто може заблокувати як оголошення, так і аккаунт продавця.

Пошуковик видав мені кілька сайтів, які паразитують на Авіто та інших дошках оголошень, переважно пов'язаних з автомобілями. У більшості своїй вони пропонують пошук оголошень за номером телефону продавця в базі попередньо завантажених оголошень. Всі вони мають недоліки, важливі для мене: хитромудрий інтерфейс, платність послуги, оновлення даних з певним лагом.

Поділяючи думку Стівена Леві про вільний доступ до інформації, було вирішено проаналізувати Авіто на предмет розробки власного сервісу sravnito.ru з блекджеком і всіма справами, а саме: з простим інтерфейсом і безкоштовним доступом.

На підставі проведеного аналізу були визначені основні атрибути оголошення:

  • назва
  • дата публікації
  • ціна
  • місцезнаходження
  • телефонний номер (або зображення номера, або хеш від нього, або розпізнане OCR значення)
Архітектура
Тепер безпосередньо про архітектуру програмного комплексу, на якому заснований сервіс пошуку всіх оголошень продавця:



Сховище
В якості сховища для зберігання оголошень та їх скріншотів використовується MySQL (Maria DB) з движком InnoDB.

У DB1 зберігаються оголошення з основними атрибутами. Для скорочення обсягу пам'яті, займаної даними, для текстових полів використовується тип VARCHAR, так як їх довжина відрізняється від оголошення до оголошення. Щоденно додається приблизно півмільйона рядків, серед яких як самі оголошення, так і логи та службова інформація. При такій динаміці сховище по праву можна буде відносити до Big Data. З особливостей налаштування можна виділити наступні параметри:

max_heap_table_size = 512M
innodb_buffer_pool_size = 3G

Таблиці в купі використовуються для оптимізації запитів з декількох великих таблиць, коли спочатку дані вибираються в тимчасову таблицю:

CREATE TEMPORARY TABLE _temp_table ENGINE=MEMORY AS (
SELECT field
FROM table
WHERE key = i_key
LIMIT i_limit);

яка потім з'єднується з іншого:

SELECT table.*
FROM table
JOIN _temp_table
ON table.field = _temp_table.field;

В DB2 зберігаються скріншоти оголошень як вони виглядають для користувача браузера. Перед записом скріншоти стискаються в JPEG quality = 5, що забезпечує розмір файлу із зображенням рівний приблизно 20Кб. Прийнято вважати, що при розмірі BLOB не більше 200Кб, продуктивність зберігання файлів в MySQL нічим не поступається NoSQL-сховищ, що дозволяє залишатися в зоні комфорту реляційної СУБД з усіма її перевагами. Настільки стислий скріншот, незважаючи на мінімальну якість зображення, дозволяє користувачеві переконатися, що заданий оголошення справді існувало, і розгледіти хоча б схематично зображення товару.

Вся логіка реалізована в збережених процедурах, щоб инкапсулировать залежний від структури даних код в самої СУБД. Таким чином, клієнти СУБД мають повноваження тільки для доступу до збережених процедур, які є идемпотентными. Як додатковий плюс отримуємо відсутність можливості здійснення SQL-ін'єкцій.

API до сховища
Сервер M1 реалізований як микросервис на golang і надає RESTful API для збереження оголошень, скріншотів, а також для читання даних, що виводяться на сторінці сервісу пошуку оголошень. Немає причин використовувати будь-які фреймворки або зовнішні бібліотеки для реалізації RESTful на golang, тому використовуються тільки стандартні бібліотеки, крім однієї:

import (
"database/sql"
"encoding/json"
"net/http"
_ "github.com/go-sql-driver/mysql"
)

Обробляються GET і POST запити від клієнтів і викликаються відповідні процедури БД DB1, DB2.

Завантажувачі оголошень
Оголошення завантажуються з сайту Авіто завантажувачами S(1)-S(N), написаними на Java з використанням бібліотеки Selenium WebDriver. Отримавши з Авіто атрибути оголошення і скріншот, завантажувач звертається до сервера M1 для передачі даних. Також реалізована зворотний зв'язок для управління завантажувачами, які періодично опитують сервер M1 на предмет команд, наприклад «стоп», «старт».

Captcha
Для розгадування капчі, яку іноді запитує Авіто, існує сервер C1, за аналогією з сервером M1 реалізований на golang і надає RESTful API. Розгадування капчі здійснюється двома способами:

  • за допомогою сервісу rucaptcha.com
  • вручну в додатку для Android
Для зв'язку з rucaptcha.com використовується їх API. Для ручного розгадування використовується написаний на Java додаток Android, який виводить зображення і приймає відповідь. Сервер C1 приймає рішення про перенаправлення капчі на rucaptcha.com або в додаток Android залежно від кількості запитів, що накопичилися в черзі. Отримавши розгадку капчі, сервер C1 відправляє відповідь запит його завантажувачу.

Моніторинг
За аналогією з додатком Android для розгадування капчі, існує додаток для моніторингу. Додаток Android для моніторингу звертається до сервера M1, який в свою чергу звертається до БД де агрегуються логи, на основі яких можна судити про кількість завантажених оголошень, збої в роботі і тощо

Висновок
Подальший розвиток сервісу може бути таким:

  • Створення завантажувачів для інших дощок оголошень, що дозволить робити крос-пошук всіх оголошень одного продавця
  • Використання комплексу для обробки інших даних, наприклад завантаження з соцмереж для пошуку всіх постів по імені облікового запису
І в тому і в іншому випадку розробці підлягають тільки завантажувачі, які легко інтегруються з серверами M1 і C1. Доробка інших частин системи не потрібно.

Якщо зробити API серверів M1, C1 публічним з авторизацією і додати в структуру БД ключове поле для поділу по клієнтам, то можна надавати послугу зі зберігання даних і обробки капчі як SaaS. Дані клієнта можна зберігати в BLOB у вигляді JSON, додавши при цьому БД з збереженими процедурами і API.

Що можна сказати про вибрані технологіях:

  • MySQL — класика жанру, без коментарів
  • Java — завантажувачі можна запускати на кавоварках і холодильниках
  • golang — дуже швидко розробляються микросервисы, легко деплоится шляхом копіювання єдиного бінарника
Буду вдячний за коментарі та обговорення.
Джерело: Хабрахабр

0 коментарів

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