16 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	Rest сервис Topic-management
Rest сервис для работы с топиками.
Сервис состоит из 2-х контекстов:
- 
topic-management - управление топиками (создание/изменение/удаление) 
- 
topic-subscription - клиентский сервис подписки и публикации сообщения 
При смене контекста в конфигурационных файлах требуется перераздать права на данный сервис.
Схема работы подписок
Схема работы нотификаций
Права
Право доступа в сервис topic-management
Для доступа к сервису topic-management у аккаунта должно быть право доступа в данный сервис.
По умолчанию право на доступ к сервису есть у пользователя admin.
Используя данного пользователя в сервисе permission-management можно раздать права на аккаунты систем.
Параметры для выдачи аккаунту прав на сервис:
- 
objectId: идентификатор учётной записи 
- 
objectType: account 
- 
subjectId: topic-management 
- 
subjectType: service 
Право manage сервиса topic-subscription
Для доступа к менеджерским функциям сервиса topic-subscription у аккаунта должно быть право manage - данное право открывает доступ к управлению подписками.
Функционал управления подписками реализован в методах subscribe и unsubscribe, пример использования приведён в подпунктах “Массовая обработка при наличии права manage для данного сервиса”.
Параметры для выдачи аккаунту права manage:
- 
objectId: идентификатор учётной записи 
- 
objectType: account 
- 
subjectId: topic-subscription 
- 
subjectType: service 
- 
action: manage 
Конфигурационные файлы
Конфигурационные файлы по умолчанию хранятся в папке сервера <karaf_home>\etc\
- 
ru.entaxy.esb.system.event.handler.cfg 
# максимальное колчичество попыток отправить сообщение в очередь
# почитать подробнее можно в https://camel.apache.org/components/latest/eips/dead-letter-channel.html#deadLetterChannel-Redelivery
redelivery.maximumRedeliveries=-1
# время между попытками отправить сообщение в очередь
redelivery.redeliveryDelay=5000
#cron - по умолчанию запускается каждые 00:00:00,
#cron выражение использует знак "+" как разделитель для модуля quartz2l
quartz.job.clean.cron=0+0+0+*+*+?+*- 
ru.entaxy.esb.system.event.rest.cfg 
service.host=http://0.0.0.0
service.port.management=9090
#Рутовый контекст управляющего сервиса, при изменении требуется перераздать права для данного сервиса
service.root.path.management=/topic-management
service.port.subscription=9092
#Рутовый контекст клиентского сервиса, при изменении требуется перераздать права для данного сервиса
service.root.path.subscription=/topic-subscriptionМетоды topic-management:
- 
create - создать топик При создании и изменении топика, есть возможность передать списки систем, которым доступна подписка или публикация в данном топике. 
Запрос:
POST server:9090/topic-management/create
Тело
{
    "topicName": "boomNews",
    "possibleSubscribers" : ["systemUuid1", "systemUuid2"],
    "possiblePublishers" : ["systemUuid3", "systemUuid4"]
}Ответ:
Статус 201
Тело
{
    "title": "Topic created",
    "topicName": "<topic_name>",
    "subscriberErrors": {
        "systemNotFound": [
            "<system_uuid>"
        ]
    },
    "publisherErrors": {
        "systemNotFound": []
    }
}- 
update - изменить топик (название не меняется, так как на него завязана сама очередь в брокере) 
Запрос:
POST server:9090/topic-management/update
Тело
{
    "topicName": "boomNews",
    "possibleSubscribers" : ["systemUuid1", "systemUuid2"],
    "possiblePublishers" : ["systemUuid3", "systemUuid4"]
}Ответ:
Статус 201
Тело
{
    "title": "Topic updated",
    "topicName": "<topic_name>",
    "subscriberErrors": {
        "systemNotFound": [
            "<system_uuid>"
        ]
    },
    "publisherErrors": {
    "systemNotFound": []
    }
}- 
delete - топик помечается как удалённый 
Запрос:
POST server:9090/topic-management/delete
Тело
{
    "topicName": "boomNews"
}Ответ:
Статус 200
Тело
{
    "title": "Topic deleted",
    "topicName": "<topic_name>"
}- 
clean - очистка хранилища топиков 
Окончательное удаление топиков, помеченных как удалённые.
Запрос:
POST server:9090/topic-management/clean
Ответ:
Статус 200
Тело
{
    "title": "Cleaned",
    "topicDeleted": "<count_of_deleted_topics>"
}Методы topic-subscription:
- 
subscribe - подписаться на топик 
Запрос:
POST server:9090/topic-subscription/subscribe
Тело
{
    "topicName": "boomNews",
    "subscriptionType": "PUSH"
}Ответ:
Статус 201
Тело
{
    "title": "Subscription created",
    "topicName": "<topic_name>",
    "systemName": "<system_name>",
    "subscriptionType": "<subscription_type>"
}Массовая обработка при наличии права manage для данного сервиса.
- 
subscribe - подписаться на топик 
Запрос:
POST server:9092/topic-subscription/subscribe
Тело
{
    "topicName": "boomNews",
    "systemUuids": [
        {
            "systemUuid": "NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN",
            "subscriptionType": "PUSH"
        },
        {
            "systemUuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            "subscriptionType": "PULL"
        },
        {
            "systemUuid": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY",
            "subscriptionType": "PULL"
        }
    ]
}Ответ:
Статус 200
Тело
[
    {
        "title": "Internal Server Error",
        "detail": "System not found NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN",
        "reason": "javax.persistence.NoResultException: No entity found for query"
    },
    {
        "title": "Subscription created",
        "topicName": "ooooo111-ff6e-4219-a878-bff120c495f1",
        "systemUUID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
        "subscriptionType": "PULL"
    },
    {
        "title": "Forbidden",
        "detail": "No permission to subscribe for system YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"
    }
]- 
unsubscribe - отписаться от топика 
Запрос:
POST server:9090/topic-subscription/unsubscribe
Тело
{
    "topicName": "boomNews"
}Ответ:
Статус 200
Тело
{
    "title": "Subscription deleted",
    "topicName": "<topic_name>",
    "systemName": "<system_name>"
}Массовая обработка при наличии права manage для данного сервиса.
Запрос:
POST server:9092/topic-subscription/unsubscribe
Тело
{
    "topicName": "boomNews",
    "systemUuids": [
        {
            "systemUuid":"NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN",
            "subscriptionType": "PUSH"
        },
        {
            "systemUuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            "subscriptionType": "PULL"
        },
        {
            "systemUuid": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY",
            "subscriptionType": "PULL"
        }
    ]
}Ответ:
Статус 200
Тело
[
    {
        "title": "Internal Server Error",
        "detail": "System not found NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN",
        "reason": "javax.persistence.NoResultException: No entity found for query"
    },
    {
        "title": "Subscription deleted",
        "topicName": "ooooo111-ff6e-4219-a878-bff120c495f1",
        "systemUUID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    {
        "title": "Subscription not found",
        "topicName": "ooooo111-ff6e-4219-a878-bff120c495f1",
        "systemUUID": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"
    }
]- 
publish - опубликовать событие 
Запрос:
POST server:9090/topic-subscription/publish
Тело
{
    "topicName": "boomNews", "message": "messageText2"
}Ответ:
	Статус 200
	Тело
		{
			"title": "Message published",
			"topicName": "<topic_name>"
		}
