Этот Docker-контейнер представляет из себя имплементацию интеграционной шины. Является тонким клиентом для проксирования запросов на приватные API.
Установка
docker run \
-e BOX_ADMIN_USER=user \
-e BOX_ADMIN_SECRET=secret \
-e PG_REAL_HOST=db \
-e PG_HOST=db \
-e PG_PORT=5432 \
-e PG_DATABASE=box_db \
-e PG_USER=user \
-e PG_PASSWORD=password \
-e QUEUE_URL=http://queue \
-e QUEUE_BACK_URL=http://box \
-e QUEUE_WORKER=box \
-d images.perfumerlabs.com/dist/box:v3.2.1
Переменные окружения
- BOX_ADMIN_USER - имя пользователя с админскими парвами, который будет создан при первой загрузке. Обязательно.
- BOX_ADMIN_SECRET - пароль пользователя с админскими парвами, который будет создан при первой загрузке. Обязательно.
- BOX_FETCH_LIMIT - максимальное число документов, возвращаемое в методе “/documents”. По умолчанию 100.
- BOX_IS_SYSTEM - определяет, является ли инстанс системным, т.е. предназначенным для синхррнизации данных. По умолчанию false.
- BOX_INSTANCES - Перечисленные через запятую инстансы, с которых нужно синхронизировать данные. Обязательно, если BOX_IS_SYSTEM=true.
- PG_HOST - PostgreSQL инстанс для подключения. Обязательно.
- PG_REAL_HOST - адрес базы данных PostgreSQL (НЕ PgBouncer). Обязательно.
- PG_SLAVES - перечисленные через запятую инстансы для slave-соединений. Опционально.
- PG_PORT - порт PostgreSQL. По умолчанию 5432.
- PG_DATABASE - название базы данных PostgreSQL. Обязательно.
- PG_SCHEMA - схема базы данных PostgreSQL. По умолчанию “public”.
- PG_USER - пользователь для подключения к PostgreSQL. Обязательно.
- PG_PASSWORD - пароль пользователя PostgreSQL. Обязательно.
- QUEUE_URL - адрес очереди Queue. Обязательно.
- QUEUE_BACK_URL - обратный адрес на шину, на которую очередь будет делать запрос. Обязательно.
- QUEUE_WORKER - название воркера на очереди, сконфигурированного для шины. Обязательно.
- PHP_PM_MAX_CHILDREN - число PHP FPM процессов. По умолчанию 10.
- PHP_PM_MAX_REQUESTS - лимит запросов на 1 процесс, после которого он перезагружается. По умолчанию 500.
Volumes
Контейнер не содержит volumes.
Если требуется дополнительная конфигурация контейнера, установите bash-скрипт в /opt/setup.sh. Этот скрипт выполнится при первой загрузке.
Доступы и авторизация
При первой загрузке контейнера будет создан пользователь с атрибутами, указанными в переменных BOX_ADMIN_USER
и BOX_ADMIN_SECRET
. Он обладает администраторскими правами. В дальнейшем можно создавать других пользователями и наделять их правами.
При создании пользователя, ему выдается специальный секрет. Каждый запрос на API шины должен содержать заголовок Api-Secret со значением этого секрета. Например:
Api-Secret: my_secret
Коллекции
Перед тем как работать с шиной, необходимо создать коллекции. Коллекция - это отдельная таблица в базе данных, содержащая документы, которые сохраняют пользователи. Необходимо создавать коллекцию на каждый отдельный сервис шины.
На каждую коллекцию отдельным пользователям возможно настроить доступы: только чтение из коллекции; запись и чтение. Администраторы могут как писать, так и читать из любой коллекции.
Чтобы создать коллекцию надо вызвать следующий метод API (действие доступно только администраторам):
POST /collection
JSON-параметры (json):
- name [string,required] - название коллекции (строго из маленьких латинских букв или цифр).
- type [string,required] - режим коллекции: “sync”, “async”, “storage”.
- handler [string,optional] - URL обработчика запросов. Для режимов коллекции “sync” и “async”.
Пример:
{
"name": "foobar",
"type": "sync",
"handler": "https://example.com"
}
Пример ответа:
{
"status": true
}
Чтобы выдать доступ к коллекции пользователю, надо вызвать метод API (действие доступно только администраторам):
POST /access
JSON-параметры:
- client [int,required] - ID пользователя.
- collection [int,required] - ID коллекции.
- level [string,required] - Доступ: “read” (только чтение) или “write” (чтение и запись).
Пример:
{
"client": 2,
"collection": 1,
"level": "write"
}
Пример ответа:
{
"status": true
}
Режимы коллекции
При создании коллекции можно указать режим работы. Всего доступно 3 режима: синхронный, асинхронный, промежуточное хранилище.
Cинхронный режим
Для создания такого типа коллекции необходимо передать при создании параметр “type”: “sync”. Также обязательно указать “handler”.
При запросе на такую коллекцию запрос будет автоматически перенаправлен на “handler” с данными переданными в запросе. Например:
Пользователь, имеющий доступ на запись в коллекцию делает запрос:
POST /document
JSON-параметры:
- collection [string,required] - Название коллекции.
- event [string,required] - название события/подсервиса/подколлекции.
- uuid [string,required] - сгенерированный UUID.
- data [mixed,required] - Данные для отправки на сервис.
Пример запроса:
{
"collection": "my_service",
"event": "my_event",
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"data": "Lorem ipsum dolor sit amet"
}
Шина сделает у себя внутри запрос на “handler” указанный при создании коллекции и вернет ответ:
JSON-параметры ответа:
- id [integer] - ID созданного документа.
- status_code [integer] - Статус кода ответа сервиса.
- body [mixed] - контент возвращенный сервисом.
Пример ответа:
{
"status": true,
"content": {
"document": {
"id": 1
},
"response": {
"status_code": 201,
"body": "data from service"
}
}
}
Асинхронный режим
Для создания такого типа коллекции необходимо передать при создании параметр “type”: “async”. Также обязательно указать “handler”.
Асинхронный режим работает аналогично синхронному. Разница в том, что асинхронная коллекция сразу не возвращает ответ от сервиса, а делает это позже на переданный webhook. Например:
Пользователь, имеющий доступ на запись в коллекцию делает запрос:
POST /document
JSON-параметры:
- collection [string,required] - Название коллекции.
- event [string,required] - название события/подсервиса/подколлекции.
- uuid [string,required] - сгенерированный UUID.
- data [mixed,required] - Данные для отправки на сервис.
- webhook [string,required] - URL, на который необходимо вернуть результат запроса на сервис.
Пример запроса:
{
"collection": "my_service",
"event": "my_event",
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"data": "Lorem ipsum dolor sit amet",
"webhook": "https://my-site.com"
}
Шина сохранит документ и вернет сохраненный ID:
JSON-параметры ответа:
- id [integer] - ID созданного документа.
Пример ответа:
{
"status": true,
"content": {
"document": {
"id": 1
}
}
}
Далее шина внутри себя через механизиы очередей делает запрос на сервис. В случае если сервис не отвечает, то шина будет стараться повторить запрос позже. При успешном ответе от сервиса шина вернет результат на указанный в документе webhook (структура аналогична синхронному ответу):
Пример запроса на webhook:
{
"status": true,
"content": {
"document": {
"id": 1
},
"response": {
"status_code": 201,
"body": "data from service"
}
}
}
Режим внутреннего хранилища
Данный режим предназначен для случаев, когда пользователи будут самостоятельно забирать данные из шины. Пользователь, имеющий доступ на запись, создает документы в шине по заранее согласованному формату, когда в его системе наступают некие события. Другой пользователь, имеющий доступ на чтение, периодически проверяет наличие новых документов и сохраняет их в своей системе.
Например, создается документ:
POST /document
JSON-параметры:
- collection [string,required] - Название коллекции.
- event [string,required] - название события/подсервиса/подколлекции.
- uuid [string,required] - сгенерированный UUID.
- data [mixed,required] - Данные для отправки на сервис.
Пример запроса:
{
"collection": "my_service",
"event": "my_event",
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"data": "Lorem ipsum dolor sit amet"
}
Другой пользователь, который хочет получить документы делает запросы:
GET /documents
Request parameters (json):
- collection [string,required] - Название коллекции.
- id [integer,optional] - ID документа от которого получить новые документы.
- limit [integer,optional] - лимит документов для получения.
Пример запроса:
{
"collection": "foobar",
"id": 100
}
параметры ответа (json):
- event [string] - название события/подсервиса/подколлекции.
- uuid [string] - UUID идентификатор.
- id [integer] - ID документа.
- data [mixed] - контент документа.
Пример ответа:
{
"status": true,
"content": {
"documents": [
{
"id": 101,
"event": "my_event",
"uuid": "uuid",
"data": [1, 2, 3]
}
]
}
}
Также можно получить число новых документов начиная с некоторого ID:
GET /documents/count
Request parameters (json):
- collection [string,required] - Название коллекции.
- id [integer,optional] - ID документа от которого получить новые документы.
Пример запроса:
{
"collection": "foobar",
"id": 100
}
Параметры ответа (json):
- documents [int] - число найденных документов.
Пример ответа:
{
"status": true,
"content": {
"documents": 5
}
}
High Availability
В случае, если требуется HA (High Availability), т.е. автоматический failover, если сервера шины становятся недоступными, необходимо сделать следующую настройку.
Допустим, у нас есть 2 кластера Cluster1 и Cluster2.
На Cluster1 разворачивается необходимое количество Master-Slave баз данных Postgresql, а также нужное количество контейнеров шины со следующим конфигом:
docker run \
-e BOX_ADMIN_USER=user \
-e BOX_ADMIN_SECRET=secret \
-e BOX_IS_SYSTEM=true \
-e BOX_INSTANCES=http://esb2 \
-e PG_REAL_HOST=db \
-e PG_HOST=db \
-e PG_PORT=5432 \
-e PG_DATABASE=box_db \
-e PG_USER=user \
-e PG_PASSWORD=password \
-e QUEUE_URL=http://queue \
-e QUEUE_BACK_URL=http://box \
-e QUEUE_WORKER=box \
-d docker/image
Ключевыми параметрами здесь являются BOX_IS_SYSTEM и BOX_INSTANCES. BOX_IS_SYSTEM показывает, что этому контейнеру надо производить синхронизацию данных. BOX_INSTANCES - указывается адрес кластера Cluster2. При установке таких параметров контейнер будет сихронизировать схему коллекций (кроме документов), клиентов и доступы с Cluster2.
Аналогично на Cluster2 разворачивается необходимое количество своих Master-Slave баз данных Postgresql, а также необходимо поднимать контейнеры со следующей конфигурацией:
docker run \
-e BOX_ADMIN_USER=user \
-e BOX_ADMIN_SECRET=secret \
-e BOX_IS_SYSTEM=true \
-e BOX_INSTANCES=http://esb \
-e PG_REAL_HOST=db2 \
-e PG_HOST=db2 \
-e PG_PORT=5432 \
-e PG_DATABASE=box_db \
-e PG_USER=user \
-e PG_PASSWORD=password \
-e QUEUE_URL=http://queue2 \
-e QUEUE_BACK_URL=http://box2 \
-e QUEUE_WORKER=box \
-d docker/image
где в BOX_INSTANCES указывается адрес кластера Cluster1.