Презентация урока
urok-1.1-vvedenie.pptx
Презентация урока
urok-1.1-vvedenie.pptx
В банке десятки систем: АБС, интернет-банк, мобильное приложение, процессинг, антифрод, платёжные системы. Каждая время от времени должна обратиться к другой. Если соединять их напрямую, получается клубок интеграций, который дорого поддерживать и страшно менять. Сервисная шина решает эту проблему: она ставит в центр одну общую точку, через которую системы общаются друг с другом. Такая шина у Colvir называется CESB - Colvir Enterprise Service Bus, корпоративная сервисная шина Colvir. Этот урок вводный, кода ещё не будет. Задача - понять, что такое CESB, из чего она состоит и что происходит с запросом внутри неё. Это фундамент под все следующие модули.
После урока вы сможете объяснить, зачем нужна сервисная шина; показать, где CESB стоит в архитектуре банка; перечислить компоненты ядра; описать путь запроса от приёма до ответа; читать структуру системного объекта Base; разложить бизнес-задачу на решение в шине.
При прямых связях «каждый с каждым» число интеграций растёт квадратично: для n
систем это n·(n−1)/2. Пять систем дают 10 связей, десять систем уже 45. Каждая связь
несёт свой протокол, формат и обработку ошибок. Меняете одну систему, и есть риск
задеть все, что с ней соединены.
Шина переворачивает картину. В центр ставится одна общая точка, и каждая система знает
только про неё. Связей становится n вместо n².
Что шина берёт на себя:
| Функция | Что даёт |
|---|---|
| Маршрутизация | направляет запрос нужному сервису |
| Развязка протоколов | клиент по REST или SOAP, сервис об этом не думает |
| Единая авторизация | проверка в одной точке, а не в каждой системе |
| Кеширование | частые ответы отдаются из кеша |
| Наблюдаемость | все запросы через одну точку, значит логи централизованы |
Такой подход применяют там, где много разнородных систем, которые нельзя переписать с нуля: банки, телеком, страховые, госсектор. CESB это реализация такой шины от Colvir.
CESB состоит из прикладных сервисов (в них живёт бизнес-логика) и ядра-шлюза, которое даёт сервисам общую функциональность. Три термина, которые будут встречаться постоянно:
AuthMngr или сервис платёжных шаблонов PayHub).Кто такой «клиент шины». В курсе клиент шины - это не человек, а вызывающая сторона: приложение или система, которая шлёт запрос в шину (мобильное приложение банка, интернет-банк, другой сервис). Человек нажимает кнопку в приложении, а клиентом шины выступает само приложение.
Клиент шины (мобильное приложение, интернет-банк, внешняя система) обращается к слою доступа Web Access Layer, тот к шине, и уже шина общается с АБС и сторонними сервисами.
Зелёным на схеме - то, что пишете вы. Всё остальное уже существует: ваш сервис встраивается в готовую конструкцию, а не строит её заново.
Правило. Клиент никогда не обращается к АБС напрямую, всё идёт через шину. Сама шина бизнес-логику не содержит, она транспорт и оркестратор. Бизнес-логику несут сервисы.
Что это даёт банку: единую точку интеграции вместо прямых связей; переиспользование сервисов между разными клиентами шины; централизованную авторизацию; подключение новых систем без переписывания существующих.
Чтобы увидеть шину в действии, проследим один мгновенный перевод по шагам:
Протоколы у участников разные, но каждый сервис видит только шину - она связывает всё в единый процесс. Запрос проходит через пять-шесть систем, а разработчику кошелька достаточно знать контракт соседнего сервиса, а не всю цепочку. Детально такие интеграции разберём в пятом модуле.
Внутри шина говорит на протоколе с рабочим названием BaS. Все запросы и ответы это JSON, и в каждом всегда два параметра: B (Base) и S (Service).
Клиент может прислать запрос в полном формате BaS либо в упрощённом REST или SOAP. Если
запрос приходит не в BaS, шлюз сам достроит объект Base (часть полей возьмёт из
HTTP-заголовков, например User-Agent, X-ColvirS, Authorization).
| Подобъект | Назначение | Ключевые поля |
|---|---|---|
Cli | информация о вызывающей стороне | Code (код клиента), L (язык), RA (IP) |
SD | дескриптор безопасности | SID (идентификатор сессии), Auth, S (секрет) |
RT | тип получения результата | Type = S синхронно или A асинхронно; Channel (например WS) |
QCTX | контекст запроса | ID (идентификатор запроса, заполняет ядро) |
CMD | межмодульные команды | Name, Params |
Запомните два поля. B.QCTX.ID - идентификатор запроса: он не меняется на всём
пути, попадает в логи и в ответ, по нему ищут конкретную ошибку и статус
асинхронной операции. B.SD.SID - идентификатор сессии: клиент обязан считывать его
из ответа и передавать в следующих запросах.
Пример запроса:
{
"B": {
"Cli": { "Code": "TestApp", "L": "RU" },
"SD": { "SID": "" },
"RT": { "Type": "S" },
"QCTX":{ "ID": "7218216729702198041" }
},
"S": { "clientCode": "C-1024", "amount": "150000" }
}
Ответ всегда содержит B и S. Внутри S либо _R с результатом, либо _E с
ошибкой. Успешный ответ:
{
"B": { "QCTX": { "ID": "7218216729702198041" } },
"S": { "_R": { "requestId": "REQ-1024", "status": "ACCEPTED" } }
}
Ответ с ошибкой - вместо _R приходит _E, и HTTP-код отражает суть ошибки:
{
"B": { "QCTX": { "ID": "7218216729702198041" } },
"S": { "_E": { "Code": 1500, "Text": "Неверный логин или пароль.", "HTTPCode": 403 } }
}
«Обязательно ли мне, как разработчику сервиса, знать все эти поля Base?»
В 90% случаев, когда вы пишете бизнес-логику, вы работаете только с объектом
Service. Объект Base извлекается и обрабатывается ядром автоматически - вы его не
собираете и не разбираете. Но понимать его структуру важно для отладки: QCTX.ID и
SD.SID - ваш главный инструмент поиска проблем в логах.
«Что такое B.RT.Channel и когда оно используется?»
Поле указывает предпочтительный способ доставки асинхронного ответа (например,
WS - WebSocket). Это позволяет ядру доставить результат обратно клиенту тем же путём,
которым пришёл запрос. Для обычного синхронного вызова (RT.Type = S) поле не
нужно.
«Где и кем заполняется QCTX.ID и SD.SID?»
QCTX.ID присваивает ядро шины, когда запрос в неё входит, - дальше он не меняется и
проходит через все сервисы в цепочке. SD.SID появляется после успешного логина: его
выдаёт AuthMngr, клиент забирает его из ответа и прикладывает к последующим запросам.
Ваш сервис оба поля только читает.
Ядро не монолит. Внутри несколько служб, каждая отвечает за свой этап обработки запроса:
| Служба | За что отвечает |
|---|---|
| Прокси | точка входа: принимает внешний запрос в ядро |
| Приведение входных параметров | разбирает запрос, при необходимости достраивает Base из HTTP-заголовков |
| Конфигурации | держатель настроек, раздаёт конфигурацию сервисам при старте |
| Авторизация | проверяет запрос до того, как он попадёт в сервис |
| Реестр сервисов | знает все сервисы и методы, решает, кому перенаправить запрос |
| Кеширование | отдаёт готовый ответ из кеша (Redis), не дёргая сервис |
| Отправка запросов модулям | доставляет запрос нужному модулю и забирает ответ |
| Регистрация асинхронных запросов | принимает запрос сейчас, отдаёт результат клиенту позже |
Три из них стоит понять сразу:
Base.Полезно понимать, в каких случаях ваш код вообще не будет вызван:
S._E) и возвращает его клиенту. Ваш код не вызывается
вообще. Это гарантия, что сервис получает только «чистые» запросы: авторизованные и
адресованные ему.S._E и возвращает клиенту. Так все ошибки в
системе выглядят одинаково, независимо от того, где они возникли.Отсюда практический вывод: не пишите в каждом методе проверки «а вдруг пользователь не
авторизован» - до вас такой запрос не дойдёт. Зато ошибку своей бизнес-логики надо
формировать осознанно, а не позволять ей превратиться в случайный
NullPointerException (этим займёмся в уроке 4.1).
Модули общаются по HTTP, используя hostname машины - он же служит уникальным кодом
модуля. Запасной путь - шина сообщений RabbitMQ. Важное правило: за исключением
внешних запросов к самому ядру, модули всегда отвечают HTTP-кодом 200, а возникшая
ошибка передаётся внутри тела ответа (в S._E). Поэтому «200» от модуля ещё не значит
«успех» - смотреть нужно в тело ответа, а не только на HTTP-статус.
Если результат нужен сразу, запрос синхронный (B.RT.Type = "S"): ответ возвращается по
той же цепочке. Для долгих операций есть асинхронный режим ("A"): ядро через службу
регистрации асинхронных запросов сразу подтверждает приём, а готовый результат клиент
забирает позже по B.QCTX.ID.
Под капотом. По реализации ядро и сервисы - это Java-сервлеты под управлением Tomcat, Tomcat живёт в Debian в Docker-контейнере, а сеть шины организована через Kubernetes. Прикладному разработчику это знать не обязательно, но полезно помнить, что «модуль» физически - это контейнер в кластере (к этому вернёмся в уроке 2.1).
Base.Service.Это главное с урока. Когда вы начнёте писать сервис, вы будете видеть, в какую точку этого пути встраивается ваш код. Это шаг 7.
Кроме ядра, в CESB есть стандартные модули. Терминологической ловушки здесь нет:
GenericService, AuthMngr и прочие из таблицы - это системные сервисы, а раз
каждый сервис является модулем (см. §2), их одинаково корректно называть и «стандартные
сервисы», и «стандартные модули» - в документации и презентациях встречаются оба
варианта. Их не нужно писать, ими нужно уметь пользоваться:
| Модуль | Назначение |
|---|---|
| GenericService | сервисы без написания Java, через метаописание в JSON |
| AuthMngr | авторизация: проверяет запросы, хранит авторизационные данные |
| DeviceAgent | работа с внешними устройствами через шину |
| CBSMQ | связь СУБД CBS с шиной: вызовы из БД, очередь, гарантия доставки |
| Служба локализации | мультиязычность: словари и переводы |
Стандартные модули против ваших сервисов. Всё перечисленное поставляется вместе с
CESB. Ваша задача - не написать их заново, а научиться их настраивать и вызывать из
своего кода. Например, вы не будете реализовывать авторизацию: вы пометите свой
метод аннотацией @Auth, и проверку сделает AuthMngr через ядро. Не будете писать
свою очередь к базе - воспользуетесь CBSMQ. Не будете придумывать хранилище
настроек - возьмёте ConfMngr. Каждый раз, когда кажется, что нужно написать
инфраструктурный кусок, сначала проверьте, нет ли его в шине.
Несколько деталей, которые пригодятся дальше:
BasicGenericService и CBSGenericService. Хранится как
WAR-проект в GitLab и Nexus.Со всем этим вы работаете через CESB SDK - набор высокоуровневых методов, который почти полностью прячет внутреннюю кухню шины. Всё, что мы разобрали выше, происходит под капотом. Структуру SDK подробно разберём в модуле про разработку.
Стандартные модули из предыдущего раздела - это фундамент. Но на нём уже стоит здание: больше сотни прикладных сервисов, написанных за годы работы с банками. Ваш сервис встанет рядом с ними, и полезно заранее понимать, в какой ряд он попадёт.
Сервисы делятся на три группы, и это деление не формальное - от него зависит, кто сервис заказывает, кто сопровождает и в какой репозиторий он попадает.
| Группа | Сколько | Для кого пишется | Примеры |
|---|---|---|---|
| Общеполезные | около 50 | нужны любому банку, независимо от страны | loans, deposits, payments, cards, collateral |
| Локализованные | около 60 | требования конкретной страны и её регуляторов | munis, nibbd, uzLoanOffice, kzdayrates, swiftbav |
| Кастомизированные | единицы | под задачу конкретного банка | сервисы для отдельных банков, интеграция с их системами |
Общеполезные - это API к модулям АБС. Кредиты, депозиты, платежи, карты, зарплатные проекты, аккредитивы, факторинг, учёт обеспечения. Они не знают ничего про страну: их предметная область - банковское дело как таковое.
Локализованные - самая большая группа, и это закономерно. Каждая страна приносит свой набор обязательных интеграций: налоговая, кредитное бюро, реестр населения, регулятор, национальная платёжная система. Для Узбекистана это МУНИС, НИББД, ГРКИ, КАТМ, АНОР; для Казахстана - НБРК, КАСЕ, шлюз электронного правительства; для Азербайджана - свои. Один и тот же банковский продукт в трёх странах требует трёх разных наборов интеграций.
Кастомизированные - то, что нужно одному конкретному банку и больше никому.
Три практических вывода, которые пригодятся уже на первом задании.
Первое: скорее всего, ваш сервис не первый в своём роде. Прежде чем проектировать с нуля, посмотрите, нет ли рядом сервиса с похожей задачей. Если вы делаете интеграцию с внешней системой - почти наверняка есть готовый образец, устроенный ровно так, как надо устроить ваш.
Второе: у большинства типовых задач есть сложившийся тип решения. Интеграция с чужим
API без бизнес-логики на нашей стороне - это, как правило, прокси с одним методом: он
сам авторизуется во внешней системе, держит таймауты и приводит запрос к нужному виду,
но бизнес-решений не принимает. API к модулю АБС - ресурсная
модель с путями вида /loans/{colvirReferenceId}. Обмен пачками по расписанию - очередь
с планировщиком. Эти типы мы разберём в уроке 5.1 на боевых примерах.
Третье: инфраструктурные вещи уже решены и решены единообразно. Таймауты во всех
интеграционных сервисах называются одинаково: connectionRequestTimeout, connectTimeout,
responseTimeout. Секреты во всех сервисах хранятся одинаково - зашифрованными в
конфигурации. Не изобретайте своих имён и своих способов: чужой сервис должен читаться
вашим коллегой без объяснений.
Правило. Прежде чем писать свой механизм, найдите сервис шины, который решает похожую задачу, и посмотрите, как сделано там. Единообразие здесь важнее изящества: сопровождать эти сервисы будут люди, которые их не писали.
Ниже ориентир по основным доменам. Список не полный, и в вашем банке набор сервисов будет своим - его знает команда, которая сопровождает шину. Задача таблицы другая: чтобы вы понимали, какие задачи шина уже решает, и не проектировали их заново.
Клиенты и идентификация
| Сервис | О чём |
|---|---|
CliData, CliList | картотека клиентов АБС, базовый состав данных |
IBClients | работа с клиентами для интернет-банка, самый объёмный сервис каталога |
uzClient | клиент с полями, которые добавляет локализация |
nibbd | реестр населения, регистрация и идентификация физлиц |
UZMyId | биометрическая идентификация |
amllist | проверка на наличие в списке террористов |
ebp, econtract, aisnotary | единая база предпринимателей, электронные контракты, нотариат |
Счета, выписки, РКО
| Сервис | О чём |
|---|---|
uzAccounts, openbanking | информация по счетам клиентов и физлиц |
dearko | договоры на расчётно-кассовое обслуживание |
BankStatement | банковская выписка |
operations | операции бизнес-процессов АБС |
accountBookRequest | запросы на бронирование средств |
Платежи
| Сервис | О чём |
|---|---|
payments | расчётно-кассовое обслуживание и платежи, крупнейший платёжный сервис |
paydoc | расчётно-кассовые операции, документная сторона |
PayCld, PaySanct | контроль и санкционирование платежей |
PayType, PayCenters, paySystem | справочники видов платежей, центров, платёжных систем |
IBPayment | платежи со стороны интернет-банка |
epr, eprout | акцепты клиентов: получение и предоставление |
munis, munis-api, munis-agent | агрегатор платежей и работа с ним для разных потребителей |
gpi-tracker | отслеживание международных платежей |
Кредиты
| Сервис | О чём |
|---|---|
loans | чтение кредитных договоров, образцовая ресурсная модель |
loancreate | создание договоров кредитов и кредитных линий |
loancalc, loanoper | рассчитываемая информация: графики и суммы |
loanclientgroup | группы клиентов в кредитовании |
loan-api | приём платежей по кредитам внешними контрагентами |
collateral | учёт обеспечения |
loanrequestgkb, loanrequestpkb, uzLoanOffice, grki, nbrkessp | кредитные бюро и регистры |
katmapi, saveApplication | аналитическая платформа и регистрация заявок |
educationloan | образовательный кредит, пример прокси с OAuth |
conscript | кредитные каникулы призывникам |
Депозиты, карты, валюта
| Сервис | О чём |
|---|---|
deposits, IBDeposit | депозитные договоры со стороны АБС и интернет-банка |
cards, CorporateCard, IBCard | карточный бэк-офис, корпоративные карты, карты в интернет-банке |
Uzcard, OfbAPI, uzCardAutoPay | процессинговые центры |
ewallet | электронные кошельки |
conversion, conversion-base | покупка и продажа валюты клиентами |
fxControl | валютный контроль |
feruz, feruzJewels | регистрация валютных операций, операции с драгметаллами |
kzdayrates | курсы валют с сайта регулятора |
swiftbav | проверка реквизитов получателя через шлюз SWIFT |
Зарплата, персонал, специальные продукты
| Сервис | О чём |
|---|---|
salary, StaffSalary, StaffData | зарплатные проекты, заработная плата, картотека персонала |
factoring | факторинг, образцовый пример компенсирующих операций |
letterofcredit | аккредитивы |
leasing | лизинг |
ProjectRegistry | реестр проектов |
kafil, Osago-gross, trust | страхование риска невозврата и страховые компании |
Уведомления и доставка
| Сервис | О чём |
|---|---|
playmobile-sms-commands, uzPlayMobile | отправка СМС через провайдера |
bankmail | электронная доставка документов, очередь с планировщиком |
CourierMeaSoft | курьерская доставка |
Инфраструктура и служебные
| Сервис | О чём |
|---|---|
AuthMngr | авторизация, единая проходная шины |
kernel, Common | ядро и общие сервисы |
adidm | пользователи и полномочия АБС |
extreq | заявки из внешних систем |
Products | шаблоны продуктов |
fileExchange | обмен файлами между CBS и хранилищем данных |
qradar | отправка данных в систему мониторинга безопасности |
kz-kalkan, uz-kms | электронная подпись и управление ключами |
apnggate, ihamkor, iaip, kz-egov | шлюзы электронного правительства и платформ |
remoteBanking, DiBank | дистанционное банковское обслуживание |
Три группы из предыдущего раздела видны прямо в структуре репозиториев. Код сервисов шины разложен по контурам: у каждого банка свой контур со своими сервисами, а общеполезные сервисы и сервисы для внешних систем конкретной страны лежат отдельно.
| Где лежит | Что там |
|---|---|
контур банка: <банк>/services/<сервис> | локализованные и кастомизированные сервисы этого банка |
общие сервисы по стране: <группа>/<страна>/<сервис> | интеграции с государственными и внешними системами страны |
Отсюда важное наблюдение: один и тот же сервис может жить в контурах разных банков одновременно. Это не ошибка и не дублирование по недосмотру - это та самая «локализация», о которой шла речь выше. Задача общая (например, интеграция с государственным реестром), а реализация у каждого банка своя: отличаются внешние системы, форматы и требования регулятора.
Два следствия, важных на практике.
Одинаковое имя не значит одинаковое устройство. Сервисы с одним названием в разных контурах могут отличаться и контрактом, и логикой. Образцом служит описание именно того экземпляра, с которым вы работаете, а не одноимённого.
Общие приёмы одинаковы везде. Имена таймаутов, шифрование секретов, заголовочный
блок, формат depId_id соблюдаются во всех контурах. Различается бизнес-часть, а не
каркас. Поэтому приёмы из курса переносятся в ваш контур без изменений.
Разборы в уроках курса построены на документации боевых сервисов шины, а в работе вам придётся читать документацию сервисов своего банка постоянно. Документы устроены одинаково, и читать их быстро - навык, который окупается с первого раза.
Типовой состав разделов:
| Раздел | Что в нём |
|---|---|
| Введение | зачем сервис существует, две-три фразы |
| Определения | расшифровка сокращений домена |
| Расположение | репозиторий и адрес стенда |
| Общая схема работы | направление обмена и заголовочный блок |
| Схема интеграции | кто кого зовёт, если участников больше двух |
| Конфигурация | таблица настроек |
| Методы сервиса | контроллеры, методы, параметры запроса и ответа |
| Список ошибок | диапазон и коды |
| История изменений | версии, авторы, ссылки на задачи |
Не сверху вниз. Порядок, который экономит время:
Первое - «Общая схема работы». Там одна строка вида Внешняя система -> СШ -> АБС
или Система, передающая логи -> СШ -> QRADAR. Эта строка говорит больше, чем весь
остальной документ: она задаёт направление, а от направления зависит всё остальное.
Сервис, в который приходят снаружи, и сервис, который ходит наружу сам, устроены
по-разному, даже если оба называются интеграционными.
Второе - «Конфигурация». Читайте её как список того, что авторы ожидали менять.
Есть emulatorActive - значит, предусмотрели работу без внешней системы. Есть
DayLimitRequest - значит, столкнулись с превышением. Есть отдельные учётные данные для
мобильного банка - значит, у сервиса несколько потребителей и их различают.
Конфигурация - это спрессованная история эксплуатации.
Третье - «Методы сервиса». Теперь, зная направление и настройки, контракт читается осмысленно. Смотрите не только на список методов, но и на то, чего в нём нет: нет метода удаления - значит, в этом домене не удаляют; нет метода списка - значит, потребитель всегда знает идентификатор.
Четвёртое - «Список ошибок». Это перечень того, что в домене реально ломается. Быстрее любого описания даёт понять, о чём сервис на самом деле.
Пятое - «История изменений». Смотрите, что добавляли позже всего. Это то, чего не предусмотрели при проектировании, и почти всегда это же придётся предусмотреть вам.
Приём, который стоит освоить сразу. Открыв документацию, сначала найдите в ней одну строку направления обмена и одну таблицу конфигурации. Если после этих двух вы не можете сказать, к какому типу относится сервис - прокси, шлюз, сервис АБС, - значит, тип нестандартный, и читать надо внимательно. Если можете - дальше вы уже знаете, чего ожидать, и читаете только отличия.
Две вещи регулярно отсутствуют, и важно не искать их там, где их не бывает.
Почему сделано именно так. Документы описывают, что есть, а не почему выбрали этот вариант. Ответ обычно в задаче, на которую ссылается «История изменений».
Что происходит при сбое. Описано, как метод работает, но редко - что будет, если внешняя система не ответит. Это придётся выяснять по конфигурации (есть ли повторы и таймауты) и по списку ошибок.
Бизнес не приходит со словами «напишите контроллер». Он приходит с задачей: клиенты хотят переводить деньги, регулятор требует отчёт. Превратить задачу в решение помогают четыре вопроса - задавайте их себе каждый раз, в том же порядке:
B.QCTX.ID.У большинства задач уже есть сложившийся тип решения:
| Тип | Когда | Пример из каталога |
|---|---|---|
| Прокси | интеграция с чужим API без бизнес-логики на нашей стороне | educationloan |
| API к модулю АБС | ресурсная модель вида /loans/{colvirReferenceId} | loans |
| Обмен по расписанию | пачки данных через очередь с планировщиком | bankmail |
Пример: электронный кошелёк. Банк запускает кошелёк в мобильном приложении: регистрация, пополнение с карты, перевод другому клиенту. Разбор по вопросам:
AuthMngr.POST), чтение кошелька (GET), пополнение и перевод
(POST), статус операции (GET). Деньги, резерв и проводки - в АБС, а не в сервисе.Во всех таких решениях повторяется одно и то же: бизнес-логика живёт в сервисе, а вход, авторизация, кеш, очередь и связь с АБС уже есть в шине. Начинать надо с контракта, а не с кода, и ваш код встаёт на шаг 7 пути запроса. Ровно это от вас ждут в ДЗ-1 - только задача будет вашей.
Курс состоит из шести модулей: введение, установка и эксплуатация, основы разработки (два урока), реализация и тестирование, интеграции и Mid-Term проект с защитой. Отдельно финальный проект писать не нужно, он накопительно собирается из ваших заданий, и к защите у вас на руках будет рабочий сервис.
ДЗ-1 подготовительное, без кода и без коммита в GitLab. На этом шаге репозитория с
сервисом ещё нет, и мы проверяем не код, а продуманность вашего будущего сервиса: его
документацию (домен, сущности, методы, связь с АБС). Этот документ станет основой
README вашего проекта во втором уроке.
Конкретное задание выдаётся индивидуально в разделе «Задания». Там же ваш сквозной проект и критерии приёмки.
Base и Service.Про каталог и документацию:
Глоссарий: модуль, реплика, ядро (шлюз), Base, Service, BaS, реестр сервисов, AuthMngr, GenericService, CBSMQ.