Примеры ответов при ошибке
- 
Передан некорректный JSON или логин не определён 
Статус 400
Тело
{
    "title": "Incorrect input parameters",
    "detail": "Cannot parse incoming JSON or login/system not defined"
}- 
Подписка не найдена 
Статус 404
Тело
{
    "title": "Subscription not found",
    "topicName": "${exchangeProperty.topicName}",
    "systemUUID": "${header.X-SystemUuid}"
}- 
Топик не зарегистрирован 
Статус 400
Тело
{
    "title": "Topic not registered",
    "topicName": "${exchangeProperty.topicName}"
}- 
Система не найдена 
Статус 500
Тело
{
    "title": "Internal Server Error",
    "detail": "System not found ${header.X-SystemUuid}",
    "reason": "${exception.stacktrace}"
}- 
Неизвестный тип подписки 
Статус 500
Тело
{
    "title": "Internal Server Error",
    "detail": "Unknown subscription type ${exchangeProperty.subscriptionType}",
    "reason": "${exception.stacktrace}"
}- 
Нет прав на выполнение запрошенной операции 
Статус 403
Тело
{
    "title": "Forbidden",
    "detail": "No permission to subscribe"
}- 
Неизвестная ошибка 
Статус 500
Тело
{
    "title": "Internal Server Error",
    "detail": "Unknown exception",
    "reason": "${exception.stacktrace}"
}Работа модуля топиков в кластере
Подписки
PULL подписки не реализованы!
Для реализации подписки используются durable shareable подписчики Apache Artemis топиков, а для доставки сообщений из топиков создаются специальные маршруты отправляющие сообщения в подписанную систему(PUSH-подписка). При работе в кластере системой создаются дублирующие маршруты на каждом узле, которые работают в конкурентном режиме, т.е. при падении одного из узлов доставка сообщений будет производиться оставшимися узлами.
Работа в кластере обеспечивается через компоненты Apache Felix Event Admin, реализующий рассылку служебных событий по топикам внутри узла, и Apache Karaf Cellar с интеграцией с Event Admin, реализующий рассылку данного события по всем узлам кластера. При создании/удалении подписки система создаёт соответствующее событие и отправляет в специальный топик subscription, далее подписчики на всех узлах, входящих в кластер, получают и обрабатывают данное событие.
Настройки
Настройки производятся на любом узле либо на мастер узле, в зависимости от настроек кластера.
Для синхронизации топика subscription в конфигурационном файле org.apache.karaf.cellar.groups.cfg, нужно добавить строки:
    default.event.blacklist.inbound = none
    default.event.blacklist.outbound = none
    default.event.whitelist.inbound = subscription
    default.event.whitelist.outbound = subscriptionДалее если Apache Karaf Cellar настроен правильно, то конфигурационные файлы org.apache.karaf.cellar.groups.cfg должны синхронизироваться и строки, представленные выше, появятся на всех узлах.
Если синхронизация конфигурационных файлов не проходит, можно проверить статус cellar продюсера командой:
cluster:producer-status
если выключен, то можно включить командой:
cluster:producer-start
Удаление топиков
Удаление топиков происходит в 2 этапа
- 
При вызове метода delete топик помечается в БД, как удалённый 
- 
По расписанию запускается задача (по умолчанию раз в сутки в 00:00), которая удаляет топик окончательно вместе с подписками, правами и консьюмерами. Либо очистка запускается вручную вызовом метода clean сервиса topic-management 
Если до очистки системы изменить топик помеченный как удалённый или попытаться создать его заново, то восстановится старый топик
Плановая задача по очистке топиков
Т.к. удаление топиков происходит в 2 этапа, с помощью планировщика Quartz2, работающего в кластере, запускается задача по очистке. Запуск происходит в конкурентном режиме, узел первый запустивший задачу получает приоритет, на остальных узлах задача останавливается до следующего запуска.
Частота запуска задачи настраивается в конфигурационном файле ru.entaxy.esb.system.event.handler.cfg в свойстве quartz.job.clean.cron=0+0+0+**?* с помощью cron выражения. Особенность cron выражения для quartz в том что “+” используется, как разделитель.

.png)