Будова jasmin sms gateway

Якщо спробувати загугли sms шлюзи з відкритим вихідним кодом, то швидше за все ви знайдете Jasmin Gateway і Kannel. Про Kannel легко знайти хороші статті в російськомовні сегменті інтернету, а ось Jasmin такою увагою обділений, тому я вирішив сьогодні розповісти трохи про його пристрій.

Якщо зробити коротку витримку

  1. Написаний на мові Python
  2. Реалізує SMPP 3.4
  3. Доступний як пакет починаючи з ubuntu 15.10
  4. Для своєї роботи використовує rabbitMQ і redis
  5. Істотно однопоточен (є окремі частини, які теоретично можуть працювати в кілька потоків, але на практиці це не трапляється)
  6. Зміна налаштувань зазвичай йде з даунтайм
  7. Реальна продуктивність 100 повідомлень в секунду (обмеження на вхід, вихідні може відправляти зі швидкістю в 1000 повідомлень) (версія 0.9b)
  8. Вміє приймати на вхід смс з http протоколу
  9. Вміє працювати і як SMPP клієнт, і як SMPP сервер

Що Jasmin вміє:

  1. Приймати смс відправлені через smpp або http
  2. Пересилати отримані смс на зовнішній smpp сервіс (наприклад на компанію поствщіка мобільних послуг)
  3. Одержувати і передавати далі статистику по смс
  4. Підтримує різні кодування смс
  5. Підтримує довгі смс (що складаються з декількох повідомлень)
  6. Можливість гнучкого налаштування перемикання каналів відправки смс в залежності від відправника \ змісту \ часу
  7. Облік фінансів і обсягу смс трафіку

Як влаштований Jasmin

Самі розробники описують архітектуру Jasmin так:

Будова jasmin sms gateway

Але я б запропонував подивитися на архітектуру з точки зору того, що відбувається з повідомленням, коли воно потрапляє на Jasmin сервер. Я розгляну шлях для smpp повідомлення, для http шлях буде такий же:

  1. Слухаючи порт Jasmin отримує повідомлення. Він перевіряє його на валідність виходячи з контексту і, якщо воно не валідність, то відкидає його (тут до речі полягає одне з найслабших місць Jasmin: майже всі компанії з якими мені довелося працювати не використовують протокол Smpp як такої, а використовують якісь свої рішення, які в окремих моментах відрізняються від протоколу - такі місця доводилося допілівать руками за місцем).
  2. Розпарсити повідомлення Jasmin кладе його в чергу в rabbitMQ, для подальшої обробки і починає далі слухати порт.
  3. В іншому слухачі (але в рамках того ж потоку), Jasmin отримує повідомлення з черги і віддає його на intercept, якщо він налаштований (intercept - це механізм в рамках якого вашому заздалегідь заданому скрипту віддається повідомлення, і скрипт може вирішити що з повідомленням робити далі : наприклад можна відхилити, змінити одержувача, або перенаправити в будь якій змісту повідомлення. Найбільшим мінусом роботи з intercept в Jasmin є те, що для зміни скрипта потрібно скидати перехоплювач, що при великому навантаженні означає втрату частини повідомлень).
  4. Після цього на основі получаенних команд від intercept і таблиця оутінга jasmin обчислює, куди потрібно відправити повідомлення, і кладе його в окрему чергу для кожного постачальника послуг з відправлення смс
  5. В іншому слухачі (але в рамках того ж потоку), Jasmin отримує повідомлення з черги постачальника послуг і перевіряє чи потрібно за повідомленням віддавати статистику, якщо так, то асинхронно записує повідомлення в redis, і відправляє повідомлення

Отримавши ж дані по статистиці повідомлення Jasmin робить наступне:

  1. Слухаючи порт Jasmin отримує повідомлення. Він перевіряє його на валідність виходячи з контексту і, якщо воно не валідність, то відкидає його.
  2. Розпарсити повідомлення Jasmin шукає в redis вихідне повідомлення, щоб зрозуміти кому потрібно відправити відповідь. Відразу ж після цього повідомлення з redis видаляється. Якщо вихідного повідомлення немає, то відповідь відкидається, інакше зворотне повідомлення кладеться в чергу rabbitMQ.
  3. В іншому слухачі (але в рамках того ж потоку), Jasmin отримує повідомлення з черги і відправляє повідомлення.

оцінка архітектури

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

З іншого боку, така система передачі внутрішніх команд і повідомлень може привести до досить складно неповторним Багам: ми отримуємо відповідь на повідомлення, до того як повідомлення буде записано в redis (такий баг дуже цікаво спостерігати і налагоджувати). Схожі причини не дають розробникам переписати код, на багато-варіант, без істотних доробок і ускладнення архітектури.

Окремим плюсів для розширення Jasmin, є використання rabbitMQ і redis. Це дозволяє підключати зовнішні модулі та сховища без необхідності будь-яких маніпуляцій з кодом Jasmin.

На відміну від Kannel, Jasmin швидше за все не підходить для серйозної промислової роботи через свою низьку продуктивність. Однак Jasmin є відмінною програму для експериментів і створенні своїх програм на основі коду Jasmin.