Якщо спробувати загугли sms шлюзи з відкритим вихідним кодом, то швидше за все ви знайдете Jasmin Gateway і Kannel. Про Kannel легко знайти хороші статті в російськомовні сегменті інтернету, а ось Jasmin такою увагою обділений, тому я вирішив сьогодні розповісти трохи про його пристрій.
Якщо зробити коротку витримку
- Написаний на мові Python
- Реалізує SMPP 3.4
- Доступний як пакет починаючи з ubuntu 15.10
- Для своєї роботи використовує rabbitMQ і redis
- Істотно однопоточен (є окремі частини, які теоретично можуть працювати в кілька потоків, але на практиці це не трапляється)
- Зміна налаштувань зазвичай йде з даунтайм
- Реальна продуктивність 100 повідомлень в секунду (обмеження на вхід, вихідні може відправляти зі швидкістю в 1000 повідомлень) (версія 0.9b)
- Вміє приймати на вхід смс з http протоколу
- Вміє працювати і як SMPP клієнт, і як SMPP сервер
Що Jasmin вміє:
- Приймати смс відправлені через smpp або http
- Пересилати отримані смс на зовнішній smpp сервіс (наприклад на компанію поствщіка мобільних послуг)
- Одержувати і передавати далі статистику по смс
- Підтримує різні кодування смс
- Підтримує довгі смс (що складаються з декількох повідомлень)
- Можливість гнучкого налаштування перемикання каналів відправки смс в залежності від відправника \ змісту \ часу
- Облік фінансів і обсягу смс трафіку
Як влаштований Jasmin
Самі розробники описують архітектуру Jasmin так:
Але я б запропонував подивитися на архітектуру з точки зору того, що відбувається з повідомленням, коли воно потрапляє на Jasmin сервер. Я розгляну шлях для smpp повідомлення, для http шлях буде такий же:
- Слухаючи порт Jasmin отримує повідомлення. Він перевіряє його на валідність виходячи з контексту і, якщо воно не валідність, то відкидає його (тут до речі полягає одне з найслабших місць Jasmin: майже всі компанії з якими мені довелося працювати не використовують протокол Smpp як такої, а використовують якісь свої рішення, які в окремих моментах відрізняються від протоколу - такі місця доводилося допілівать руками за місцем).
- Розпарсити повідомлення Jasmin кладе його в чергу в rabbitMQ, для подальшої обробки і починає далі слухати порт.
- В іншому слухачі (але в рамках того ж потоку), Jasmin отримує повідомлення з черги і віддає його на intercept, якщо він налаштований (intercept - це механізм в рамках якого вашому заздалегідь заданому скрипту віддається повідомлення, і скрипт може вирішити що з повідомленням робити далі : наприклад можна відхилити, змінити одержувача, або перенаправити в будь якій змісту повідомлення. Найбільшим мінусом роботи з intercept в Jasmin є те, що для зміни скрипта потрібно скидати перехоплювач, що при великому навантаженні означає втрату частини повідомлень).
- Після цього на основі получаенних команд від intercept і таблиця оутінга jasmin обчислює, куди потрібно відправити повідомлення, і кладе його в окрему чергу для кожного постачальника послуг з відправлення смс
- В іншому слухачі (але в рамках того ж потоку), Jasmin отримує повідомлення з черги постачальника послуг і перевіряє чи потрібно за повідомленням віддавати статистику, якщо так, то асинхронно записує повідомлення в redis, і відправляє повідомлення
Отримавши ж дані по статистиці повідомлення Jasmin робить наступне:
- Слухаючи порт Jasmin отримує повідомлення. Він перевіряє його на валідність виходячи з контексту і, якщо воно не валідність, то відкидає його.
- Розпарсити повідомлення Jasmin шукає в redis вихідне повідомлення, щоб зрозуміти кому потрібно відправити відповідь. Відразу ж після цього повідомлення з redis видаляється. Якщо вихідного повідомлення немає, то відповідь відкидається, інакше зворотне повідомлення кладеться в чергу rabbitMQ.
- В іншому слухачі (але в рамках того ж потоку), Jasmin отримує повідомлення з черги і відправляє повідомлення.
оцінка архітектури
Все основна взаємодія в Jasmin будується через rabbitMQ. З урахуванням можливостей асинхронної роботи з ним, це дозволяє досить сильно підвищити продуктивність в порівнянні з лінійним однопоточні додатком. Так як Jasmin зберігає в пам'яті лише тимчасову інформацію (від відправки смс, до отримання його статусу), то він дуже невимогливий до пам'яті.
З іншого боку, така система передачі внутрішніх команд і повідомлень може привести до досить складно неповторним Багам: ми отримуємо відповідь на повідомлення, до того як повідомлення буде записано в redis (такий баг дуже цікаво спостерігати і налагоджувати). Схожі причини не дають розробникам переписати код, на багато-варіант, без істотних доробок і ускладнення архітектури.
Окремим плюсів для розширення Jasmin, є використання rabbitMQ і redis. Це дозволяє підключати зовнішні модулі та сховища без необхідності будь-яких маніпуляцій з кодом Jasmin.
На відміну від Kannel, Jasmin швидше за все не підходить для серйозної промислової роботи через свою низьку продуктивність. Однак Jasmin є відмінною програму для експериментів і створенні своїх програм на основі коду Jasmin.