Авакари — сервис для публикации и подписки на релевантные сообщения
- четверг, 22 июня 2023 г. в 00:00:16
В предыдущей статье "Дерево Киви для поиска шаблона по тексту" я рассказывал, как можно эффективно находить по входящему сообщению все удовлетворяющие "поисковые запросы", избегая их перебора "в лоб" и прямого сопоставления. Это можно применить реализации полноценной Pub/Sub-системы, дополняющей уже существующие, такие как Nats, Apache Kafka или AWS SNS новой возможностью поддерживать действительно масштабируемое число wildcard-подписок. В этой статье я расскажу о такой системе.
Авакари на текущий момент - backend сервис, который использует gRPC API по ряду причин:
Эффективное использование ресурсов (HTTP/2, бинарная сериализация Protobuf)
Streaming - необходимо для реализации push уведомлений от сервиса клиенту. Здесь отдельное спасибо Кириллу Гусакову за подсказку.
Потоковая передача сообщений используется как для отправки сообщений в систему (Publish), так и для получения сообщений на выходе.
При выборе формата сообщений я решил остановиться на нейтральном стандарте CloudEvents. Исходные требования к формату сообщений были следующие:
Поддержка произвольных key-value метаданных, по которым будет происходить сопоставление с подписками
Независимость от протокола
Удобство (де)сериализации с помощью Protobuf
Пример payload при получении/отправке сообщений выглядит следующим образом:
{
"msgs": [
{
"id": "3426d090-1b8a-4a09-ac9c-41f2de24d5ac",
"type": "example.type",
"source": "example/uri",
"spec_version": "1.0",
"attributes": {
"author": {
"ce_string": "Obi-Wan Kenobi"
},
"time": {
"ce_timestamp": "1985-04-12T23:20:50.52Z"
}
},
"text_data": "I felt a great disturbance in the force"
}
]
}
Для работы с пользовательскими подписками достаточно простого набора CRUDL операций (также gRPC). Чтобы пользователь мог определять, как выбирать сообщения, подписки должны содержать условия выбора.
Так как входящие сообщения имеют метаданные в виде набора "key: input value", то условия выбора сообщения можно выразить как: "key: wildcard", где key - это искомый ключ метаданных, а wildcard - шаблон. Kiwi-условие, если короче.
Дополнительно kiwi-условия имеют следующие свойства:
Not - условие является отрицанием, то есть совпадение исключает сообщение
Partial - искать совпадения также среди лексем из input, который разбивается
Пример:
"cond": {
"not": false,
"ktc": {
"key": "title",
"pattern": "?usk", // musk, Musk, dusk, ...
"partial": true
}
}
Такому условию должны удовлетворять сообщения, которые в метаданных по ключу "title" содержат отдельные слова как, например, "musk" или полные строки вроде "Elon Musk" или "Dusk and her embrace".
Для полноценного описания того, какие сообщения требуется получать, kiwi-условий недостаточно. Необходимо иметь возможность описывать сразу множество условий в одной и той же подписке (например по разным ключам метаданных) и применять логические операции:
And
Or
Xor
Для этой цели служат группы условий. Так как группа тоже является условием, можно использовать вложенность.
Полный пример описания подписки с групповым условием:
{
"md": {
"description": "my subscription 1",
"enabled": true
},
"cond": {
"not": false,
// "gc" means "group condition"
"gc": {
"logic": 0, // 0 - And, 1 - Or, 2 - Xor
"group": [
{
"not": false,
// "ktc" means "kiwi-tree condition"
"ktc": {
"key": "key0",
"pattern": "pattern?",
"partial": false
}
},
{
"not": true,
"ktc": {
"key": "key1",
"pattern": "pattern1",
"partial": true
}
}
]
}
}
}
На текущий момент есть два варианта:
Самостоятельно раздеплоить Core систему, например, на minikube у себя дома.
В облачном варианте уже используется producer-rss компонент, который регулярно поглощает RSS из разных источников, конвертирует данные в сообщения и отправляет в систему. То есть можно подписаться на новости по какому-либо критерию и получать их.
В первую очередь, конечно же нужно добиться выполнения критериев production-ready и запустить боевой экземпляр сервиса. Тут ещё довольно много рутинной работы, такой как автоматизация выдачи сертификатов.
В перспективе Авакари можно будет использовать в довольно широком наборе сфер, таких как инвестиции, СМИ, реклама.
Можно представить интеграцию с чем-то вроде Авито, где новое объявление о продаже уведомляет всех, кто подписан на специфический товар, например iphone 42.
Вместо изобретения собственного UI есть идея реализации чат-бота, который будет позволять управлять подписками, отправлять и получать сообщения в/из Авакари.
Проект является Open Source, поэтому замечания, исправления и дополнения - приветсвуются. В набор входит уже более дюжины различных микросервисов, написанных на Go.