Руководство прикладного разработчика#
Шлюз ActiveMQ Artemis, ASGT далее (Шлюз) продукта Platform V Synapse Enterprise Integration (SEI) поставляется в виде собранного Docker-образа, размещаемого в целевом Docker-репозитории, и предназначается для использования в составе прикладных интеграционных решений, разрабатываемых продуктовыми командами.
Термины и определения#
Термин/Аббревиатура |
Определение |
|---|---|
XML |
eXtensible Markup Language |
JSON |
JavaScript Object Notation, текстовый формат обмена данными, основанный на JavaScript |
API |
Application Programming Interface |
HTTP |
HyperText Transfer Protocol, протокол передачи гипертекста |
HTTP/2 |
Вторая версия протокола Hypertext Transfer Protocol |
SSL |
Security Socket Layer |
JMS |
Java Message System |
MQ |
Message Queue |
gRPC |
Google Remote Procedure Call |
REST |
Representational State Transfer, архитектурный стиль взаимодействия компонентов распределенного приложения в сети |
URI |
Uniform Resource Identifier, унифицированный идентификатор ресурса |
URL |
Система унифицированных адресов электронных ресурсов |
RPC |
Remote Procedure Call, система удаленного вызова процедур |
Service Mesh |
Конфигурируемый инфраструктурный уровень с низкой задержкой. Используется для обработки большого объема сетевых межпроцессных коммуникаций между API |
Spring |
Сокращение от Spring Framework, универсальный фреймворк с открытым исходным кодом для Java-платформы |
Spring Boot |
Проект, который позволяет упростить создание приложений на основе Spring |
Artemis |
Программный продукт Apache ActiveMQ Artemis |
ВХС |
Внешнее хранилище секретов на основе hashicorp vault |
Системные требования#
Требования к системному программному обеспечению приведены в разделе Системные требования документа «Руководство по установке»
Подключение и конфигурирование#
Перечень артефактов Kubernetes, требующихся для запуска тестового экземпляра Шлюза.
Артефакт |
Содержание |
Описание |
|---|---|---|
Deployment |
Параметры запуска контейнера приложения в Kubernetes |
Наименование экземпляра приложения, ссылка на образ контейнера приложения, запрашиваемые ресурсы, публикуемые порты, параметры liveness и readiness проб, необходимость и параметры подключения sidecar-контейнеров, точки монтирования конфигурационных артефактов в файловую систему контейнера |
Config Map |
application.yml |
Файл, содержащий параметры конфигурации приложения |
Secret |
Ключи и сертификаты |
Файлы, содержащие ключи и сертификаты для подключения к брокерам Artemis по SSL. Содержит конфиденциальные данные, поэтому загружается в виде секрета |
Service |
Артефакт для регистрации приложения в service discovery Kubernetes |
Селекторы и порты для подключения приложения к механизмам распределения трафика Kubernetes |
Virtual Service |
Артефакт для настройки политик Istio |
Параметры маршрутизации трафика между сервисами в Kubernetes |
Destination Rule |
Артефакт для настройки политик Istio |
Параметры балансировки трафика между pods приложения |
Service Entry |
Артефакт для регистрации внешнего сервиса в Kubernetes |
Содержит адреса хостов и номера портов для подключения к брокерам Artemis. Если для нужных брокеров Service Entry уже установлен в проекте, загружать его повторно не требуется |
Service |
Артефакт регистрирующий фиктивный сервис (empty-service) |
empty-service — фиктивный сервис Kubernetes, требуется в каждом проекте для правильной работы механизмов маршрутизации Istio. В отличие от реального сервиса, в empty-service НЕ должно быть задано значение параметра selector |
Порядок подключения#
На брокерах Artemis Dev-стенда создать 2 тестовые очереди для входящих и исходящих сообщений (например, TEST.GW.IN и TEST.GW.OUT);
Проверить и при необходимости загрузить артефакт ServiceEntry, задающий точку подключения;
В артефакте должны быть указаны параметры:
spec.hosts[].<hostname>
spec.ports[].protocol: tcp
spec.ports[].name: tcp
spec.ports[].number:<port>
нужного брокера Artemis
ServiceEntry
apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: amq-brocker-se spec: exportTo: - . hosts: - <hostname брокера MQ> location: MESH_EXTERNAL ports: - name: tcp number: <port брокера MQ> protocol: tcp resolution: DNSПодготовить и загрузить артефакт Config Map c файлом application.yml, задающий настройки Шлюза.
В артефакте должны быть указаны параметры:
режима работы Шлюза:
mq.typeMQ: ARTEMIS_MQ (значение по умолчанию - ARTEMIS_MQ может быть опущено)
mq.workMode: all
mq.systemType: sp
очередей MQ:
mq.connection.receiveQueue[]: [TEST.GW.IN]
mq.connection.sendQueue: TEST.GW.OUT
подключения к MQ:
mq.connection.connections[].url: <протокол>://<имя хоста>:<номер порта>
mq.connection.connections[].username: <логин для подключения к брокеру>
mq.connection.connections[].password: <пароль для подключения к брокеру>
порта Healthcheck:
server.port: 8787
сервера и клиента gRPC:
grpc.server.serverPort: 5454
grpc.client.settings.default.port: 5454
трейсинга
tracing.tracingHeaders[].x-synapse-rquid:<заполнить из примера ниже>
и маршрутизации:
routing.routeList[].destinationExpression: ServiceName
routing.routeList[].variables[]:<заполнить из примера ниже>
ConfigMap
kind: ConfigMap apiVersion: v1 metadata: name: test-gw-config data: application.yml: |- mq: typeMQ:ARTEMIS_MQ workMode: async systemName: test systemType: sp connection: receiveQueue: [TEST.GW.IN] sendQueue: TEST.GW.OUT connections: - url: <протокол>://<имя хоста>:<номер порта> # <протокол>='amqp' для подключения без ssl username: <логин к брокеру MQ> password: <пароль к брокеру MQ> server: port: 8787 grpc: server: serverPort: 5454 client: settings: default: hostname: empty-service port: 5454 tracing: generateXB3Headers: 'true' generate128bitTraceId: 'true' tracingHeaders: x-synapse-rquid: - type: fromBody value: //RqUID routing: routeList: - routeName: default destinationExpression: ServiceName variables: - name: ServiceName valueFrom: - type: fromConst value: <имя клиентского приложения>Подготовить и загрузить артефакт Deployment, задающий параметры запуска контейнера Шлюза;
В артефакте должны быть заданы параметры:
spec.template.metadata.labels[].app: <имя сервиса Шлюза> #в приведенном здесь примере test-gw
spec.template.spec.volumes[0].configMap.name: <Имя артефакта Config Name>
spec.template.spec.containers[].ports[].containerPort: 5454
spec.template.spec.containers[].ports[].containerPort: 8787
spec.template.spec.containers[].image: <ссылка на Docker-образ Шлюза в целевом репозитории>
В подсекции
resourcesзадаются limits и requests ЦПУ и памяти, необходимые для нормальной работы приложения. Эти параметры зависят от нагрузки на экземпляр Шлюза и должны быть определены при выполнении нагрузочного тестирования конкретной интеграционной цепочки.Выделение ресурсов для приложения должно удовлетворять следующим ограничениям:
memory - не более 8 Гб на Pod;
CPU не более 4 ядер;
размер контейнера не более 1024 Мб;
размер временное хранилища (ephemeral volume) для Pod не должен превышать 2.5 ГБ.
Deployment
kind: Deployment apiVersion: apps/v1 metadata: name: test-gw spec: replicas: 1 selector: matchLabels: app: test-gw template: metadata: labels: app: test-gw annotations: sidecar.istio.io/inject: 'true' spec: volumes: - name: application-config configMap: name: test-gw-config items: - key: application.yml path: application.yml defaultMode: 256 - name: synapselogs emptyDir: {} containers: - resources: limits: cpu: 200m memory: 400Mi requests: cpu: 100m memory: 330Mi readinessProbe: httpGet: path: /actuator/health/readiness port: 8787 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 periodSeconds: 2 successThreshold: 1 failureThreshold: 2 terminationMessagePath: /dev/termination-log name: test-gw livenessProbe: httpGet: path: /actuator/health/liveness port: 8787 scheme: HTTP initialDelaySeconds: 180 timeoutSeconds: 5 periodSeconds: 60 successThreshold: 1 failureThreshold: 10 env: - name: PROJECT_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: NODE_IP valueFrom: fieldRef: apiVersion: v1 fieldPath: status.hostIP ports: - containerPort: 5454 protocol: TCP - containerPort: 8787 protocol: TCP imagePullPolicy: Always securityContext: privileged: false runAsNonRoot: true readOnlyRootFilesystem: true capabilities: drop: ["ALL"] allowPrivilegeEscalation: false runAsUser: 1001 # DropApp/Kubernetes runAsGroup: 1001 # DropApp/Kubernetes seccompProfile: # DropApp/Kubernetes type: RuntimeDefault volumeMounts: - name: application-config readOnly: true mountPath: /deployments/config - name: synapselogs mountPath: /opt/synapse/logs terminationMessagePolicy: File image: >- <ссылка на докер-образ в целевом репозитории> terminationGracePeriodSeconds: 60 securityContext: runAsUser: 1002 # DropApp/Kubernetes runAsGroup: 1002 # DropApp/Kubernetes runAsNonRoot: true fsGroup: 1001 # DropApp/Kubernetes seccompProfile: # DropApp/Kubernetes type: RuntimeDefault strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25%Подготовить и загрузить артефакт Service, регистрирующий сервис в Kubernetes.
В артефакте должны быть заданы параметры:
spec.ports[].name: grpc spec.ports[].protocol: TCP spec.ports[].port: 5454 spec.ports[].targetPort: 5454
Service
kind: Service apiVersion: v1 metadata: name: test-gw spec: ports: - name: grpc protocol: TCP port: 5454 targetPort: 5454 selector: app: test-gwПроверить, что Шлюз запущен и готов к работе.
В консоли Kubernetes войти в меню Workloads/pods, найти pod Шлюза и, перейдя по ссылке в наименовании pod, проверить, что он имеет статус Running.
Зайти в терминал pod и выполнить команду:
sh-4.2$ curl localhost:8799/actuator/health/ping {"status":"UP"}Отклик {"status":"UP"} показывает, что Шлюз запущен и готов к работе.
Миграция на текущую версию#
Для миграции на текущую версию требуется:
Уточнить в разделе Примечания к релизу необходимость внесения изменений в конфигурацию Шлюза при переходе на текущую версию;
При необходимости подготовить Config map с новой конфигурацией;
Подготовить артефакт Deployment, в котором заменить ссылку на docker-образ Шлюза в репозитории ссылкой на Docker-образ с текущей версией;
Если это указано в разделе «Примечания к релизу», изменить значения выделяемых ресурсов;
Остановить Шлюз;
Загрузить новую конфигурацию Шлюза;
Загрузить новый deployment;
Запустить Шлюз (если в deployment указано количество реплик >0, Шлюз запустится автоматически).
Дополнительно:
Порядок действий при обновлении описан в разделе Обновление документа Руководство по установке.
Порядок действий для остановки и запуска Шлюза описано в разделе Сценарии администрирования документа Руководство по системному администрированию.
Быстрый старт#
Разработка первого приложения с использованием программного компонента#
Подготовить proto-файлы с описанием универсального API Шлюза:
Message.proto
syntax = "proto3"; import "google/protobuf/any.proto"; package com.sbt.synapse.gateway; message ProtoMessage { string messageId = 1; string correlationId = 2; string body = 14; map<string, string> systemHeaders = 3; map<string, string> userHeaders = 4; google.protobuf.Any extension = 15; }Heartbeat.proto
syntax = "proto3"; package com.sbt.synapse.gateway; message Heartbeat { int64 timestamp = 1; string messageId = 2; }MessageService.proto
syntax = "proto3"; import "Message.proto"; import "Heartbeat.proto"; package com.sbt.synapse.gateway; option java_multiple_files = true; option java_package = "com.sbt.synapse.gateway.protobuf"; option java_outer_classname = "MessageService"; option objc_class_prefix = "HLW"; service MessageAsyncChannel { rpc processMessage (ProtoMessage) returns (Heartbeat); } service MessageSyncChannel { rpc processMessage (ProtoMessage) returns (ProtoMessage); }MqMessageInformation.proto
syntax = "proto3"; package com.sbt.synapse.gateway.mq; message MqMessageInformation { enum DeliveryMode { UNKNOWN_MODE = 0; NON_PERSISTENT = 1; PERSISTENT = 2; } enum MessageType { UNKNOWN_TYPE = 0; REQUEST = 1; REPLY = 2; REPORT = 4; DATAGRAM = 8; } MessageType messageType = 1; int32 priority = 2; DeliveryMode deliveryMode = 3; int64 expiry = 4; string destinationQueue = 5; string destinationManager = 6; string sourceQueue = 7; string sourceManager = 8; string jmsType = 9; }Создать проект простого Springboot приложения;
По proto-описанию сгенерировать Java-классы, используя proto-компилятор (protoc) или плагин для используемой системы сборки (gradle, maven);
Добавить полученные файлы к проекту.
Package
Classes
com.sbt.synapse.gatewayMessageHeartbeatOuterClasscom.sbt.synapse.gateway.protobufMessageAsyncChannelGrpc MessageSyncChannelGrpccom.sbt.synapse.gateway.mqMqMessageInformationOuterClassДополнительно прописать зависимости:
Зависимости
<dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.20.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.20.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-core</artifactId> <version>1.20.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> <version>1.20.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-services</artifactId> <version>1.20.0</version> </dependency>Добавить импорт полученных классов, а также классов поддержки protobuf и grpc в свое приложение
Импорт классов
import com.google.protobuf.Any; import com.sbt.synapse.gateway.HeartbeatOuterClass.Heartbeat; import com.sbt.synapse.gateway.protobuf.MessageAsyncChannelGrpc; import com.sbt.synapse.gateway.Message.ProtoMessage; import com.sbt.synapse.gateway.mq.MqMessageInformationOuterClass.MqMessageInformation; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.stub.StreamObserver;Добавить в приложение сервис для приема и асинхронных входящих вызовов и отправки подтверждений
Пример сервиса
@GRpcService public class GrpcService extends MessageAsyncChannelGrpc.MessageAsyncChannelImplBase { @Override public void processMessage(ProtoMessage message, StreamObserver<Heartbeat> responseObserver) { Logger logger = LoggerFactory.getLogger(GrpcService.class); logger.info("Request: " + message.getBody()); responseObserver.onNext(Heartbeat.newBuilder().setMessageId(message.getMessageId()).setTimestamp(System.currentTimeMillis()).build()); responseObserver.onCompleted(); } }Добавить в приложение клиента, формирующего простой запрос в XML-формате с установкой messageId и Expiry
Пример клиента
@Component public class GrpcClientSender { @Value("${service.host}") private String serviceHost; @Value("${service.port}") private int servicePort; public void makeRequest() { Logger log = LoggerFactory.getLogger(GrpcClientSender.class); ManagedChannel channel = ManagedChannelBuilder.forAddress(serviceHost, servicePort).usePlaintext().build(); MqMessageInformation mqMessageInformation = MqMessageInformation.newBuilder().setExpiry(30000).build(); ProtoMessage message = ProtoMessage.newBuilder() .setBody("<Rq><RqUID>12345678901234567890123456789012</RqUID></Rq>").setExtension(Any.pack(mqMessageInformation)).setMessageId("123456789012345678901234567890").build(); MessageAsyncChannelGrpc.MessageAsyncChannelBlockingStub messageAsyncChannelBlockingStub = MessageAsyncChannelGrpc.newBlockingStub(channel); try { Heartbeat pongMessage = messageAsyncChannelBlockingStub.processMessage(message); log.info("Response: " + pongMessage.getMessageId()); } catch (Exception e) { System.out.println("catch error " + e.getMessage()); } finally { channel.shutdown(); } } }В application.properties задать параметры:
фрагмент application.properties
service.host=localhost service.port=5454 server.port=8787 grpc.port=5454Для публикации образа приложения в docker-registry создать Dockerfile:
В нем указать, на основе какого базового образа собирать контейнер с приложением, имя JAR-файла приложения для установки в контейнер и команду для его запуска.
Dockerfile
#Ссылка на базовый Docker-образ, нужно указать свой FROM <базовый образ для сборки> ADD <jarName>.jar /app/<jarName>.jar CMD touch /app/<jarName>.jar ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dspring.config.location=file:/deployments/config/application.properties","-Djava.security.egd=file:/dev/./urandom","-jar","/app/<jarName>.jar"]Собрать Docker-образ и опубликовать его в Dev-репозиторий
Настроить артефакты для приложения:
Config Map
kind: ConfigMap apiVersion: v1 metadata: name: test-app-config data: application.properties: |- server.port=8787 grpc.port=5454 service.host=<имя сервиса Шлюза> service.port=5454Deployment
kind: Deployment apiVersion: apps/v1 metadata: name: test-app spec: replicas: 1 selector: matchLabels: app: test-app template: metadata: labels: app: test-app annotations: sidecar.istio.io/inject: 'true' spec: volumes: - name: application-config configMap: name: test-app-config items: - key: application.properties path: application.properties defaultMode: 400 containers: - resources: limits: cpu: 200m memory: 400Mi requests: cpu: 100m memory: 330Mi name: test-app env: - name: PROJECT_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace ports: - containerPort: 5454 protocol: TCP - containerPort: 8787 protocol: TCP imagePullPolicy: Always volumeMounts: - name: application-config readOnly: true mountPath: /deployments/config terminationMessagePolicy: File image: >- <ссылка на Docker-образ приложения в dev-репозитории> terminationGracePeriodSeconds: 80Service
apiVersion: v1 kind: Service metadata: name: test-app spec: selector: app: test-app ports: - name: grpc port: 5454 targetPort: 5454 type: LoadBalancerЗагрузить артефакты в Kubernetes.
Зайти в терминал pod приложения и проверить, что в логах отражаются записи об успешной отправке сообщений.
Пример лога клиента
2021-02-07 10:54:27.740 INFO 14592 --- [ main] c.s.s.workshop.grpc.GrpcClientSender : Response: 123456789012345678901234567890 2021-02-07 10:54:27.743 INFO 14592 --- [ main] c.s.s.workshop.grpc.GrpcClientSender : Response: 123456789012345678901234567890 2021-02-07 10:54:27.746 INFO 14592 --- [ main] c.s.s.workshop.grpc.GrpcClientSender : Response: 123456789012345678901234567890Чтобы проверить прием входящих сообщений в асинхронном режиме, нужно разместить сообщение в тестовой очереди входящих сообщений.
В логе приложения должна появиться запись о приеме сообщения.
Пример лога сервера
2021-02-07 10:54:27.743 INFO 3876 --- [ault-executor-0] c.sbt.synapse.workshop.grpc.GrpcService : Request: <Rq><RqUID>12345678901234567890123456789012</RqUID></Rq> 2021-02-07 10:54:27.746 INFO 3876 --- [ault-executor-0] c.sbt.synapse.workshop.grpc.GrpcService : Request: <Rq><RqUID>12345678901234567890123456789012</RqUID></Rq> 2021-02-07 10:54:27.748 INFO 3876 --- [ault-executor-0] c.sbt.synapse.workshop.grpc.GrpcService : Request: <Rq><RqUID>12345678901234567890123456789012</RqUID></Rq>
Использование программного компонента#
Асинхронный режим работы#
В этом режиме Шлюз может принимать асинхронные запросы по gRPC и передавать их в очередь Artemis, считывать сообщения из очереди Artemis и асинхронно отправлять их по gRPC.
Конфигурация Шлюза#
Для запуска Шлюза в этом режиме необходимо в конфигурационном файле application.yml установить параметры:
mq:
workMode: all # Шлюз работает только в совмещенном (синхронно/асинхронном режиме)
systemName: <имя системы> # аббревиатура внешней системы
systemType: <sc/sp> # sc - если инициатор взаимодействия - внешняя система, sp - если микросервис
connection:
receiveQueue: [<имя входящей очереди>] # Список очередей, из которых Шлюз читает сообщения, которые будут обработаны асинхронно
sendQueue: <имя исходящей очереди> # очередь, в которую Шлюз кладет сообщения
connections:
- url: <hostname брокера Artemis> # при подключении без SSL
username: <логин к брокеру Artemis>
password: <пароль к брокеру Artemis>
- url: <hostname брокера Artemis> # при подключении по SSL
sslConfigName: <имя профиля SSL> # имя профиля SSL из секции sslConfigs
sslConfigs:
- sslConfigName: <имя профиля SSL>
verifyHost: false # принудительно отключает проверку CN сертификата брокера на соответствие имени хоста
allowedDNs: # список DN брокеров к которым разрешено подключение
- <DN брокера>
sslCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
sslSocketFactory:
protocol: TLSv1.2
keyPem: <путь к файлу с личным ключом Шлюза>
certPem: <путь к файлу с сертификатом Шлюза>
rootPem: <путь к файлу с сертификатами УЦ>
server:
port: <порт HTTP> # порт HTTP, на котором выставляется эндпойнт actuator/health для liveness и readiness проб
grpc:
server:
serverPort: <порт gRPC> # порт, на котором поднимается gRPC-сервер для приема входящих запросов
client:
settings:
default:
hostname: empty-service
port: <порт> # порт по которому Шлюз будет выполнять исходящие gRPC-вызовы
tracing: # задает заголовки для исходящего gRPC вызова и правила их заполнения
generateXB3Headers: 'true'
generate128bitTraceId: 'true'
tracingHeaders:
x-synapse-rquid: # правило определения заголовка x-synapse-rquid по входящему сообщению
- type: fromBody
value: //RqUID
x-synapse-operationname: # правило определения заголовка x-synapse-operationname по входящему сообщению
- type: fromBody
value: local-name(/*)
routing: # задает правила маршрутизации исходящего gRPC вызова (определение имени сервиса назначения)
routeName: # определение имени маршрута
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
routeList:
- routeName: default # имя маршрута. Правила описанные в default применяются по-умолчанию
destinationExpression: toLower(ServiceName)
variables:
- name: ServiceName
valueFrom:
- type: fromBody,
value: '//ServiceName'
exp: coalesce(value?"<имя вызываемого сервиса по-умолчанию>":value)
Отправка сообщения в MQ#
Для отправки сообщения в очередь Artemis нужно сделать вызов асинхронного API Шлюза:
Heartbeat MessageAsyncChannel.ProcessMessages(ProtoMessage)
Обязательные поля ProtoMessage:
Поле |
Тип |
Описание |
|---|---|---|
body |
string |
информационное сообщение в формате XML для отправки в MQ |
Дополнительные поля ProtoMessage
Поле |
Тип |
Описание |
|---|---|---|
messageId |
string |
Задать при необходимости установить определенное значение при отправке. Если отсутствует – будет сгенерировано в момент отправки в MQ |
correlationId |
string |
Задать при необходимости установить определенное значение при отправке. Если отсутствует – не будет установлено |
extension.expiry |
int64 |
Задать при необходимости установить время жизни сообщения в очереди |
Обязательные заголовки gRPC
Заголовок |
Описание |
|---|---|
x-synapse-rquid |
Уникальный идентификатор сообщения |
x-synapse-operationname |
Имя операции |
x-synapse-from-pod-name |
Имя pod сервиса — инициатора вызова |
Поля возвращаемого Heartbeat
Поле |
Тип |
Описание |
|---|---|---|
timestamp |
int64 |
время получения сообщения |
messageId |
string |
messageId отправленного в MQ сообщения |
Чтение сообщений из MQ#
Шлюз постоянно опрашивает очередь входящих сообщений.
При появлении сообщения в очереди Шлюз считывает сообщение и выполняет вызов асинхронного API:
Heartbeat MessageAsyncChannel.ProcessMessages(ProtoMessage)
Имя сервиса назначения определяется по правилам, прописанным в секции routing конфигурации Шлюза.
Обязательные поля ProtoMessage:
Поле |
Тип |
Описание |
|---|---|---|
messageId |
string |
MessageId входящего сообщения |
correlationId |
string |
CorrelationId входящего сообщения |
body |
string |
Информационное сообщение в формате XML |
extension.sourceQueue |
string |
Очередь, из которой было считано входящее сообщение |
Дополнительные поля ProtoMessage
Поле |
Тип |
Описание |
|---|---|---|
systemHeaders |
map<string, string> |
Заполняется при наличии во входящем сообщении свойств с ключами, имеющими префикс JMS |
userHeaders |
map<string, string> |
Заполняется при наличии во входящем сообщении свойств с ключами, не имеющими префикс JMS |
Обязательные заголовки gRPC
Заголовок |
Описание |
|---|---|
x-synapse-rquid |
Уникальный идентификатор сообщения |
x-synapse-operationname |
Имя операции |
x-synapse-from |
Имя внешней системы из конфигурации Шлюза |
x-synapse-from-pod-name |
Имя pod Шлюза, принявшего сообщение |
Поля возвращаемого Heartbeat
Поле |
Тип |
Описание |
|---|---|---|
timestamp |
int64 |
время получения сообщения |
messageId |
string |
messageId из ProtoMessage (не меняется) |
Синхронный режим, отправка сообщений в MQ#
В этом режиме Шлюз может принимать синхронные запросы по gRPC и передавать их в очередь Artemis, возвращая в ответе считанное из MQ ответное сообщение. Режим неблокирующий, во время ожидания прихода ответных сообщений Шлюз продолжает принимать новые вызовы по gRPC.
Конфигурация Шлюза#
Для запуска Шлюза в этом режиме необходимо в конфигурационном файле application.yml установить параметры:
mq:
systemName: <имя системы> # аббревиатура внешней системы
systemType: sp # sp - инициатор взаимодействия микросервис
workMode: sync # режим работы - синхронный
connection:
sendQueue: <имя исходящей очереди> # очередь, в которую Шлюз кладет сообщения
connections:
- url: <hostname брокера Artemis> # при подключении без SSL
username: <логин к брокеру Artemis>
password: <пароль к брокеру Artemis>
- url: <hostname брокера Artemis> # при подключении по SSL
sslConfigName: <имя профиля SSL> # имя профиля SSL из секции sslConfigs
sslConfigs:
- sslConfigName: <имя профиля SSL>
verifyHost: false # принудительно отключает проверку CN сертификата брокера на соответствие имени хоста
allowedDNs: # список DN брокеров к которым разрешено подключение
- <DN брокера>
sslCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
sslSocketFactory:
protocol: TLSv1.2
keyPem: <путь к файлу с личным ключом Шлюза>
certPem: <путь к файлу с сертификатом Шлюза>
rootPem: <путь к файлу с сертификатами УЦ>
sync-receiver:
poolSize: 20 # число потоков выполняющих чтение - разбор очереди
startDelay: 1 # отложить время чтения ответа на ms
maxDelay: 10 # максимальная задержка переповтора.
maxProcessingTime: 100000 # таймаут ожидания ответного сообщения
maxStopTime: 100000 # время ожидания получения ответов при остановке Шлюза
receiveTimeout: 50 # таймаут на операцию чтения
defaultReceiveQueue: <имя входящей очереди> # дефолтная очередь используется если в сообщении не задан ReplyToQ
server:
port: <порт HTTP> # порт HTTP, на котором выставляется эндпойнт actuator/health для liveness и readiness проб
grpc:
server:
serverPort: <порт gRPC> # порт, на котором поднимается gRPC-сервер для приема входящих запросов
client:
settings:
default:
hostname: empty-service
port: <порт> # порт по которому Шлюз будет выполнять исходящие gRPC-вызовы
tracing: # задает заголовки для исходящего gRPC вызова и правила их заполнения
generateXB3Headers: 'true'
generate128bitTraceId: 'true'
tracingHeaders:
x-synapse-rquid: # правило определения заголовка x-synapse-rquid по входящему сообщению
- type: fromBody
value: //RqUID
x-synapse-operationname: # правило определения заголовка x-synapse-rquid по входящему сообщению
- type: fromBody
value: local-name(/*)
Отправка сообщения в MQ#
Для отправки сообщения в очередь Artemis нужно сделать вызов синхронного API Шлюза:
ProtoMessage MessageSyncChannel.ProcessMessages(ProtoMessage)
Обязательные поля ProtoMessage:
Поле |
Тип |
Описание |
|---|---|---|
body |
string |
информационное сообщение в формате XML для отправки в MQ |
Дополнительные поля ProtoMessage
Поле |
Тип |
Описание |
|---|---|---|
messageId |
string |
Задать при необходимости установить определенное значение при отправке. Если отсутствует — будет сгенерировано в момент отправки в MQ |
correlationId |
string |
Задать при необходимости установить определенное значение при отправке. Если отсутствует — не будет установлено. |
extension.expiry |
int64 |
Задать при необходимости установить время жизни сообщения в очереди. |
systemHeaders |
map<string, string> |
Если содержит пару "ReplyToQ":"<имя очереди>" Шлюз ждет ответное сообщение в этой очереди. Внешняя система должна уметь отвечать по этому заголовку. |
Обязательные заголовки gRPC
Заголовок |
Описание |
|---|---|
x-synapse-rquid |
Уникальный идентификатор сообщения |
x-synapse-operationname |
Имя операции |
x-synapse-from-pod-name |
Имя pod сервиса — инициатора вызова |
Прием ответного сообщения из MQ#
Шлюз постоянно опрашивает очередь ответных сообщений. При появлении ответного сообщения считывает его и возвращает ProtoMessage в ответе на gRPC вызов. Если в полученном ответе отсутствует (пустое) тело сообщения, то Шлюз записывает в системный лог предупреждение: "Отсутствует тело в ответе на сообщение <ID сообщения>".
Считывание производится по CorrelationId.
Обязательные поля возвращаемого ProtoMessage:
Поле |
Тип |
Описание |
|---|---|---|
messageId |
string |
MessageId входящего сообщения |
correlationId |
string |
CorrelationId должен содержать MessageId исходного сообщения |
body |
string |
Информационное сообщение (ответ) в формате XML |
extension.sourceQueue |
string |
Очередь, из которой было считано входящее сообщение |
Дополнительные поля возвращаемого ProtoMessage
Поле |
Тип |
Описание |
|---|---|---|
systemHeaders |
map<string, string> |
Заполняется при наличии во входящем сообщении свойств с ключами, имеющими префикс JMS |
userHeaders |
map<string, string> |
Заполняется при наличии во входящем сообщении свойств с ключами, не имеющими префикс JMS |
Обязательные заголовки gRPC
Заголовок |
Описание |
|---|---|
x-synapse-rquid |
Уникальный идентификатор сообщения |
x-synapse-operationname |
Имя операции |
x-synapse-from |
Имя внешней системы из конфигурации Шлюза |
x-synapse-from-pod-name |
Имя pod Шлюза, принявшего сообщение |
Тайм-аут#
Если ответное сообщение не вычитано за время, установленное настройкой mq.sync-receiver.maxProcessingTime, то в ответ на синхронный вызов возвращается исключение deadline-exceeded
Дополнительно в Шлюзе реализованы режимы синхронного чтения ответов со всех подключенных менеджеров. Подробнее описано в разделе Особенности режима синхронного поставщика в кластере Artemis данного документа.
Синхронный режим, чтение сообщений из MQ#
В этом режиме Шлюз читает сообщения из Artemis и синхронно отправляет их по gRPC. Режим неблокирующий, во время ожидания ответа Шлюз продолжает считывать сообщения.
Конфигурация Шлюза#
Для запуска Шлюза в этом режиме необходимо в конфигурационном файле application.yml установить параметры:
mq:
systemName: <имя системы> # аббревиатура внешней системы
systemType: sс # sс - инициатор взаимодействия внешняя система
workMode: sync # режим работы - синхронный
connection:
receiveQueue: [<имя входящей очереди>] # Список очередей, из которых Шлюз читает сообщения
sendQueue: <имя исходящей очереди> # очередь, в которую Шлюз кладет сообщения
connections:
- url: <hostname брокера Artemis> # при подключении без SSL
username: <логин к брокеру Artemis>
password: <пароль к брокеру Artemis>
- url: <hostname брокера Artemis> # при подключении по SSL
sslConfigName: <имя профиля SSL> # имя профиля SSL из секции sslConfigs
sslConfigs:
- sslConfigName: <имя профиля SSL>
verifyHost: false # принудительно отключает проверку CN сертификата брокера на соответствие имени хоста
allowedDNs: # список DN брокеров к которым разрешено подключение
- <DN брокера>
sslCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
sslSocketFactory:
protocol: TLSv1.2
keyPem: <путь к файлу с личным ключом Шлюза>
certPem: <путь к файлу с сертификатом Шлюза>
rootPem: <путь к файлу с сертификатами УЦ>
server:
port: <порт HTTP> # порт HTTP, на котором выставляется эндпойнт actuator/health для liveness и readiness проб
grpc:
server:
serverPort: <порт gRPC> # порт, на котором поднимается gRPC-сервер для приема входящих запросов
client:
settings:
default:
hostname: empty-service
port: <порт> # порт по которому Шлюз будет выполнять исходящие gRPC-вызовы
timeout: <время в мс> # таймаут ожидания ответа для исходящего gRPC-вызова
tracing: # задает заголовки для исходящего gRPC вызова и правила их заполнения
generateXB3Headers: 'true'
generate128bitTraceId: 'true'
tracingHeaders:
x-synapse-rquid: # правило определения заголовка x-synapse-rquid по входящему сообщению
- type: fromBody
value: //RqUID
x-synapse-operationname: # правило определения заголовка x-synapse-rquid по входящему сообщению
- type: fromBody
value: local-name(/*)
routing: # задает правила маршрутизации исходящего gRPC вызова (определение имени сервиса назначения)
routeName: # определение имени маршрута
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
routeList:
- routeName: default # имя маршрута. Правила описанные в default применяются по-умолчанию
destinationExpression: toLower(ServiceName)
variables:
- name: ServiceName
valueFrom:
- type: fromBody,
value: '//ServiceName'
exp: coalesce(value?"<имя вызываемого сервиса по-умолчанию>":value)
Чтение сообщений из MQ#
Шлюз постоянно опрашивает очередь входящих сообщений.
При появлении сообщения в очереди Шлюз считывает сообщение и выполняет вызов синхронного API:
ProtoMessage MessageSyncChannel.ProcessMessages(ProtoMessage)
Имя сервиса назначения определяется по правилам, прописанным в секции routing конфигурации Шлюза.
Обязательные поля ProtoMessage:
Поле |
Тип |
Описание |
|---|---|---|
messageId |
string |
MessageId входящего сообщения |
correlationId |
string |
CorrelationId входящего сообщения |
body |
string |
Информационное сообщение в формате XML |
extension.sourceQueue |
string |
Очередь, из которой было считано входящее сообщение |
Дополнительные поля ProtoMessage
Поле |
Тип |
Описание |
|---|---|---|
systemHeaders |
map<string, string> |
Заполняется при наличии во входящем сообщении свойств с ключами, имеющими префикс JMS |
userHeaders |
map<string, string> |
Заполняется при наличии во входящем сообщении свойств с ключами, не имеющими префикс JMS |
Обязательные заголовки gRPC
Заголовок |
Описание |
|---|---|
x-synapse-rquid |
Уникальный идентификатор сообщения |
x-synapse-operationname |
Имя операции |
x-synapse-from |
Имя внешней системы из конфигурации Шлюза |
x-synapse-from-pod-name |
Имя pod Шлюза, принявшего сообщение |
Отправка ответного сообщения в MQ#
Шлюз ожидает возврата ответного ProtoMessage, получив его, отправляет ответ в MQ
Обязательные поля ответного ProtoMessage:
Поле |
Тип |
Описание |
|---|---|---|
messageId |
string |
MessageId исходного сообщения |
correlationId |
string |
CorrelationId должно содержать MessageId исходного сообщения |
body |
string |
Информационное сообщение (ответ) в формате XML |
Дополнительные поля ответного ProtoMessage
Поле |
Тип |
Описание |
|---|---|---|
extension.expire |
int64 |
Задать при необходимости установить время жизни сообщения в очереди. |
Обязательные заголовки gRPC
Заголовок |
Описание |
|---|---|
x-synapse-rquid |
Уникальный идентификатор сообщения |
x-synapse-operationname |
Имя операции |
x-synapse-from-pod-name |
Имя pod сервиса — инициатора вызова |
Тайм-аут#
Если ответ не будет получен до истечения времени указанного в параметре grpc.client.settings.default.timeout, то Шлюз логирует ошибку и завершает обработку сообщения.
Подключение по SSL#
Для подключения к брокерам Artemis по протоколу SSL должна быть задана конфигурация подключения. Конфигурация задается в секции mq.sslConfigs[] и содержит список профилей с настройками SSL/TLS.
Имя профиля задается в параметре sslConfigName и используется для связывания по одноименному параметру с настройками соединения (mq.connection.connections[].sslConfigName).
Если в профиле не задано имя, то ему присваивается имя default.
Профиль default используется как для соединений, у которых sslConfigName = default, так и для соединений, у которых sslConfigName явно не задано.
mq:
connection:
connections:
- url: <hostname брокера Artemis> # при подключении без SSL
username: <логин к брокеру Artemis>
password: <пароль к брокеру Artemis>
- url: <hostname брокера Artemis> # при подключении по SSL
sslConfigName: <имя профиля SSL> # имя профиля SSL из секции sslConfigs
sslConfigs:
- sslConfigName: <имя профиля SSL>
verifyHost: false # принудительно отключает проверку CN сертификата брокера на соответствие имени хоста
allowedDNs: # список DN брокеров к которым разрешено подключение
- <DN брокера>
sslCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
sslSocketFactory:
protocol: TLSv1.2
keyPem: <путь к файлу с личным ключом Шлюза>
certPem: <путь к файлу с сертификатом Шлюза>
rootPem: <путь к файлу с сертификатами УЦ>
Файлы ключей и сертификатов должны быть загружены в Kubernetes в виде отдельного артефакта Secret и подключены в контейнер Шлюза по путям, указанным в конфигурации SSL.
Мониторинг и очистка очереди ответов#
Возможна ситуация, когда при синхронном вызове в MQ, внешняя система в ответе не проставляет Expiration. Если при этом на ее стороне возникают задержки с ответом, превышающие тайм-аут, установленный в настройках Шлюза, то эти сообщения не вычитываются и начинают накапливаться в очереди ответов.
Для предотвращения накоплений на очередях ответов от синхронных поставщиков необходимо настроить политики очистки очереди.
Политики настраиваются на брокере Artemis в файле broker.xml, для конкретного адреса или шаблона адресов. Если для адреса задан параметр expiry-delay, то всем сообщениям, помещаемым в очередь, у которых expiration = 0 (не задано), будет установлено expiration = timestamp + expiry-delay. Если сообщение, помещаемое в очередь имеет expiration, не равное 0, значение изменено не будет.
<address-setting match="exampleQueue">
<expiry-address>expiryQueue</expiry-address>
<expiry-delay>10</expiry-delay>
</address-setting>
Важно! Для очередей ответов синхронных сервисов необходимо устанавливать значение
expiry-delay> величины таймаута сервиса.
Логирование#
В процессе работы Шлюз фиксирует события в логах.
Системное логирование#
В системном логе фиксируются события, возникающие в приложении в процессе его работы. По умолчанию системный лог выводится в консоль контейнера приложения.
Доступ к системному логу можно получить через Web-интерфейс Kubernetes (Workloads->Pods->Имя pod->вкладка Logs).
Системный лог может быть выгружен через консоль клиента Kubernetes командой:
kubectl logs -c <имя контейнера> <имя pod> > <имя файла>.txt
Также уровень системного логирования можно изменить, задав его в конфигурации Шлюза:
logging:
level: debug
Прикладное логирование#
В прикладном логе фиксируются следующие шаги прохождения интеграционной цепочки:
Шлюз вычитал сообщение JMS/MQ из очереди внешней системы;
Шлюз вызвал микросервис по gRPC и отправил ему сообщение;
Шлюз получил сообщение по gRPC от микросервиса;
Шлюз отправил JMS/MQ сообщение в очередь внешней системы;
Ошибка на Шлюзе.
Для корректного отражения в прикладном логе в Шлюзе должен быть заданы:
Заголовок
x-synapse-rquid. Правило определения значения задается в секции трейсинг;Переменная
ServiceName. Правило определения задается в секции Routing. Значение фиксируется в прикладном логе в полеoperationName. Если переменная не задана, то будет использовано значение имени маршрута (routeName).
Прикладной лог пишется на смонтированный в контейнер приложения ресурс. По умолчанию прикладной лог пишется в файлы:
/opt/synapse/logs/messages*.log
Прикладные логи могут быть извлечены из контейнера приложения и отправлены в подсистему журналирования платформы. Для этого в deployment Шлюза должен быть сконфигурирован sidecar-контейнер с компонентом платформы Synapse — Агентом журналирования.
Порядок подключения и использования Агента журналирования приведены в разделе Подключение и конфигурирование документа Руководство прикладного разработчика на компонент Сервис Журналирование (LOGA) Platform V Monitor.
Интеграционное журналирование (трассировка)#
Интеграционное журналирование выполняется средствами Service Mesh.
Sidecar-контейнер istio-proxy обеспечивает передачу трассировочной информации из транспортных заголовков каждого исходящего gRPC-вызова в систему интеграционного журналирования.
Шлюз заполняет заголовки трассировки в соответствии с заданными настройками.
Правила заполнения заголовков трассировки устанавливаются в секции настроек tracing.
Горизонтальное масштабирование#
Горизонтальное масштабирование Шлюза реализуется и регулируется системными механизмами Kubernetes/Istio. В любой момент при необходимости могут работать одновременно произвольное количество экземпляров Шлюза с общей конфигурацией (произвольное количество pods одного Deployment). Количество запущенных экземпляров определяется настройкой в Deployment и ограничивается только лимитами ресурсов проекта в Kubernetes.
Количество запускаемых экземпляров (pods) Шлюза задается в артефакте Deployment параметром spec.replicas.
Метрики#
Для дополнительного мониторинга параметров Шлюза в нем реализован механизм сбора метрик его работы. Метрики публикуются на HTTP-интерфейсе Шлюза и доступны по URI /actuator/prometheus (метод GET).
Порт, на котором поднимается HTTP-сервис, устанавливается настройкой:
server.port
Получить текущий актуальный список метрик можно, выполнив в терминале контейнера Шлюза команду:
curl localhost:<номер HTTP порта Шлюза>/actuator/prometheus
Мониторинг сертификатов#
Шлюз в процессе работы проверяет срок действия используемых сертификатов SSL и публикует метрику certs, выводящую эту информацию, вид метрики приведен ниже. Значения параметров указаны для примера и в действующей системе будут отличаться.
certs{certLabel="{Alias='gateway', Subject='CN=GATEWAY', Expiration date='01.03.2122', Issuer='CN=SYNAPSEDEV_ROOT_CA'}",} 364.0
certs{certLabel="{Alias='root-ca', Subject='CN=SYNAPSEDEV_ROOT_CA', Expiration date='26.07.3021', Issuer='CN=SYNAPSEDEV_ROOT_CA'}",} 3649.0
Мониторинг используемых ресурсов#
Для расчета производных показателей используются платформенные метрики, публикуемые Kubernetes:
Метрика |
Комментарий |
|---|---|
|
рабочий набор контейнера = RSS+Cache, кеш — уровня ОС и не регулируется приложением |
|
лимит памяти контейнера |
|
RSS контейнера |
Метрики Kubernetes публикуются для всех контейнеров в pod, поэтому при расчете показателей их нужно фильтровать по контейнеру приложения, а не только по pod.
Для мониторинга ресурсов в системе визуализации (Grafana) можно настроить следующие показатели:
Container working set %
=max(container_memory_working_set_bytes{pod="$instance", container=~".*gate.*"})/max(container_spec_memory_limit_bytes{pod="$instance", container=~".*gate.*"})*100
Это процент использования памяти контейнера: то, что отображается в стандартном мониторинге.
Container working set
=max(container_memory_working_set_bytes{pod="$instance", container=~".*gate.*"})
Это рабочий набор контейнера
Container rss %
=max(container_memory_rss{pod="$instance", container=~".*gate.*"})/max(container_spec_memory_limit_bytes{pod="$instance", container=~".*gate.*"})*100
Это % RSS от лимита памяти контейнера
Container rss
=max(container_memory_rss{pod="$instance", container=~".*gate.*"})
Это RSS контейнера
В примерах выше переменные содержащие $app - имя Deployment, а $instance - имя pod Шлюза.
Многоточечное подключение#
При многоточечном подключении один экземпляр Шлюза может быть подключен к нескольким брокерам Artemis. При отправке сообщений в исходящие очереди выполняется балансировка по точкам подключения (hostname:port).
Это внутренняя функция Шлюза, которая никак не связана с настройкой брокеров Artemis.
В Шлюзе реализована периодическая проверка доступности брокеров, если проверка завершается неудачей, брокеры исключаются из балансировки до следующей успешной проверки. Из балансировки также исключаются брокеры отключенные настройкой disabledManagerIds, причем по брокерам отключенным настройкой, проверка доступности не выполняется. Если доступные брокеры отсутствуют, то Шлюз опускает readiness-пробу, и трафик на этот экземпляр (pod) Шлюза блокируется механизмами Kubernetes/Istio.
Если брокер доступен, но при отправке сообщения в MQ возникает ошибка, то Шлюз выполняет попытку отправки через другой брокер из числа доступных. Если сообщение не удается отправить ни через один из брокеров, то Шлюз возвращает ошибку вызывавшему микросервису и опускает readiness-пробу.
Шлюз читает запросы/асинхронные ответы из входящих очередей всех доступных брокеров.
В синхронном режиме работы Шлюз читает ответ из того же брокера, через который был отправлен запрос.
Настройки проверки доступности брокеров устанавливается в секции mq.connection.health конфигурации Шлюза.
В секции mq.connection.health можно задать период опроса, задержку, и, отдельно, количество попыток перед вводом брокера в балансировку, и выводом из балансировки. Подробнее см. раздел «Полное описание настроек».
Для корректной работы механизма проверки, необходимо, чтобы таймаут блокирующих вызовов к брокеру mq.connection.callTimeout имел величину меньшую или равную mq.connection.health.timeoutSeconds.
HTTP-интерфейс#
HTTP-интерфейс в Шлюзе предназначен для организации взаимодействия между внешними АС с разными протоколами взаимодействия — MQ и HTTP.
Использование Шлюза с HTTP-интерфейсом позволяет осуществлять вызов MQ/HTTP с возможностью трансформации транспортных заголовков HTTP→MQ/MQ→HTTP (без преобразования тела сообщения).
Не реализована возможность вызова HTTP→gRPC и gRPC→HTTP.
Определение параметров маршрутизации по телу сообщения работает только с форматами тела сообщения XML и JSON. Возможность работы с другими форматами не поддерживается.
Тип Шлюза: Шлюз потребителя (MQ→HTTP)#
При появлении в очереди запросов входящего сообщения Шлюз считывает сообщение из очереди.
Из полученного сообщения Шлюз извлекает значения параметров, определяющих дальнейшую маршрутизацию вызова. Эти параметры могут содержаться как в заголовках, так и в теле сообщения, либо задаваться константой. Правила определения параметров маршрутизации устанавливаются в секции настроек routing.
Для вызова по HTTP в параметрах маршрута должен быть задан тип транспорта HTTP. Тип транспорта устанавливается настройкой routing.routeList[].transportType.
Шлюз преобразует полученный запрос в httpMessage и вызывает по HTTP-сервис, заданный в параметрах секции HTTP-конфигурации Шлюза, передавая ему сформированное сообщение. Параметры по умолчанию вызываемого сервиса устанавливаются в блоке настроек http.
Параметры вызываемого сервиса для конкретного маршрута устанавливаются в секции настроек routing.routeList[].http.
Важно ! В секцию
httpвходят настройки SSL для HTTP-вызова. Эти настройки должны храниться и монтироваться в артефакте типа secret. В отдельный конфигурационный файл можно вынести только настройки SSL по умолчанию из блокаhttp.
Правила преобразования MQ-заголовков в заголовки HTTP-сообщения устанавливаются в настройке transform.mq-http.headers.
Порядок формирования сообщения подробно описан в разделе Преобразование интерфейсов.
В асинхронном режиме Шлюз, отправив сообщение, завершает вызов.
В синхронном режиме Шлюз ожидает ответ в течение времени тайм-аута, заданного в конфигурации в секции http. Если в течении этого времени ответ не получен, Шлюз прерывает вызов и записывает в журнал тайм-аут. В случае успешного завершения вызова, Шлюз получает ответ от поставщика сервиса. В противном случае в журнал записывается ошибка.
Шлюз преобразует полученное сообщение в MQ-сообщение. Правила преобразования заголовков HTTP-сообщения в заголовки MQ-сообщения устанавливаются в настройке transform.http-mq.
Порядок формирования сообщения подробно описан в разделе Преобразование интерфейсов.
Шлюз отправляет сообщение в очередь, определяемую из настроек Шлюза и информации, содержащейся в ответе.
Если отправка завершилась неудачей, Шлюз записывает ошибку в журнал.
Тип Шлюза: Шлюз поставщика (HTTP→MQ)#
Шлюз при запуске поднимает сервис согласно параметрам, указанным в настройках в секции server конфигурации Шлюза. Параметры HTTP-сервиса устанавливаются в блоке настроек server. Когда сервис получает HTTP-запрос, Шлюз преобразует его в MQ-сообщение. Правила преобразования заголовков HTTP-сообщения в заголовки MQ-сообщения устанавливаются в секции настроек transform.http-mq.
Порядок формирования сообщения подробно описан в разделе Преобразование интерфейсов.
В зависимости от значения параметра sendToCustomDestination в разделе mq конфигурации Шлюза и информации, полученной во входящем сообщении, Шлюз может отправить сообщение:
в очередь, указанную в настройках Шлюза;
в очередь, указанную в блоке Destination Proto-сообщения;
в очередь, указанную в gRPC-заголовках входящего вызова.
В асинхронном режиме Шлюз после отправки сообщения в очередь возвращает HTTP-код 200 (успешное завершение).
Для синхронного ответа АС-поставщик должен установить значение MsgId запроса в CorrelId ответа. Кроме того, ответ должен быть считан тем же экземпляром Шлюза, который отправил запрос.
В синхронном режиме Шлюз отправляет преобразованное сообщение и синхронно ожидает ответ с CorrelId, равным MsgId запроса. Тайм-аут устанавливается настройкой mq.sync-receiver.maxProcessingTime.
АС-поставщик считывает сообщение из очереди запросов, выполняет бизнес-функцию и помещает ответ в очередь ответов по ReplyToQ.
Шлюз считывает ответ и преобразует его в HttpMessage. Правила преобразования MQ-заголовков в заголовки HTTP-сообщения задаются в настройке transform.mq-http.headers.
Порядок формирования сообщения подробно описан в разделе Преобразование интерфейсов.
Шлюз возвращает преобразованное сообщение инициатору запроса.
Работа с кластером Artemis#
Для асинхронных режимов работа в кластере не отличается от работы с множеством брокеров, не связанных в кластер, т. к. в этом случае запросы и ответы балансируются по Pods независимо друг от друга.
Особенности режима синхронного поставщика в кластере Артемис#
Шлюз реализует три варианта работы с кластером Артемис в синхронном режиме:
1. Режим динамического создания очередей для ответов для каждого Pod.
В этом режиме Шлюз при старте каждого Pod создает на общем адресе отдельная очередь с именем Pod (<адрес>::<имя Pod1>, <адрес>::<имя Pod2> и т. д.).
При отправке запроса АС-поставщику конкретный Pod Шлюза в заголовке ReplyToQ передает FQQN "своей" очереди для ответа.
АС поставщик адресует ответ в указанную очередь.
Ответ считывается тем же Pod Шлюза, который отправлял запрос.
В этом варианте Pod Шлюза должен проверять ответы на каждом брокере, к которому он подключен, но поскольку он работает только со своими очередями, чтение по селектору не требуется.
Динамические очереди именуются на основе имени Pod: {ADDRESS}::{PODNAME}, где ADDRESS - имя адреса из настройки mq.sync-receiver.defaultReceiveQueue или из заголовка ReplyToQ, если он есть, PODNAME - имя Pod. В этом режиме заголовок ReplyToQ входящего по gRPC сообщения не должен содержать FQQN очереди. То же касается и параметра mq.sync-receiver.defaultReceiveQueue конфигурации Шлюза.
Для использования этого функционала необходимы следующие настройки в брокере Artemis:
<address-setting match="<адрес>#">
<auto-create-queues>true</auto-create-queues>
<auto-delete-queues>true</auto-delete-queues>
<auto-delete-queues-delay>30000</auto-delete-queues-delay>
<auto-delete-queues-message-count>0</auto-delete-queues-message-count>
</address-setting>
автоматическое создание очередей auto-create-queues - по умолчанию включено, убедиться что не выключено явно;
автоматическое удаление созданных автоматически очередей auto-delete-queues - по умолчанию включено, убедиться что не выключено явно;
таймаут, после которого очередь будет удалена при отсутствии потребителей и сообщений - auto-delete-queues-delay. Рекомендуется ставить достаточный интервал на случай перезапуска Envoy, либо других сайдкаров, во избежание пересоздания одной и той же очереди. Так же на таймаут влияет глобальный параметр брокера address-queue-scan-period интервал сканирования очередей на удаление. Например, при настройке auto-delete-queues-delay=0 и address-queue-scan-period = 30000 пустая очередь может удалиться в промежутке от 0 до 30 секунд.
Количество сообщений в очереди должно быть меньше или равно указанному в auto-delete-queues-message-count чтобы очередь могла быть удалена. Если в настройке задано значение -1, то проверка на наличие сообщений не производится.
Если выставить таймаут на удаление очереди равным общему таймауту на Шлюзе, то в этом случае потерь сообщений не будет (так как оставшиеся в очереди сообщения все равно не будут обработаны из-за истечения таймаута).
Разрешения на работу с такими очередями устанавливаются в настройках безопасности для адреса (можно применять wildcard-синтаксис):
<security-settings> <security-setting match="TEST.QUEUE.RESPONSE"> <!-- Очередь для ответов --> <permission type="createNonDurableQueue" roles="amq, gwsp"/> <permission type="createDurableQueue" roles="amq, gwsp"/> <permission type="consume" roles="amq, gwsp"/> <permission type="browse" roles="amq, gwsp"/> <permission type="send" roles="amq, assp"/> <!-- we need this otherwise ./artemis data imp wouldn't work --> <permission type="manage" roles="amq"/> </security-setting> <security-setting match="TEST.QUEUE.REQUEST"> <!-- Очередь для запросов --> <permission type="consume" roles="amq, assp"/> <permission type="browse" roles="amq, assp"/> <permission type="send" roles="amq, gwsp"/> <!-- we need this otherwise ./artemis data imp wouldn't work --> <permission type="manage" roles="amq"/> </security-setting> </security-settings>В текущем примере gwsp - роль, созданная в брокере для Шлюза, может создавать очереди и читать из них на адресе TEST.QUEUE.RESPONSE, но не может в них писать. Для очередей на адресе TEST.QUEUE.REQUEST наоборот, есть права на запись, но нет на чтение. assp - роль для АС, обладает противоположными правами — только читать из очередей на TEST.QUEUE.REQUEST и только писать в очереди на адресе TEST.QUEUE.RESPONSE. Создавать очереди сама не может.
Шлюз и АС должны подключаться к брокеру под отдельными пользователями, каждому из которых назначена соответствующая роль. Права на удаление и обслуживание очередей таким пользователям не требуются. Созданные ими очереди будут автоматически удалены брокером при выполнении условий для удаления.
2. Режим синхронного чтения ответов из всех подключенных брокеров по корреляционному идентификатору
В этом случае используется схема адресации с одной очередью на адрес. Сценарий:
при отправке запроса АС-поставщику конкретный Pod Шлюза в заголовке ReplyToQ передает имя общей очереди для ответа;
АС поставщик отвечает в эту очередь, не уточняя имя брокера или имя Pod Шлюза;
Конкретный Pod Шлюза читает очереди ответов на всех подключенных брокерах, но считывает только "свои" сообщения, используя селектор по корреляционному идентификатору (CorrelationID).
3. Режим синхронного чтения ответов из всех подключенных брокеров по селектору
Это смешанный режим — вычитка происходит со всех менеджеров по селектору, но селектор не по CorrelId, а по фиксированному, заранее созданному селектору, индивидуальному для каждого Pod (соответствует имени Pod).
В этом случае используется схема адресации с одной очередью на адрес. Сценарий:
при отправке запроса АС-поставщику конкретный Pod Шлюза передаёт:
в заголовке ReplyToQ имя общей очереди для ответа.
в заголовке GWResponseSelector значение для селектора, по которому текущий Pod читает сообщения из очереди для ответа
АС поставщик отвечает в эту очередь, не уточняя имя брокера или имя Pod Шлюза, но обязательно сохраняет и передаёт в сообщении заголовок GWResponseSelector и его значение
Конкретный Pod Шлюза читает очереди ответов на всех подключенных брокерах, но считывает только "свои" сообщения, используя селектор по GWResponseSelector.
В качестве значения селектора используется только имя Pod в заголовке GWResponseSelector
Используемый заголовок можно поменять через настройку
mq.sync-receiver.selectorName.
Выбор режима работы:
Выбор осуществляется настройкой:
mq:
sync-receiver:
replyToMode: UNIQUE #SHARED # SHARED_SINGLE # SHARED_SELECTOR
#selectorName: GWResponseSelector # для режима SHARED_SELECTOR
где UNIQUE - вычитка из динамической очереди (п.1), SHARED и SHARED_SINGLE - вычитка по CorrelId (п.2) из всех или одного менеджера (в который был отправлен запрос), SHARED_SELECTOR - вычитка из всех менеджеров по селектору (п.3)
Для сохранения обратной совместимости по умолчанию используется режим SHARED_SINGLE.
Режим workMode: ALL — совмещенный синхронный и асинхронный режим#
Шлюз может работать в совмещенном (синхронном и асинхронном) режиме. Для этого предусмотрен режим работы ALL.
Для включения режима нужно в конфигурации Шлюза задать настройку:
mq:
workMode = all
Для входящих из MQ сообщений режим обработки определяется входящей очередью:
Входящая очередь |
Режим |
|---|---|
из настройки mq.connection.receiveQueue[] |
async |
из настройки mq.connection.receiveQueueSync[] |
sync |
Для исходящих в MQ сообщений режим обработки определяется API, через который был вызван Шлюз:
АПИ |
Режим |
|---|---|
Асинхронное |
async |
Синхронное |
sync |
Режим systemType: ALL — объединенный режим поставщика и потребителя#
Объединенный режим работы Шлюза устанавливается настройкой mq.systemType: all.
mq:
systemName: <Аббревиатура системы>
systemType: all
workMode: all # если systemType: all, то workMode всегда тоже all
Идентификация режимов при обработке сообщений.
Шлюз в объединенном режиме поднимает два API, синхронный и асинхронный, а также прослушивает заданный в настройках набор очередей.
Для каждой входящей очереди в настройках указывается, в каком режиме обрабатывать пришедшие в нее сообщения.
Вызов синхронного API Шлюза будет обработан в режиме «Синхронный поставщик»;
Для вызовов асинхронного API устанавливается асинхронный режим обработки, но определить, делается запрос в сторону поставщика или ответ в сторону потребителя, невозможно. Это надо учитывать при реализации интеграций через объединенный Шлюз;
Сообщение положенное в очередь, помеченную в настройках Шлюза параметрами workMode: async, systemType: sc будет обработано как асинхронный запрос от потребителя;
Сообщение положенное в очередь, помеченную в настройках Шлюза параметрами workMode: async, systemType: sp будет обработано как асинхронный ответ от поставщика;
Сообщение положенное в очередь, помеченную в настройках Шлюза параметрами workMode: sync, systemType: sc будет обработано как синхронный запрос от потребителя.
Важно! В настройках очередей нельзя указывать workMode: all либо systemType: all. Чтение из таких очередей выполняться не будет.
Настройки очередей:
Входящие очереди для всех используемых режимов должны быть заданы в списке listReceiveQueue (кроме режима синхронного поставщика):
mq:
connection:
listReceiveQueue:
- queue: <очередь1>
workMode: sync
systemType: sc
systemName: <АС1>
- queue: <очередь2>
workMode: async
systemType: sc
systemName: <АС1>
- queue: <очередь3>
workMode: async
systemType: sp
systemName: <АС1>
Исходящие очереди для асинхронных режимов не задаются, отправка производится по customDestination. Для синхронных режимов также используется отправка по customDestination, но можно задать дефолтные очереди в разрезе потребитель/поставщик:
mq:
connection:
defaultSendQueues:
syncProvider:
queue: <очередь синхронного поставщика>
systemName: <АС1>
syncConsumer:
queue: <очередь синхронного потребителя>
systemName: <АС1>
В настройки коррекции заголовков для исходящих сообщений mq.outbound для возможности разделения настроек между режимами добавлен селектор. Между асинхронными Шлюзами async sc и async sp дефолтные настройки разнести невозможно, так как нет параметра во входящем gRPC вызове, по которому можно было бы надежно определить, направлено оно поставщику или потребителю. Для именованных сервисов можно разнести настройки, например, по наличию «rq» или «rs» в корневом теге сообщения
mq:
outbound:
serviceName:
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
serviceList:
- serviceName: default
selector: SYNC_SP # <-----------------Для режима синхронного поставщика. Могут быть (SYNC_SC, SYNC_SP, ASYNC)
В блок routing для исключения случаев пересечения дефолтных схем маршрутизации можно задать селектор, определяющий на какой поток применить схему — синхронный или асинхронный, потребителя или поставщика.
routing:
routeName:
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
routeList:
- routeName: default
selector: ASYNC_SC # <-----------------Для режима асинхронного потребителя. Могут быть (SYNC, ASYNC_SP, ASYNC_SC)
. . .
- routeName: default
selector: ASYNC_SP # <-----------------Для режима асинхронного поставщика. Могут быть (SYNC, ASYNC_SP, ASYNC_SC)
. . .
В блоке tracing можно задавать списки настроек в разрезе режимов. Добавлен селектор для разделения списков настроек.
#признак генерации заголовков трассировки x-b3-*
tracing:
generateXB3Headers: true
generate128bitTraceId: true
listTracingHeaders:
- selector: ASYNC_SC # <-----------------Для режима асинхронного потребителя. Могут быть (SYNC, ASYNC_SP, ASYNC_SC)
tracingHeaders:
x-synapse-rquid:
- type: fromBody
value: //*[local-name()='RqUID']
Валидация сообщений на Шлюзе#
Валидация сообщений на Шлюзе выполняется внешним компонентом (Валидатор запросов IGEG (REQV)).
Возможна валидация как входящих (из MQ), так и исходящих (в MQ) сообщений в форматах XML и JSON.
Для синхронных вызовов можно настроить отправку информационных ответов об ошибках валидации, если форматы (схемы) ответных сообщений это позволяют.
Получив сообщение по одному из своих основных интерфейсов, Шлюз в соответствии со своими настройками вызывает по HTTP-контейнер с валидатором и отправляет тело сообщения на валидацию. Валидатор по своим настройкам определяет нужную схему сообщения и проводит валидацию, после чего возвращает Шлюзу результат. В случае положительного результата валидации Шлюз отправляет сообщение дальше в точку назначения. В случае отрицательного результата валидации Шлюз фиксирует ошибку, сообщение дальше не отправляется.
Если сообщение пришло в синхронном вызове и в настройках валидатора для этого сообщения задан шаблон ответа об ошибке, то, в случае отрицательного результата валидации, валидатор формирует и передает Шлюзу ответ об ошибке, а Шлюз возвращает его инициатору.
Чтобы Валидатор мог определить схему сообщения для валидации, ему в заголовках HTTP-вызова должны быть переданы два параметра: metod и path. Значение заголовка path на Шлюзе определяется динамически, на основании параметров сообщения, по правилам заданным в настройках Шлюза. Соответствие значений path схемам сообщений задается в конфигурации валидатора.
Важно!
При работе валидатора совместно со Шлюзом:
Заголовок
metodвсегда имеет значение POST.Валидатор, при ошибке валидации должен всегда возвращать код 403 (используется по-умолчанию).
Возвращаемые валидатором заголовки
error-headersШлюзом не обрабатываются.Шлюз при вызове валидатора самостоятельно заполняет заголовок
x-request-idзначением RqUID определенным для целей логирования.
Подключение валидатора#
Для подключения валидатора необходимо в Deployment Шлюза добавить контейнер валидатора, а также тома с его конфигурацией (артефакт ConfigMap или Secret содержащий файл appl.yml) и схемами сообщений (артефакт ConfigMap или Secret содержащий схемы сообщений) и их точки монтирования.
Пример подключения валидатора в Deployment Шлюза:
Deployment: spec.template.spec.containers
containers
- name: validator
resources:
limits:
cpu: 200m
memory: 160Mi
requests:
cpu: 100m
memory: 150Mi
terminationMessagePath: /dev/termination-log
env:
- name: PROJECT_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
ports:
- containerPort: 50051
protocol: TCP
imagePullPolicy: IfNotPresent
volumeMounts:
- name: validator-schemas
readOnly: true
mountPath: /schemas
- name: validator-config
mountPath: /config
- name: synapselogs
mountPath: /opt/synapse/logs
terminationMessagePolicy: File
image: >-
registry.example.com/ci01994970/ci03302438_synapse-igeg/rhel7-java-synapse-sidecar-validator-ci03302438:0.1.0.26
Deployment: spec.template.spec
volumes:
- name: validator-config
configMap:
name: validator-config
defaultMode: 416
- name: validator-schemas
configMap:
name: validator-schemas
defaultMode: 416
В настройках Валидатора нужно задать порт, на котором Валидатор будет принимать запросы. Порт валидатора по номеру не должен совпадать с портом, который использует Шлюз. Также в настройках задается соответствие параметров вызова валидатора конкретной схеме валидации.
Пример настройки Валидатора: validator-config
app.yaml: |
port: 8787
log_level: info
schemas:
- name: 'foo'
method: POST
path: '/ping'
schema: /schemas/foo.json
type: 'json'
error_response: '{"error-message":{"x-request-id": "{{get .Header "x-request-id"}}", "error": "{{get .Error "error_message"}}"}}'
error_headers:
- key: content-type
value: application/json
- key: foo
value: '{{get .Header "foo"}}'
headers:
- key: x-foo-first
value: foo1
error_code: 200
- name: bar
method: POST
path: '/'
schema: /schemas/bar.xsd
type: 'xml'
error_code: 403
error_response: '<error_rs>{{get .Error "error_message"}}</error_rs>'
Дополнительно к валидатору в точку монтирования /schemas должен быть смонтирован артефакт типа ConfigMap или Secret, содержащий схемы для валидации сообщений.
Пример артефакта со схемами: validator-schemas
bar.xsd: |
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element name="RqUID" type="xs:string"/>
<xs:element name="street" type="xs:string"/>
<xs:element name="street-number" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="zip" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
barn.xsd: |
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element name="RqUID" type="xs:string"/>
<xs:element name="street" type="xs:string"/>
<xs:element name="street-number" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="zip" type="xs:string"/>
<xs:element name="country-n" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
foo.json: |
{
"$id": "http://json-schema.org/draft/2019-09/json-schema-core.html",
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$comment": "sample comment",
"title": "Config dump",
"type": "object",
"properties": {
"configs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"last_updated": {
"type": "string"
},
"bootstrap": {
"type": "object",
"properties": {
"admin": {
"type": "object"
},
"dynamic_resources": {
"type": "object"
},
"node": {
"type": "object"
},
"static_resources": {
"type": "object"
},
"stats_config": {
"type": "object"
}
},
"required": ["admin", "dynamic_resources", "node", "static_resources", "stats_config"]
}
},
"required": ["@type", "last_updated", "bootstrap"]
}
}
},
"required": [
"configs"
]
}
Более подробная информация содержится в разделе Использование программного продукта документа Руководство прикладного разработчика на компонент Валидатор запросов (REQV) Platform V Synapse Service Mesh.
Настройка Шлюза для выполнения валидации#
Включить валидацию#
Добавить в конфигурацию Шлюза блок параметров верхнего уровня validator. Параметры могут быть добавлены в существующий файл конфигурации application.yml, но, учитывая их критичность, можно выделить их в отдельный файл validator-secret.yml, и поместить его в артефакт типа Secret.
Отдельный артефакт необходимо подключить к контейнеру Шлюза в Deployment: Пример подключения секрета с настройками валидации
volumes:
- name: test-gw-validator
secret:
secretName: test-gw-validator
defaultMode: 288
. . .
containers
- name: test-gw
volumeMounts:
- name: test-gw-validator
mountPath: /deployments/config/validator
Установить настройку validator.enabled в true.
Установить параметры вызова валидатора#
Установить настройки validator.http.client.url и validator.http.client.timeout
URL нужно задать в формате http://localhost/:<port>/check, где port соответствует номеру порта заданному в настройках валидатора.
Установить правила выбора профиля настроек#
Заполнить секцию validator.serviceName. Секция задает правило выбора профиля настроек валидации по параметрам сообщения. Принцип заполнения такой же, как для секции routing, но дефолтный профиль не предусмотрен.
Обычно (но не обязательно) профиль соответствует наименованию сервиса и может быть получен, например, из пользовательского заголовка ServiceName (если он используется) либо из тега ServiceName в теле сообщения.
Пример заполнения секции validator.serviceName
serviceName: # правила определения схем для сообщений
valueFrom:
- type: fromRfh2Header
value: ServiceName
- type: fromBody
value: //ServiceName
valueJson: $..ServiceName
expr:
Установить правила выбора пути для поиска схемы#
Заполнить секцию validator.serviceList. Секция задает список профилей, и для каждого профиля — правила вычисления значения заголовка path для вызова валидатора. Принцип заполнения такой же, как для секции routing. Значение pathопределяется как результат вычисления выражения заданного в pathExpression над списком переменных. Значения переменных определяются из параметров конкретного сообщения по заданным в профиле правилам.
В большинстве случаев (но не всегда) достаточно привязать path к корневому тегу сообщения:
Пример заполнения секции serviceList
serviceList:
- serviceName: testServiceName
pathExpression: ServiceNameRootTag
variables:
- name: ServiceNameRootTag
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
предопределенные переменные#
Для более точной идентификации схемы можно использовать встроенные переменные, которые Шлюз заполняет самостоятельно.
direction - направление движения сообщения, варианты:
outbound - в MQ
inbound - из MQ
workMode - режим вызова, варианты:
sync - сообщение получено в синхронном вызове
async - сообщение получено в асинхронном вызове
msgType - тип сообщения (определяется только для синхронных вызовов), варианты:
rq - синхронный запрос
rs - ответ на синхронный запрос
"_" - сообщение в асинхронном вызове
Пример использования предопределенных переменных
serviceList:
- serviceName: testServiceName
pathExpression: ("/"+variables['direction']+"/"+variables['workMode']+"/"+variables['msgType']+"/"+ServiceNameRootTag)
variables:
- name: ServiceNameRootTag
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
Заголовки#
В вызов валидатора могут быть добавлены дополнительные заголовки. Они используются для уточненного поиска схемы, а также для параметризации ответа об ошибке валидации (подробности см. в документации на Валидатор запросов (REQV) Platform V Synapse Service Mesh).
Для добавления заголовка в вызов нужно для конкретного профиля настроек заполнить параметр headers:
Пример настройки заполнения заголовков
serviceList:
- serviceName: testServiceName
headers: # Заполняется, если требуется передать дополнительные заголовки для вставки в ответ.
RqUID:
- type: fromBody
value: //RqUID
# Matching values
valueJson: $..RQID
pathExpression: ("/"+variables['direction']+"/"+variables['workMode']+"/"+variables['msgType']+"/"+ServiceNameRootTag)
variables:
- name: ServiceNameRootTag
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
Выполнение валидации на Шлюзе#
Если на Шлюзе включена валидация, то к каждому проходящему через Шлюз сообщению применяются правила определения профиля валидации.
Если профиль найден, то вычисляется параметр path по правилам, заданным в профиле настроек, и тело сообщения отправляется на валидацию.
Если профиль для сообщения не задан, то по умолчанию сообщение будет признано валидным и отправлено дальше по маршруту. Это поведение можно изменить установкой параметра настройки invalidateByDefault в true.
При положительном результате валидации сообщение будет оправлено дальше по маршруту.
При отрицательном результате валидации будет вызвано исключение. Если вызов был синхронным и валидатор вернул информационный ответ об ошибке, этот ответ будет возвращен инициатору. В остальных случаях:
для входящего сообщения из MQ обработка прекращается;
для входящих по gRPC/HTTP — возвращается исключение и статус/код завершения соответственно.
Возврат ответа#
Если Шлюз при обработке синхронного вызова получил от валидатора ошибку валидации с информационным ответом, то:
Для синхронного запроса из MQ ответ отправляется в очередь и менеджер указанные в заголовках
MQMD.ReplyToQиMQMD.ReplyToQMgrвходящего запроса. По умолчанию заголовокMQMD.CorrelIdответа заполняется значением заголовкаMQMD.MsgIdзапроса (стандартное поведение, может быть изменено установкой параметраreplyByCorrelIdвtrue);Для ответа на синхронный запрос из MQ тело ответа заменяется полученным от валидатора сообщением, заголовки не модифицируются;
Для вызовов по gRPC/HTTP ответ возвращается в вызове.
Вызов завершается штатно, исключение не вызывается.
Логирование и мониторинг#
Шлюз фиксирует в прикладном логе заголовок PATH и результат вызова валидатора. Тело сообщения по умолчанию не логируется (поведение можно изменить установкой параметра настройки loggingBody в true).
Шлюз отображает в метрике errors_gateways количество ошибок валидации и количество ошибок вызова валидатора раздельно по кодам 604 и 605 соответственно.
Ошибки валидации на Шлюзе:
ошибка |
Описание |
код |
HTTP статус |
gRPC статус |
|---|---|---|---|---|
ошибка валидации сообщения |
Сюда относятся только ошибки несоответствия сообщения его схеме, в случаях, когда информационный ответ об ошибке инициатору не возвращается |
604 |
403 Forbidden |
aborted |
ошибка вызова валидатора (синхронные запросы и асинхронные вызовы) |
Сюда относятся все ошибки вызова валидатора, при которых результат проверки остается неизвестным (транспортные ошибки включая тайм-ауты, внутренние ошибки валидатора) |
605 |
502 Bad gateway Есть возможность повтора вызова через другой экземпляр Шлюза (если настроены повторы) |
unavailable Есть возможность повтора вызова через другой экземпляр Шлюза (если настроены повторы) |
ошибки вызова валидатора (ответы на синхронные запросы) |
Сюда относятся все ошибки вызова валидатора, при которых результат проверки остается неизвестным (транспортные ошибки включая таймауты, внутренние ошибки валидатора) |
605 |
400 Bad request Не выполняется повтор вызова, чтобы избежать дублирования запроса |
internal Не выполняется повтор вызова, чтобы избежать дублирования запроса |
Хранение секретов во внешнем хранилище#
При использовании внешнего хранилища (ВХС) для хранения секретов с конфиденциальными данными требуется синхронизация запуска приложения Шлюза и момента готовности файлов секретов к чтению со стороны приложения, так как подготовка и монтирование секретов начинается уже после запуска pod.
Для этого в Шлюзе реализован механизм ожидания готовности файлов конфигурации перед запуском приложения.
Для настройки механизма нужно добавить в проект configMap со списком секретов, которые нужно ждать.
kind: ConfigMap
apiVersion: v1
metadata:
name: gateway-all-sp-secman
data:
secman.txt: |-
/mnt/secrets/cert.pem #путь к файлу личного сертификата для SSL-подключения.
/mnt/secrets/key.pem #путь к файлу личного ключа для SSL-подключения.
/mnt/secrets/root.pem #путь к файлу доверенных сертификатов для SSL-подключения.
# далее - стандартные пути секретов конфигураций, неизменяемые
/deployments/config/masking/masking-secret.yml
/deployments/config/validator/validator-secret.yml
и смонтировать в контейнер с приложением по пути /tmp/secman/config.
spec:
volumes:
# подключение файла со списком путей к файлам, создание которых ожидается
- name: secman-config
configMap:
name: gateway-all-sp-secman
items:
- key: secman.txt
path: secman.txt
defaultMode: 256
containers:
volumeMounts:
- name: secman-config
readOnly: true
mountPath: /tmp/secman/config
Путь /tmp/secman/config, по которому должен быть смонтирован файл с конфигурацией, зафиксирован в образе Шлюза и не может быть изменен.
Добавить SE для ВХС. Также необходимо исправить параметр host в SE, в зависимости от стенда согласно таблице в инструкции
SE-secman.yaml
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: se-secman
spec:
exportTo:
- .
hosts:
- t.secrets.domainname.ru
location: MESH_EXTERNAL
ports:
- name: https-443
number: 443
protocol: HTTPS
resolution: DNS
В deployment Шлюза добавляются аннотации и метки, обеспечивающие подключение vault-агента и монтирование секретов из него. Пример файла с необходимыми аннотациями и монтированиями:
Пример deployment
kind: Deployment
apiVersion: apps/v1
spec:
template:
metadata:
labels:
secman-injector: enabled #обеспечивает подключение vault-агента к подам
annotations:
# базовые аннотации
sidecar.istio.io/inject: 'true' #подключение Sidecar istio
vault.hashicorp.com/agent-init-first: "false" # ОТКЛЮЧИТЬ (смонтировать секреты до запуска основного контейнера)
vault.hashicorp.com/agent-inject: "true" # обеспечивает инъекцию init-контейнера и Sidecar Vault-Agent в поды Шлюза MQ
vault.hashicorp.com/namespace: CIxxxxxxxx_CIxxxxxxxx #имя пространства в хранилище секретов формата CIxxxxxxxx_CIxxxxxxxx
vault.hashicorp.com/agent-pre-populate: "false" #ОТКЛЮЧИТЬ (обеспечить наличие секретов до запуска основного контейнера_
vault.hashicorp.com/role: ciNNNNNNNN_xxx # роль в SecMan, получаемая при подключении к хранилищу (по тикету в Jira)
vault.hashicorp.com/agent-volumes-default-mode: "0400" # задание прав на созданные файлы с секретами в примонтированном EmptyDir
vault.hashicorp.com/agent-inject-perms-<имя ресурса>: 0400 # задает права на примонтированный ресурс <имя ресурса>
vault.hashicorp.com/agent-inject-containers: <имя контейнера приложения Шлюза> # ограничивает монтирование ресурсов только контейнером (контейнерами) из списка.
vault.hashicorp.com/agent-run-as-same-user: "true" # запуск контейнера Vault-агента от имени того же пользователя, что и приложение в containers[0]
# подключение секрета настроек маскирования сообщений
vault.hashicorp.com/secret-volume-path-masking-secret.yml: /deployments/config/masking # путь монтирования файла конфигурации маскирования из секрета
vault.hashicorp.com/agent-inject-secret-masking-secret.yml: 'true' # признак монтирования секрета -vault.hashicorp.com/agent-inject-secret - статичная часть, masking-secret.yml - имя секрета
vault.hashicorp.com/agent-inject-file-masking-secret.yml: masking-secret.yml # имя файла конфигурации маскирования из секрета, будет создан по пути выше
vault.hashicorp.com/agent-inject-template-masking-secret.yml: | # шаблон извлечения секрета конфигурации маскирования
{{- with secret "CIxxxxxxxx_CIxxxxxxxx/x/xxxx/xxx/x/KV/secret_name" -}} #полный путь к секрету в хранилище
{{ .Data.masking }} #имя свойства секрета, в котором хранится значение секрета
{{- end -}}
# подключение секрета настроек валидатора
vault.hashicorp.com/secret-volume-path-validator-secret.yml: /deployments/config/validator # путь монтирования файла конфигурации валидатора из секрета
vault.hashicorp.com/agent-inject-secret-validator-secret.yml: 'true' # признак монтирования секрета -vault.hashicorp.com/agent-inject-secret - статичная часть, masking-secret.yml - имя секрета
vault.hashicorp.com/agent-inject-file-validator-secret.yml: validator-secret.yml # имя файла конфигурации валидатора из секрета, будет создан по пути выше
vault.hashicorp.com/agent-inject-template-validator-secret.yml: | # шаблон извлечения секрета конфигурации валидатора
{{- with secret "CIxxxxxxxx_CIxxxxxxxx/x/xxxx/xxx/x/KV/secret_name" -}}
{{ .Data.validator }}
{{- end -}}
# подключение секрета файла доверенных сертификатов для ssl-соединения
vault.hashicorp.com/secret-volume-path-root.pem: /mnt/secrets # путь монтирования файла из секрета
vault.hashicorp.com/agent-inject-secret-root.pem: 'true' # признак монтирования секрета -vault.hashicorp.com/agent-inject-secret - статичная часть, root.pem - имя секрета
vault.hashicorp.com/agent-inject-file-root.pem: root.pem # имя файла из секрета, будет создан по пути выше
vault.hashicorp.com/agent-inject-template-root.pem: | # шаблон извлечения секрета с декодированием из Base64
{{- with secret "CIxxxxxxxx_CIxxxxxxxx/x/xxxx/xxx/x/KV/secret_name" -}}
{{ base64Decode .Data.rootPem }} #декодирование Base64 значения секрета
{{- end -}}
# подключение секрета файла личного сертификата для ssl-соединения
vault.hashicorp.com/secret-volume-path-cert.pem: /mnt/secrets # путь монтирования файла из секрета
vault.hashicorp.com/agent-inject-secret-cert.pem: 'true' # признак монтирования секрета -vault.hashicorp.com/agent-inject-secret - статичная часть, cert.pem - имя секрета
vault.hashicorp.com/agent-inject-file-cert.pem: cert.pem # имя файла из секрета, будет создан по пути выше
vault.hashicorp.com/agent-inject-template-cert.pem: | # шаблон извлечения секрета с декодированием из Base64
{{- with secret "CIxxxxxxxx_CIxxxxxxxx/x/xxxx/xxx/x/KV/secret_name" -}}
{{ base64Decode .Data.certPem }} #декодирование Base64 значения секрета
{{- end -}}
# подключение секрета файла личного ключа для ssl-соединения
vault.hashicorp.com/secret-volume-path-key.pem: /mnt/secrets # путь монтирования файла из секрета
vault.hashicorp.com/agent-inject-secret-key.pem: 'true' # признак монтирования секрета -vault.hashicorp.com/agent-inject-secret - статичная часть, key.pem - имя секрета
vault.hashicorp.com/agent-inject-file-key.pem: key.pem # имя файла из секрета, будет создан по пути выше
vault.hashicorp.com/agent-inject-template-key.pem: | # шаблон извлечения секрета с декодированием из Base64
{{- with secret "CIxxxxxxxx_CIxxxxxxxx/x/xxxx/xxx/x/KV/secret_name" -}}
{{ base64Decode .Data.keyPem }} #декодирование Base64 значения секрета
{{- end -}}
Важно! Аннотация vault.hashicorp.com/agent-run-as-same-user: "true" требуется для корректного назначения прав на смонтированные Vault-агентом ресурсы.
После старта pod в логах образа Шлюза можно наблюдать счётчик времени ожидания, там же видно какие файлы ожидаются и какие из них найдены.
В Deployment Шлюза, должен быть задан минимальный уровень полномочий на монтируемые ресурсы.
Динамическая загрузка TLS сертификатов#
При изменении файлов секретов с хранилищами ключей внешней системой хранения сертификатов, Шлюз должен перечитать новые значения и использовать их для создания подключений.
Последовательность действий при обновлении сертификатов:
Шлюз мониторит изменения (обновление, удаление, создание) файлов ключей и сертификатов (расположение файлов указывается в конфигурации).
При наступлении события изменения файлов, Шлюз:
выдерживает паузу определяемую алгоритмом временного смещения для снижения коллизий (перекрытия по времени недоступности двух или более pods общего Deployment (см. ниже мониторинг каскадных перезапусков));
останавливает обработку сообщений;
останавливает все коннекты к брокерам MQ;
перечитывает файлы ключей и сертификатов;
восстанавливает коннекты с использованием новых ключей и сертификатов;
возобновляет обработку сообщений.
Сообщения принятые по каналам HTTP и gRPC во время обновления сертификатов (с момента остановки обработки до ее возобновления) накапливаются в пуле потоков обработки, и обрабатываются после восстановления коннектов.
Если пул потоков обработки исчерпан, а процедура обновления еще не завершена, новые входящие вызовы по каналам HTTP и gRPC будут отклоняться шлюзом, и средствами istio будет выполняться повтор вызова на другие pod-ы шлюза.
Предусмотрена настройка, позволяющая задать состояние Readiness пробы на время проведения процедуры обновления. По умолчанию Readiness - проба не опускается. Снятие Readiness-пробы выводит шлюз из балансировки на время приостановки обработки. Это позволяет предотвратить повторы вызовов на уровне сервис меша и связанное с этим увеличение латентности в прикладных интеграциях.
Чтобы исключить существенное негативное влияние на поток, предусмотрен механизм, снижающий вероятность одновременного обновления ключей на нескольких экземплярах одного deployment приложения.
С этой целью Шлюз сдвигает начало применения новых сертификатов от момента изменения файлов хранилищ. Время сдвига определяется для каждого экземпляра независимо, по вероятностному алгоритму, который позволяет минимизировать количество коллизий перезапуска коннектов, но не исключает их полностью.
Описание алгоритма#
Алгоритм использует хэш от имени пода, распределенный по заданному количеству сегментов, для получения временного смещения начала перезапуска коннектов, относительно момента изменения файлов ключей и сертификатов.
Временное смещение определяется исходя из номера сегмента для конкретного пода и размера интервала обновления.
Интервал обновления — это время необходимое одному поду шлюза, для выполнения процедуры применения сертификатов
Произведение интервала обновления и количества сегментов дает общее время выполнения процедуры обновления сертификатов на deployment шлюза.
При уменьшении фактора репликации вероятность коллизий будет снижаться, при этом величина коллизий (количество подов одновременно начавших процедуру применения сертификатов) и общее время выполнения процедуры на deployment сохраняются.
Шлюз вносит дополнительную фиксированную временную задержку, задаваемую параметром mq.sslCertUpdate.certificateReloadDelay для того, чтобы при несинхронном изменении файлов ключей и сертификатов со стороны внешней системы хранения сертификатов исключить излишние повторы процедуры обновления.
Конфигурирование#
Для настройки алгоритма используются следующие параметры (mq.sslCertUpdate):
enable - включение(true)/выключение(false) механизма обновления сертификатов. Если установлено значение false, контроль за изменением файлов хранилища сертификатов отключается.
checkInterval - устанавливает периодичность проверки изменения файлов хранилища сертификатов.
downReadinessProbe - задает нужно (true), или не нужно (false) опускать Readiness-пробу на время выполнения обновления сертификатов. Если значение true, то Readiness-проба на каждом конкретном экземпляре шлюза будет переводиться в состояние down с момента остановки обработки сообщений до момента ее возобновления этим конкретным экземпляром.
intervalsNumber - количество интервалов (сегментов распределения). С его уменьшением вероятность коллизий будет увеличиваться. Можно уменьшить, если у deployment малый фактор репликации (количество запущенных подов < 5), чтобы уменьшить обще время выполнения процедуры замены сертификатов.
updateTimeInSeconds - Интервал обновления — время применения сертификатов для одного пода Шлюза. Нужно увеличивать, если у шлюза задано большое количество коннектов (очередей и брокеров), так как в этом случае отключение и подключение всех коннектов потребует больше времени. Пропорционально увеличивает общее время выполнения для deployment.
roundTimeInMinutes - интервал на который округляется (в большую сторону) момент изменения файлов хранилищ ключей. Это позволяет нивелировать временную разницу распространения обновленных файлов по нодам, и обеспечить независимые поды общей точкой отсчета для начала процедуры. Нужно увеличивать, если в проекте наблюдается значительный разброс времени распространения файлов по нодам. Приводит к сдвигу общего времени выполнения процедуры для deployment на величину roundTimeInMinutes.
certificateReloadDelay - Дополнительная фиксированная временная задержка, для того, чтобы при несинхронном изменении файлов ключей и сертификатов со стороны внешней системы хранения сертификатов исключить излишние повторы процедуры обновления.
Пример настройки (приведены значения по умолчанию):
mq:
sslCertUpdate:
enable: false
checkInterval: 30000ms
downReadinessProbe: false
intervalsNumber: 20
updateTimeInSeconds: 2
roundTimeInMinutes: 10
certificateReloadDelay: 30s
Обработка внештатных ситуаций#
В процессе обновления сертификатов возможно возникновение исключительных ситуаций:
Файл хранилища был удален, но новый файл не был доставлен. В действующей реализации попытка прочитать реквизиты удаленного файла завершиться неудачей, шлюз продолжит работу со старыми сертификатами, и продолжит попытки проверить реквизиты файла. Когда будет смонтирован файл хранилища, то шлюз выполнит проверку реквизитов, и в случае их изменения обновит сертификаты.
Новый файл хранилища поврежден (файл есть, но "битый"). При попытке загрузить новые сертификаты возникнет ошибка инициализации библиотек криптографии. Будет снята Readiness - проба, шлюз будет пытаться инициализировать библиотеку. После устранения ошибки будут загружены сертификаты, и восстановлена Readiness-проба.
Сертификаты в новом файле хранилища не валидные. После обновления сертификатов возникнет ошибка установки соединения с менеджерами MQ. Readiness-проба будет снята. Шлюз будет пытаться установить соединение с менеджерами. После устранения ошибки подключения будут восстановлены, и Readiness-проба поднята.
Настройка регистрации событий аудита#
Шлюз позволяет фиксировать события аудита в локальном буфере аудита.
Перечень фиксируемых событий Аудита, которые возникают в процессе функционирования Шлюза:
Код |
Событие |
Комментарий |
|---|---|---|
MQ_success |
Успешное подключение к брокеру MQ |
Фиксируется при каждом успешном подключении Шлюза к брокеру MQ. Для многоточечного подключения (один Шлюз к нескольким брокерам) фиксируется отдельное событие подключения к каждому брокеру MQ. |
MQ_error |
Ошибка подключения к брокеру MQ |
Фиксируется при ошибке подключения Шлюза к брокеру MQ. Для многоточечного подключения события фиксируются для каждого подключенного брокера отдельно. |
Параметры события#
Общие:
Код |
Параметр |
Комментарий |
|---|---|---|
Время события |
Время фиксируется по моменту возникновения события в конкретном экземпляре шлюза |
|
Проект |
Наименование проекта в Kubernetes с запущенным Pod шлюза, на котором произошло событие |
|
Источник события |
Имя Pod шлюза, на котором произошло событие |
|
Имя Node |
Имя Node, на которой запущен Pod шлюза |
|
IP адрес Node |
IP Node, на которой запущен Pod шлюза |
|
Имя менеджера |
не используется |
|
Канал |
не используется |
|
Имя хоста |
Имя хоста брокера, к которому выполнялось подключение |
|
Номер порта |
номер порта брокера, по которому выполнялось подключение |
|
Схема шифрования |
Схема шифрования указанная в настройках Pod шлюза |
|
DN шлюза |
DN сертификата шлюза из настроек |
|
DN менеджера MQ |
DN брокеров MQ из настройки allowedDNs конфигурации шлюза. |
|
Описание ошибки |
Для успешного подключения: пусто; |
Чтобы отправить событие аудита в ТС Аудит (AUDT) Platform V Audit SE, в нем предварительно должна быть зарегистрирована метамодель события.
Шлюз формирует метамодель в формате JSON:
{
"metamodelVersion": "1",
"module": "mq-gateway",
"events": [
{
"name": "MQ_success",
"description": "Успешное подключение к менеджеру MQ",
"success": "true",
"mode": "reliability",
"params": [
{
"name": "time",
"description": "Время события (timestamp)"
},
{
"name": "os_project",
"description": "Проект OpenShift"
},
{
"name": "event_source",
"description": "Имя Pod источника события"
},
{
"name": "node_name",
"description": "Имя Node для Pod источника события"
},
{
"name": "node_ip",
"description": "IP Node для Pod источника события"
},
{
"name": "mqm_name",
"description": "Имя менеджера к которому выполнялось подключение"
},
{
"name": "mqm_channel",
"description": "Имя канала по которому выполнялось подключение"
},
{
"name": "mqm_host",
"description": "Имя хоста менеджера к которому выполнялось подключение"
},
{
"name": "mqm_port",
"description": "Номер порта менеджера к которому выполнялось подключение"
},
{
"name": "cipher",
"description": "Используемая схема шифрования"
},
{
"name": "dn_mqgateway",
"description": "DN сертификата шлюза из настроек"
},
{
"name": "dn_mqm",
"description": "Ожидаемый DN менеджера MQ из настроек"
},
{
"name": "error_desc",
"description": "Описание ошибки"
}
]
},
{
"name": "MQ_error",
"description": "Ошибка подключения к менеджеру MQ",
"success": "false",
"mode": "reliability",
"params": [
{
"name": "time",
"description": "Время события (timestamp)"
},
{
"name": "os_project",
"description": "Проект OpenShift"
},
{
"name": "event_source",
"description": "Имя Pod источника события"
},
{
"name": "node_name",
"description": "Имя Node для Pod источника события"
},
{
"name": "node_ip",
"description": "IP Node для Pod источника события"
},
{
"name": "mqm_name",
"description": "Имя менеджера к которому выполнялось подключение"
},
{
"name": "mqm_channel",
"description": "Имя канала по которому выполнялось подключение"
},
{
"name": "mqm_host",
"description": "Имя хоста менеджера к которому выполнялось подключение"
},
{
"name": "mqm_port",
"description": "Номер порта менеджера к которому выполнялось подключение"
},
{
"name": "cipher",
"description": "Используемая схема шифрования"
},
{
"name": "dn_mqgateway",
"description": "DN сертификата шлюза из настроек"
},
{
"name": "dn_mqm",
"description": "Ожидаемый DN менеджера MQ из настроек"
},
{
"name": "error_desc",
"description": "Описание ошибки"
}
]
}
]
}
Метамодель отправляется один раз при старте приложения.
Примеры событий в JSON - формате:
Успешное
{
"module": "mq-gateway",
"metamodelVersion": "1",
"name": "MQ_success",
"userNode": "NO-USERNODE",
"userLogin": "NO-USER",
"createdAt": "1234567890000",
"session": "NO-SESSION",
"userName": "",
"tags": [
"<project_name>",
"<deployment_name>"
],
"params": [
{
"name": "time",
"value": "1234567890"
},
{
"name": "os_project",
"value": "ci01994970-idevgen2-synapse-esbub-dev"
},
{
"name": "event_source",
"value": "test-gw-56558d77b6-hcl9v"
},
{
"name": "node_name",
"value": "nodename.domainname.ru"
},
{
"name": "node_ip",
"value": "10.125.82.208"
},
{
"name": "mqm_name",
"value": "не используется"
},
{
"name": "mqm_channel",
"value": "не используется"
},
{
"name": "mqm_host",
"value": "amqps://hostname.domainname.ru"
},
{
"name": "mqm_port",
"value": "61617"
},
{
"name": "cipher",
"value": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
},
{
"name": "dn_mqgateway",
"value": "CN=TEST-GW"
},
{
"name": "dn_mqm",
"value": "CN=SYNAPSE"
},
{
"name": "error_desc",
"value": ""
}
]
}
Ошибка
{
"module": "mq-gateway",
"metamodelVersion": "1",
"name": "MQ_error",
"userNode": "NO-USERNODE",
"userLogin": "NO-USER",
"createdAt": "1234567890000",
"session": "NO-SESSION",
"userName": "",
"tags": [
"<project_name>",
"<deployment_name>"
],
"params": [
{
"name": "time",
"value": "1234567890"
},
{
"name": "os_project",
"value": "ci01994970-idevgen2-synapse-esbub-dev"
},
{
"name": "event_source",
"value": "test-gw-56558d77b6-hcl9v"
},
{
"name": "node_name",
"value": "nodename.domainname.ru"
},
{
"name": "node_ip",
"value": "10.125.82.208"
},
{
"name": "mqm_name",
"value": "не используется"
},
{
"name": "mqm_channel",
"value": "не используется"
},
{
"name": "mqm_host",
"value": "amqps://hostname.domainname.ru"
},
{
"name": "mqm_port",
"value": "61617"
},
{
"name": "cipher",
"value": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
},
{
"name": "dn_mqgateway",
"value": "CN=TEST-GW"
},
{
"name": "dn_mqm",
"value": "CN=SYNAPSE"
},
{
"name": "error_desc",
"value": "{errorCode=, reason=dial tcp 10.25.8.7:61619: connect: connection refused, linkedErr=dial tcp 10.25.8.7:61619: connect: connection refused}"
}
]
}
Получение данных об имени проекта, имени Node и ее IP-адреса.
Чтобы приложение Шлюза получило доступ к этим данным, в deployment Шлюза должны быть добавлены следующие настройки:
env:
- name: PROJECT_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: NODE_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
Шлюз при заполнении данных о событиях должен передать в параметре os_project значение переменной окружения PROJECT_NAME, в параметре node_name значение переменной окружения NODE_NAME, в параметре node_ip значение переменной окружения NODE_IP.
Для включения регистрации событий, аудита нужно в конфигурацию Шлюза добавить секцию:
audit:
enable: true
transportType: file
directory: /opt/synapse/logs
В этом случае Шлюз MQ при старте создает в каталоге, указанном в параметре directory два файла:
event.aud
metamodel.amm
В файл metamodel.amm однократно выгружается метамодель событий. В файл event.aud начинают выгружаться события аудита по мере их возникновения на Шлюзе.
Эту схему можно использовать, если при регистрации событий аудита не предполагается использовать ТС Аудит, либо передача событий в ТС Аудит должна выполняться сторонними компонентами, выбранными архитектором и разработчиком конечной системы.
Для прямой отправки событий в ТС Аудит, секцию audit нужно настроить следующим образом.
audit:
enable: true
transportType: http
http:
client:
httpMethod: POST
url: http://хост:порт
eventPath: /event_endpoint
metamodelPath: /metamodel_endpoint
responseTimeout: 10000
maxBufferSize: 3000
retry:
attempts: 10
При старте Шлюз подключится к endpoint ТС Аудит зарегистрирует метамодель и начнет отправку событий.
Одна и та же версия метамодели может регистрироваться произвольное количество раз, но при этом описатель метамодели не должен меняться. Поэтому версия метамодели вместе с самой метамоделью прошита в коде Шлюза и меняется только при перепоставке.
Это гарантирует, что Шлюзы одной и той же версии установленные в разных проектах всегда будут оправлять консистентную модель.
При возникновении ошибок отправки, Шлюз сохраняет событие в локальном буфере в памяти приложения и пытается отправить его повторно. Количество попыток настраивается в параметре audit.http.retry.attempt. Количество событий, которое может быть сохранено в буфере настраивается в параметре audit.http.maxBufferSize.
Если возникает ошибка при регистрации модели, то Шлюз повторяет попытки, пока модель не будет зарегистрирована, при этом readiness проба не поднимается, и перевод трафика на этот экземпляр Шлюза не происходит.
Маршрутизация gRPC вызовов в Шлюзе#
Маршрутизация в Шлюзе — это определение имени сервиса-получателя (точки назначения), которому необходимо направить gRPC-вызов с преобразованным в формат ProtoMessage входящим сообщением.
В Шлюзе реализована динамическая маршрутизация по гибким правилам на основании параметров входящего MQ-сообщения.
Механизм маршрутизации работает следующим образом:
В настройках Шлюза в блоке gRPC прописывается наименование сервиса-заглушки empty-service.
grpc:
client:
settings:
default:
hostname: empty-service
port: 5454
При выполнении gRPC-вызова он перенаправляется механизмами Kubernetes в сервис, имя которого задано в параметре вызова Authority.
Шлюз позволяет динамически задать значение этого параметра при вызове, применяя правила, заданные в конфигурации Шлюза к параметрам (элементам тела и транспортным заголовкам) входящего сообщения.
Правила определения Authority задаются в конфигурации Шлюза в блоке routing.
Процесс маршрутизации сообщения состоит из нескольких шагов:
Шаг 1. Определение имени маршрута#
Правила определения имени маршрута задаются в секции routeName блока routing.
Секция определения имени маршрута (routeName):
routing:
routeName:
valueFrom:
- type: fromRfh2Header
value: OperationName
- type: fromBody
value: local-name(/*)
- type: fromConst
value: SomeServiceRq
expr: value[0:len(value)-2]
routeList:
...
В этой секции задается список правил, каждое правило состоит из пары type и value.
type - определяет источник, из которого будет извлечено значение. value - определяет правило извлечения значения. Для различных type возможные варианты значений value различны.
Для type= fromBody есть дополнительный тег valueJson, в котором можно задать выражение JsonPath для работы с сообщениями в формате JSON.
Возможные варианты:
type |
описание |
Значения value |
|---|---|---|
fromHeader |
значение извлекается из блока системных заголовков. |
value должно содержать название системного заголовка, из которого будет взято значение |
fromRfh2Header |
значение извлекается из блока пользовательских заголовков. |
value должно содержать название пользовательского заголовка, из которого будет взято значение |
fromBody |
значение будет извлечено из тела сообщения. |
value должно содержать XPath * запрос, которым из тела сообщения будет получено значение. Работает только с сообщениями в формате XML |
fromConst |
значение задается константой непосредственно в конфигурации. |
value должно содержать непосредственно нужное значение |
* При вычислении значений на основе содержимого тела XML-сообщения, Шлюз MQ может работать в одном из двух режимов: DOM или SAX. Режим может быть задан в параметре mq.typeParser конфигурации Шлюза MQ. По умолчанию используется значение DOM. Режим SAX более экономный в отношении использования ОЗУ, но ограничивает возможность задания value тремя типами выражений:
local-name(/*)— получение имени корневого тега XML-сообщения//tagName— получение значения элемента с именем tagName, если он встречается на любом уровне вложенности в сообщении. Возвращается значение первого найденного с таким именем элемента.//tagName/@attributeName— получение значения атрибута attributeName элемента tagName, если они встречаются на любом уровне вложенности сообщения. Возвращается значение для первого найденного с таким сочетанием имен аттрибута.
Для повышения гибкости определения маршрута в секции routeName есть параметр expr:, в нем можно задать выражение для дополнительной коррекции полученного значения. Обращение к найденному значению выполняется через предопределенную переменную value.
Например, выражение value[0:len(value)-2] позволяет обрезать два последних символа в полученном значении.
Шлюз применяет правила к входящему сообщению по порядку их следования в конфигурации, до тех пор, пока не будет получено ненулевое значение. Поэтому правило c типом fromConst следует ставить в конце списка.
К найденному значению Шлюз применяет выражение заданное в expr:
Полученное в результате этих действий значение и будет являться именем маршрута routeName.
Пример:
Настройки Шлюза заданы как указано выше.
Если сообщение содержит Property с ключом OperationName и значением "OneServiceNameRq", а тело сообщения содержит блок:
<Message>
<RqUID>4382730B7D4111ebB66EFA163E29F519</RqUID>
<RqTm>2021-03-05T08:44:09.000+00:00</RqTm>
<Mode>Async</Mode>
...
В routeName будет получено значение: OneService.
Шаг 2. Поиск блока настроек в списке маршрутов routeList#
Полученное на предыдущем шаге имя маршрута сопоставляется со списком элементов следующей секции блока routing - routeList.
Секция правил определения Authority (routeList)
routeList:
- routeName: AnotherService
destinationExpression: 'system1-anotherservice-system2-rs'
- routeName: default
destinationExpression: variables['SCName'] + '-' + variables['ServiceName'] + '-' + variables['SPName']
variables:
- name: ServiceName
valueFrom:
- type: fromBody
value: local-name(/*)
expr: value[0:len(value)-2]
- name: SCName
valueFrom:
- type: fromRfh2Header
value: SCName
- type: fromConst
value: 'System1'
expr: toLower(value)
- name: SPName
valueFrom:
- type: fromRfh2Header
value: SPName
- type: fromBody
value: //SystemID
expr: value+'-rs'
destinations:
'system1-someservice-system2-rs': 'system1-someservice-system2-async-rs'
Каждый элемент этой секции содержит именованный набор правил вычисления Authority сервиса назначения и состоит из параметров:
параметр |
описание |
|---|---|
routeName |
Имя маршрута, сопоставляется с полученным значением routeName |
destinationExpression |
Задает выражение, для непосредственного вычисления Authority из элементов variables |
variables |
задает список именованных переменных, используемых в destinationExpression, и правил определения их значений. |
destinations |
список соответствия вычисленных значений зафиксированным в этом списке. Позволяет при необходимости полученное значение другим |
Если в списке routeList найден блок с именем, соответствующим полученному routeName, то он используется для определения Authority.
Если нужный routeName не найден, но задан блок с routeName: default, то для определения Authority будет использован блок default. Если и блок default не задан, то будет сгенерировано исключение.
Шаг 3. Определение значений переменных#
Шлюз вычисляет значения всех переменных, описанных в списке variables. Каждый элемент списка variables содержит имя (name), список правил вычисления (type, value) и дополнительное выражение (expr).
variables:
- name: ServiceName
valueFrom:
- type: fromBody
value: local-name(/*)
expr: value[0:len(value)-2]
- name: SCName
valueFrom:
- type: fromRfh2Header
value: SCName
- type: fromConst
value: 'System1'
expr: toLower(value)
Принцип применения type, value и expr был детально рассмотрен выше, при описании вычисления routeName. Например, для приведенного примера значение параметра variables['ServiceName'] будет взято из корневого тега сообщения с обрезанием двух последних символов.
Шаг 4. Определение destinationExpression#
Полученные на шаге 3 значения параметров Шлюз подставляет в выражение заданное в destinationExpression и вычислив его получает Authority вызываемого сервиса.
В частном случае destinationExpression может быть задано константой.
Шаг 5. Подстановка#
В блоке правил может быть задан список destinations.
destinations:
'system1-someservice-system2-rs': 'system1-someservice-system2-async-rs'
Если он задан, Шлюз производит в нем поиск по наименованию значения, полученного на шаге 4. Если поиск успешен, то Шлюз производит замену Authority на значение из найденного элемента. Если список destinations не задан или поиск в нем неудачен, используется значение, полученное на шаге 4.
Шаг 6. Выполнение вызова#
Шлюз выполняет вызов сервиса по найденному Authority.
Примечание#
Прочие секции настроек блока routing кроме приведенных здесь на маршрутизацию сообщений не влияют.
Синтаксис Expression#
Поскольку строка в goel - это массив символов, а не объект, для обработки нужно использовать функции и/или операторы, а не методы.
функции |
Комментарий |
|---|---|
|
Преобразовать к нижнему регистру |
|
Преобразовать к верхнему регистру |
|
Сравнение строк |
|
Получение длины строки |
|
Выделение подстроки |
|
проверка, что переменная содержит строку |
|
определение позиции подстроки в строке |
|
Замена одной подстроки другой |
|
поделить строку на подстроки с использованием разделителя |
|
конкатенация строки строкового представления целого значения с инкрементом |
|
преобразование строки в целое число |
|
инкремент |
|
декремент |
|
проверка на пустое значение |
Реализация на Go поддерживает тернарный оператор.
Выражения:
SCName+'-'+ServiceName[0:len(ServiceName)-2]+'-'+SPName
"variables['SCName'] + '-' + 'srv' + variables['ServiceName'][0:len(ServiceName)-2] + '-' + variables['SPName']"
destinationExpression: '"ufsfl-srvgetcarddeliverystatus-oddo-rq"'
destinationExpression: "'ufsfl-srvgetcarddeliverystatus-oddo-rq'"
destinationExpression: ('ufsfl-srvgetcarddeliverystatus-oddo-rq')
"'<строка>' == toLower(value) ? '<строка 1>':value"
будут работать в реализации на Golang.
Спецификация интерфейсов#
Интерфейс транспортной библиотеки (Artemis - AMQP)#
Структура native-сообщения Artemis имеет ограниченный набор предопределенных заголовков, и список пользовательских свойств произвольного размера. Детально использование брокеров Artemis описано в документации Apache ActiveMQ Artemis.
Кодировка сообщений#
Artemis не обеспечивает механизма перекодирования сообщений и не имеет зарезервированного заголовка для передачи кодовой страницы.
Шлюз при работе с брокером Artemis обеспечивает передачу сообщений только в кодировке UTF-8.
Протокол обмена#
Шлюз, подключается к брокерам Artemis с использованием протокола AMQP. Спецификация протокола приведена в стандарте Advanced Message Queueing Protocol (AMQP) v1.0
Заголовки AMQP - Artemis#
Заголовок (Header)/Свойство (property) Artemis |
Комментарий |
|---|---|
header |
|
property |
Корреляционный идентификатор сообщения, формат - String |
header |
Приоритет обработки сообщения |
header |
Персистентность сообщения, |
header |
Момент времени, после которого сообщение считается просроченным |
header |
тип сообщения (text, byte, map, stream, object) |
header |
Время помещения сообщения в очередь |
header |
Признак повторной доставки сообщения. |
header |
Количество повторов доставки. Присутствует в свойствах сообщения после переноса в DeadLetterQueue |
property |
ID группы сообщений |
property |
Номер сообщения в группе |
|
Прочие пользовательские свойства сообщения Artemis доступны через JMS интерфейс как пользовательские свойства JMS |
|
Сообщения в Artemis могут аннотироваться. Например, при перемещении в ExpiryQueue в сообщении проставляются аннотации с исходным именем очереди и исходным expiry. |
Интерфейс gRPC#
Для выполнения вызовов внутри кластера используется протокол gRPC поверх HTTP/2.
Для определения интерфейса и генерации API использован Protobuf:
syntax = "proto3";
import "google/protobuf/any.proto";
package com.sbt.synapse.gateway;
option java_package = "com.sbt.synapse.gateway.protobuf";
option java_outer_classname = "MessageService";
service MessageAsyncChannel {
rpc processMessage (ProtoMessage) returns (Heartbeat);
}
service MessageSyncChannel {
rpc processMessage (ProtoMessage) returns (ProtoMessage);
}
message ProtoMessage {
string messageId = 1;
string correlationId = 2;
string body = 14;
map<string, string> systemHeaders = 3;
map<string, string> userHeaders = 4;
google.protobuf.Any extension = 15;
}
message Heartbeat {
int64 timestamp = 1;
string messageId = 2;
}
package com.sbt.synapse.gateway.mq;
message MqMessageInformation {
enum DeliveryMode {
UNKNOWN_MODE = 0;
NON_PERSISTENT = 1;
PERSISTENT = 2;
}
enum MessageType {
UNKNOWN_TYPE = 0;
REQUEST = 1;
REPLY = 2;
REPORT = 4;
DATAGRAM = 8;
}
MessageType messageType = 1;
int32 priority = 2;
DeliveryMode deliveryMode = 3;
int64 expiry = 4;
string destinationQueue = 5;
string destinationManager = 6;
string sourceQueue = 7;
string sourceManager = 8;
string jmsType = 9;
}
Параметры gRPC вызова:
Запрос
Параметр |
Описание |
|---|---|
:method |
POST |
:scheme |
"http"/"https" |
:path |
Имя сервиса/имя метода описанное в схеме |
:authority |
Виртуальное имя вызываемого хоста |
grpc-timeout |
Тайм-аут вызова |
content-type |
"application/grpc" |
grpc-message-type |
Название типа схемы сообщения |
Ответ
Параметр |
Описание |
|---|---|
:status |
HTTP-статус вызова |
grpc-status |
gRPC-статус вызова |
grpc-message |
Описание к статусу |
Метаданные gRPC вызова:
Заголовок |
Описание |
|---|---|
Обязательны для трассировки сообщений. Если не заполнены — генерируются внутренним прокси |
|
x_request_id |
Уникальный идентификатор сообщения. |
x_b3_traceid |
Уникальный идентификатор Trace'а. |
x_b3_spanid |
Уникальный идентификатор Span'а. |
x_b3_parentspanid |
Уникальный идентификатор родительского Span'а. |
x_b3_sampled |
Признак семплирования запроса – если <<1>>, то трассировка этого запроса должна быть отправлена в систему сбора информации. |
x_b3_flags |
Дополнительные флаги |
Используются на прикладном уровне. |
|
x-synapse-status-code |
Возвращаемый статус код. Включается в трассировку |
x-synapse-status-desc-bin |
Описание статуса. Включается в трассировку |
x-synapse-messageid |
Идентификатор сообщения. Включается в трассировку |
x-synapse-corellationid |
Корреляционный идентификатор. Включается в трассировку |
x-synapse-rquid |
RqUID. Включается в трассировку |
x-synapse-rquid-bin |
RqUID. Используется, если RqUID содержит символы не из ASCII набора (например кириллицу). При заполнении значение упаковывается в BASE64. Включается в трассировку. |
x-synapse-rqtm |
RqTm. Включается в трассировку |
x-synapse-spname |
Идентификатор поставщика сервиса. Включается в трассировку |
x-synapse-scname |
Идентификатор потребителя сервиса. Включается в трассировку |
x-synapse-servicename |
Наименование сервиса. Включается в трассировку |
x-synapse-operationname |
Наименование операции |
x-synapse-from |
Источник сообщения |
x-synapse-type-message |
Тип сообщения Запрос/Ответ (Rq/Rs) для асинхронных интеграционных взаимодействий |
x-synapse-monitoring-notification |
Признак нотификации |
x-synapse-serviceversion |
Версия сервиса. Включается в трассировку |
x-synapse-from-pod-name |
Имя pod источника сообщения |
x-synapse-propagate |
Признак необходимости отправки нотификации |
x-synapse-logging-system-name |
|
Необязательные. Используются для корректировки параметров исходящего сообщения |
|
x-synapse-override-clear-correlationid |
Исключает CorrelationID из сообщения (true/false) |
x-synapse-override-destination-queue |
Заменяет очередь назначения |
x-synapse-override-expiry |
Заменяет JMSExpiration. Указывается в миллисекундах |
x-synapse-override-jmstype |
Заменяет JMSType в Jms сообщении |
x-synapse-override-persistence |
Заменяет персистентность (Режим доставки) сообщения (0 = UNKNOWN_MODE; 1 = NON_PERSISTENT; 2 = PERSISTENT) |
x-synapse-override-priority |
Заменяет приоритет сообщения |
x-synapse-override-replytoq |
Заменяет очередь для ответа |
x-synapse-override-replytoqmgr |
Заменяет менеджер для ответа |
Интерфейс HTTP#
Для выполнения вызовов используется протокол HTTP/1.1. Тип вызова — синхронный.
Параметры вызова (используется только метод POST):
Запрос
Параметр |
Описание |
|---|---|
Метод |
POST |
URI |
Адрес вызываемого ресурса |
Протокол |
HTTP/1.1 |
Host |
Имя хоста |
Content-Type |
Тип тела запроса |
Content-Length |
Длина тела запроса |
Ответ
Параметр |
Описание |
|---|---|
Протокол |
HTTP/1.1 |
HTTP-status |
Статус вызова |
Status |
Описание статуса |
Content-Type |
Тип тела ответа |
Content-Length |
Длина тела ответа |
Тело сообщения:
Текстовое, в формате XML.
Пользовательские заголовки вызова:
Специальных требований к наличию дополнительных заголовков не предъявляется.
Состав используемых заголовков определяется индивидуально для каждого прикладного интеграционного взаимодействия и задается в конфигурации.
Преобразование интерфейсов#
Преобразование интерфейса AMQP-Artemis в gRPC (чтение сообщения из MQ)#
При трансляции JMS-сообщения в gRPC вызов поля структуры ProtoMessage заполняются по следующим правилам:
| Структура | Поле | Тип | Источник значения | Комментарий |
|----------------------|------------------------------------------------------|------------------------------|--------------------------------------------------------------|
|ProtoMessage|messageId | | userID | Уникальный идентификатор полученного сообщения |
|ProtoMessage|correlationId | | CorrelationID | Корреляционный идентификатор полученного сообщения |
|ProtoMessage|body | | body | Тело текстового сообщения копируется без преобразования.
Сообщение типа массив байтов преобразуется в строку |
|ProtoMessage|systemHeaders
| <string, string>
… | properties … | В цикле добавляются свойства (Property) сообщения имеющие префикс "JMS" в названии.
key заполняется названием свойства. |
|ProtoMessage|userHeaders | <string, string>
… | properties … | В цикле добавляются свойства (Property) сообщения не имеющие префикса "JMS" в названии.
key заполняется названием свойства. |
|ProtoMessage|extension (<MqMessageInformation> extension)|messageType | property "JMS_IBM_MsgType", если не задано, то 0 | Тип сообщения. Не используется в Artemis |
|ProtoMessage|extension (<MqMessageInformation> extension)|priority | priority | Приоритет сообщения. |
|ProtoMessage|extension (<MqMessageInformation> extension)|deliveryMode | durable | Признак персистентности сообщения |
|ProtoMessage|extension (<MqMessageInformation> extension)|expiry | expiration - timestamp | Время жизни сообщения в миллисекундах. Пересчитывается из TTL |
|ProtoMessage|extension (<MqMessageInformation> extension)|destinationQueue | - | Наименование MQ-очереди в которую выходной Шлюз должен отправить сообщение. При чтении сообщения из очереди не заполняется |
|ProtoMessage|extension (<MqMessageInformation> extension)|sourceQueue | sourceQueue | Очередь из которой вычитано входящее сообщение. Задается Шлюзом |
|ProtoMessage|extension (<MqMessageInformation> extension)|jmsType | type | Тип сообщения. |
Заголовки gRPC-вызова заполняются по следующим правилам:
Параметр |
Источник значения |
Комментарий |
|---|---|---|
:method |
POST |
Используемый метод HTTP протокола |
:scheme |
"http" |
Всегда используется HTTP, при необходимости использовать HTTPS для внутренних вызовов настраивается средствами Kubernetes ServiceMesh |
:path |
/com.sbt.synapse.gateway.MessageSyncChannel/processMessage для синхронного вызова |
Имя сервиса/имя метода описанное в схеме |
:authority |
Задается по правилам маршрутизации |
Виртуальное имя вызываемого хоста, вычисляется по правилам заданным в настройках destinationExpression, variables и destinations секции routing.routeList конфигурации Шлюза |
grpc-timeout |
Из настройки timeout секции grpc.client.settings конфигурации. |
Таймаут вызова по gRPC |
content-type |
"application/grpc" |
Тип контента |
grpc-message-type |
|
Название типа схемы сообщения |
При синхронном вызове, когда ответ возвращается в той же сессии gRPC, в которой был получен запрос:
Заголовки gRPC-ответа заполняются по следующим правилам:
Параметр |
Источник |
Комментарий |
|---|---|---|
:status |
Заполняется Шлюзом |
HTTP-статус вызова |
grpc-status |
Заполняется Шлюзом |
gRPC - статус вызова |
grpc-message |
Заполняется Шлюзом |
Описание к статусу |
Метаданные gRPC-вызова заполняются по следующим правилам:
Заголовок |
Источник значения |
Комментарий |
|---|---|---|
Обязательны для трассировки сообщений. Если не заполнены — генерируются внутренним прокси |
||
|
Генерируется |
Уникальный идентификатор сообщения. Формат: GUID. Генерируется Envoy'ем (внутренним прокси), если запрос еще не имеет такого заголовка. |
|
Генерируется |
Уникальный идентификатор Trace. Формат: строка с Hex-представлением 64- или 128-битного целого числа. Генерируется Шлюзом, если установлена настройка |
|
Генерируется |
Уникальный идентификатор Span. Формат: строка с Hex-представлением 64-битного целого числа. Генерируется Шлюзом, если установлена настройка |
|
Генерируется |
Уникальный идентификатор родительского Span. Формат: строка с Hex-представлением 64-битного целого числа. Генерируется Шлюзом, если установлена настройка |
|
1 |
Признак семплирования запроса — если <<1>>, то трассировка этого запроса должна быть отправлена в систему сбора информации. Устанавливается в 1, если установлена настройка |
|
не заполняется на Шлюзе |
Дополнительные флаги |
Используются на прикладном уровне |
||
|
Не заполняется в запросе |
Возвращаемый статус код. Включается в трассировку |
|
Не заполняется в запросе |
Описание статуса. Включается в трассировку |
|
|
Идентификатор сообщения. Заполняется значением из ProtoMessage (см. блок заполнения ProtoMessage). Включается в трассировку |
|
|
Корреляционный идентификатор. Заполняется значением из ProtoMessage (см. блок заполнения ProtoMessage). Включается в трассировку |
|
Реквизит входящего сообщения |
RqUID - уникальный ID запроса. Должен поставляться внешней АС. Порядок извлечения определяется настройкой |
|
Реквизит входящего сообщения |
Аналогичен |
|
Реквизит входящего сообщения |
RqTm - время запроса. Может поставляться внешней АС. Порядок извлечения определяется настройкой |
|
|
Идентификатор поставщика сервиса. Определяется настройкой variables секции |
|
|
Идентификатор потребителя сервиса. Определяется настройкой variables секции |
|
Не заполняется на Шлюзе |
Наименование сервиса. Включается в трассировку |
|
|
Наименование операции. Определяется настройкой variables секции |
|
|
Источник сообщения. Заполняется значением настройки |
|
"RQ" |
Тип сообщения Запрос/Ответ (Rq/Rs) для асинхронных интеграционных взаимодействий. Для Шлюза потребителя проставляется "RQ" |
|
|
Версия сервиса. Определяется настройкой variables секции |
|
|
Имя Pod источника сообщения. Заполняется на Шлюзе именем собственного pod. |
|
не заполняется на Шлюзе |
Признак необходимости отправки нотификации |
|
Не заполняется на Шлюзе |
Имя системы для записи в лог |
Необязательные. Используются для корректировки параметров исходящего сообщения |
||
|
Не заполняется на Шлюзе |
Исключает |
|
Не заполняется на Шлюзе |
Заменяет менеджер назначения |
|
Не заполняется на Шлюзе |
Заменяет очередь назначения |
|
Не заполняется на Шлюзе |
Заменяет |
|
Не заполняется на Шлюзе |
Заменяет |
|
Не заполняется на Шлюзе |
Заменяет персистентность (Режим доставки) сообщения (0 = UNKNOWN_MODE; 1 = NON_PERSISTENT; 2 = PERSISTENT) |
|
Не заполняется на Шлюзе |
Заменяет приоритет сообщения |
|
Не заполняется на Шлюзе |
Заменяет очередь для ответа |
В конфигурации Шлюза можно дополнительно задать значение персистентности отправляемых сообщений по умолчанию:
mq.outbound.defaultPersistence(значенияPERSISTENT/NON_PERSISTENT) для Шлюза в целом,mq.outbound.serviceList[].overridePersistense(значенияPERSISTENT/NON_PERSISTENT) для конкретного сервиса.Признак персистентности в отправляемом сообщении (
deliveryMode) будет выставлен:в соответствии с параметром
overridePersistenseна сервисе при его наличии;иначе в соответствии с параметром
defaultPersistenceна Шлюзе, при его наличии;иначе в соответствии с заголовком
x-synapse-override-persistenceпри его наличии;иначе в соответствии с заголовком
ProtoMessage.extension.messageType.
Преобразование интерфейса gRPC в AMQP-Artemis (отправка сообщения в MQ)#
Параметры отправляемого сообщения |
Источник |
комментарий |
|---|---|---|
|
|
Тело сообщения копируется в исходящее сообщение без преобразования |
|
|
Корреляционный идентификатор сообщения. Если во входящем сообщении отсутствует или заполнен нулями, то не передается в исходящее сообщение |
|
|
Режим доставки. Если значение = 0, то не заполняется (определяется настройкой на целевой очереди) |
|
Настройка |
Назначение (Очередь, в которую должно быть помещено сообщение). |
|
ProtoMessage.extension.expiry |
Время жизни сообщения. Преобразуется из expiry в TTL |
|
ProtoMessage.messageId |
Идентификатор сообщения |
|
ProtoMessage.extension.priority |
Приоритет сообщения |
|
ProtoMessage. systemHeaders.get("ReplyToQ") |
Назначение для ответа (Очередь, в которую должен быть помещен ответ на это сообщение) |
|
Проставляется MQ менеджером |
Метка времени сообщения |
|
- |
Тип сообщения. Определяется классом отправляемого сообщения |
|
ProtoMessage. systemHeaders.get(systemKey) |
В цикле добавляются все свойства из |
… |
… |
В цикле добавляются все свойства из |
|
ProtoMessage.userHeaders.get(userKey) |
В цикле добавляются все свойства из |
… |
… |
В цикле добавляются все свойства из |
Подмена значений свойств сообщения с помощью заголовков gRPC-вызова.
Если во входящем вызове заданы определенные gRPC-заголовки, их значение переопределяет значение свойств отправляемого в MQ сообщения до его отправки, в порядке указанном в таблице:
Параметр сообщения |
gRPC заголовок |
Действие |
|---|---|---|
|
|
Заменяет |
|
|
Заменяет |
|
|
Заменяет |
|
|
Заменяет |
|
|
Заменяет |
|
|
Очищает |
Формирование квитанции (HeartBeat) при получении асинхронного вызова#
При получении асинхронного вызова по gRPC Шлюз в ответ отправляет квитанцию (HeartBeat), содержащую информацию о статусе вызова.
Заголовки gRPC-ответа в этом случае заполняются по следующим правилам:
Параметр |
Источник |
Комментарий |
|---|---|---|
:status |
Заполняется Шлюзом |
HTTP-статус вызова |
grpc-status |
Заполняется Шлюзом |
gRPC-статус вызова |
grpc-message |
Заполняется Шлюзом |
Описание к статусу |
Поля сообщения HeartBeat заполняются по следующим правилам:
Поле структуры |
Источник |
Комментарий |
||
|---|---|---|---|---|
|
|
int64 |
Системное время Шлюза |
Метка времени ответа при вызове через |
|
|
string |
|
ID сообщения в ответе при вызове через |
Преобразование интерфейса AMQP-Artemis в HTTP при запросе со стороны внешней АС#
Параметры сообщения передаются в HTTP-вызов по следующим правилам:
Запрос:
Параметр |
Описание |
Комментарий |
|---|---|---|
Метод |
Настройка |
Вызываемый метод HTTP-протокола. Заполняется из настройки |
URI |
Настройка |
Адрес вызываемого ресурса. Заполняется из настройки |
Протокол |
HTTP/1.1 |
Сигнатура протокола. |
Host |
Настройка |
Имя хоста. Заполняется из настройки |
Content-Type |
application/xml application/json |
Тип тела запроса. |
Content-Length |
Задается Шлюзом |
Длина тела запроса. |
Система копирует тело запроса из входящего JMS-сообщения без преобразования на Шлюзе. Дополнительные заголовки HTTP добавляются системой в исходящий вызов, если установлена настройка mqHttpRequired в секции transform.mq-http конфигурации Шлюза, либо если по правилам роутинга определен тип транспорта - http, и для него заданы правила трансформации. В этом случае все заголовки, описанные в секции transform.mq-http.headers (либо по правилам трансформации, заданным в секции routing), будут добавлены к исходящему HTTP-вызову.
Важно! Все заголовки сообщения, которые необходимо передать в HTTP-вызов, должны быть явно заданы в правилах трансформации.
Существует ограничение для заголовков, для которых указано правило извлечения fromHeaders. Для них определен фиксированный набор ключей и правила сопоставления с JMS-заголовками.
Ключ |
Источник |
Комментарий |
|---|---|---|
|
|
Идентификатор сообщения. |
|
|
Корреляционный идентификатор сообщения. |
|
|
Очередь для ответа. |
|
|
Идентификатор группы сообщения. |
|
|
Приоритет сообщения. |
|
|
Режим отправки. |
|
|
Время жизни сообщения. |
|
|
Очередь назначения. |
Преобразование интерфейса AMQP-Artemis в HTTP при ответе со стороны внешней АС#
Ответ:
Параметр |
Описание |
Комментарий |
|---|---|---|
Протокол |
HTTP/1.1 |
Сигнатура протокола |
HTTP-status |
Заполняется Шлюзом |
Статус вызова |
Status |
Заполняется Шлюзом |
Описание статуса |
Content-Type |
application/xml application/json |
Тип тела ответа |
Content-Length |
Заполняется Шлюзом |
Длина тела ответа |
Тело запроса:
Система копирует тело запроса из входящего JMS-сообщения без преобразования на Шлюзе. Дополнительные заголовки HTTP добавляются системой в ответ по тем же правилам, что и при обработке запроса.
Преобразование интерфейса HTTP в AMQP-Artemis при запросе со стороны HTTP клиента и ответе со стороны HTTP сервиса#
Тело сообщения (Body):
Параметры сообщения |
Источник |
Комментарий |
|---|---|---|
|
|
Тело сообщения копируется в исходящее JMS-сообщение без преобразования |
Система заполняет заголовки (Headers) из HTTP сообщения, если включена настройка httpMqRequired в секции transform.http-mq. Правила прописаны в секциях http-mq.mqmd и http-mq.usr. При этом используются ключи:
Параметры отправляемого сообщения |
ключ настройки |
Комментарий |
|---|---|---|
|
|
Корреляционный идентификатор сообщения. |
|
|
Режим доставки. |
|
|
Назначение — очередь, в которую должно быть помещено сообщение. Заполняется значением, полученным по ключу |
|
|
Время жизни сообщения. |
|
|
Идентификатор сообщения. |
|
|
Назначение для ответа — очередь, в которую помещается ответ на это сообщение. Заполняется значением, полученным по ключу |
|
Заполняется брокером |
Метка времени сообщения. |
|
Не определено |
Тип сообщения. |
|
|
Номер группы. |
|
|
Номер сообщения в группе. |
|
|
В цикл добавляются все значения, определенные по ключам. Ключи задаются в |
Важно! Все заголовки сообщения, которые необходимо передать из HTTP-вызова, должны быть явно заданы в правилах трансформации.
Полное описание настроек#
Важно! Строковые значения представляющие числовые величины рекомендуется заключать в кавычки, во избежание неявных преобразований типов при загрузке и чтении конфигурации.
Верхнеуровневые блоки настроек#
Название |
Описание |
Обязательность |
|---|---|---|
Настройки gRPC-клиента/сервера |
- |
|
Настройки сервера |
- |
|
Настройки HTTP-транспорта |
- |
|
Настройки прикладного журнала |
- |
|
Описание преобразования HTTP-заголовков в формат MQ и обратно |
- |
|
Настройки подключения к MQ |
+ |
|
Правила маршрутизации |
+ Необязателен для синхронного Шлюза провайдера |
|
Настройки трассировки |
+ |
|
Настройки журналирования |
- |
|
Настройки подключения внешнего валидатора REQV |
- |
|
Настройки отправки событий в аудит |
— |
|
Настройки настройки механизма очистки .FDC файлов |
- |
|
Настройка разбора тела сообщения |
- |
|
Настройка параметров проверки файлов конфигурации на изменение |
— |
Блок grpc#
Настройки gRPC-клиента/сервера:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
Настройки клиента для gRPC API |
+ |
||
|
Настройки сервера gRPC API |
- |
Тип grpc.GRpcClientProperties#
Настройки клиента gRPC API:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
Map<String, ClientSettings> |
Имя канала и соответствующие ему настройки. Предопределен канал: - |
+ |
Тип grpc.ClientSettings#
Настройки gRPC-канала:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
String |
Хост, к которому будет осуществляться запрос |
- |
empty-service |
|
int |
Порт подключения |
+ |
5454 |
|
int |
Тайм-аут запроса, мс |
- |
300 000 |
Пример настройки секции client
grpc:
client:
settings:
default:
hostname: localhost
port: 5455
timeout: 1000
Тип grpc.GRpcServerProperties#
Настройки сервера gRPC API:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
int |
Порт сервера gRPC API |
- |
6565 |
|
Настройки пула обработчиков запросов |
- |
||
|
int |
Настройка максимального размера сообщения, передаваемого через gRPC, Мбайт |
— |
4 |
Тип grpc.ThreadPoolConfiguration#
Параметры pool потоков сервера gRPC. Предназначен для тонкой настройки.
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
int |
Минимальное количество потоков, обрабатывающих запросы |
- |
1 |
|
int |
Максимальное количество потоков, обрабатывающих запросы |
- |
5 |
|
int |
Время жизни потока после обработки последнего сообщения, с |
- |
60 |
|
int |
Ограничение на число запросов в обработке. По умолчанию отключено. (Deprecated, рекомендуется использовать параметр concurrentLimiter) Используется для защиты от перегрузок. Если установлено значение больше нуля, то при его превышении будет генерироваться ошибка со статусом UNAVAILABLE. При таком коде ошибки Envoy по умолчанию повторяет вызовы – запрос уйдет на менее нагруженный pod |
- |
0 |
Пример настроек блока grpc
grpc:
maxMessageSizeInMb: 4 - максимальный размер gRPC-сообщения
server:
serverPort: 5455
threadPool:
#ограничение запросов в обработке
rejectCapacity: 500
concurrentConsumers: 30
maxConcurrentConsumers: 30
client:
settings:
default:
hostname: localhost
port: 5454
Блок server#
Настройки сервера:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
String |
Псевдоним системы-инициатора, используемый при фиксации HTTP-вызова в прикладном журнале. Используется для ведения журнала в HTTP-вызовах |
- |
REST |
|
int |
Порт, на котором запустится приложение |
- |
8080 |
|
string |
URI HTTP-сервиса, поднимаемого Шлюзом |
- |
|
|
boolean |
Признак конвертации запросов из формата XML в JSON и обратно |
- |
true |
|
int |
Только для реализации на Golang. |
— |
16KB |
|
int |
Максимальный размер тела сообщения |
- |
|
|
Параметры ограничения одновременной обработки сообщений по http |
— |
Тип server.ConcurrentLimiter#
настройки ограничителя одновременной обработки сообщений по http
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
включен ли ограничитель |
— |
false |
|
int |
кол-во одновременно выполняемых запросов |
- |
100 |
Блок http#
Настройки HTTP-транспорта:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
Настройки клиента HTTP |
+ |
Тип httpClientConfiguration#
Настройки клиента HTTP:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
String |
URL, по которому будет вызываться сервер |
+ |
|
|
Long |
Тайм-аут, мс |
- |
Без тайм-аута |
|
enum |
Тип метода, который будет использоваться при HTTP-вызове |
- |
POST |
Блок logger#
Настройки ведения прикладного журнала:
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
<String, List<ExtractionRule>> |
Правила определения заголовков для ведения журнала. Доступны |
- |
|
Настройка правил маскирования элементов тела сообщения в прикладном журнале. Обычно настройка выносится в отдельный файл конфигурации masking-secret.yml, который загружается в секрет. |
- |
Тип LoggerMaskConfigurationProperties#
Настройки маскирования элементов тела сообщения при записи в прикладной журнал.
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
boolean |
Включение/выключение маскирования |
- |
|
Set<String> |
Список наименований XML-атрибутов, в которых нужно замаскировать номер карты |
- |
|
Set<String> |
Список наименований XML и JSON-элементов, в которых нужно замаскировать номер карты |
- |
|
Set<String> |
Список наименований XML-атрибутов, в которых нужно замаскировать номер телефона |
- |
|
Set<String> |
Список наименований XML и JSON-элементов, в которых нужно замаскировать номер телефона |
- |
|
Set<String> |
Список наименований XML-атрибутов, в которых нужно замаскировать номер паспорта |
- |
|
Set<String> |
Список наименований XML и JSON-элементов, в которых нужно замаскировать номер паспорта. |
- |
|
Set<String> |
Список наименований XML-атрибутов, в которых нужно замаскировать ФИО |
- |
|
Set<String> |
Список наименований XML и JSON-элементов, в которых нужно замаскировать ФИО. |
- |
|
Set<String> |
Список наименований XML-атрибутов, в которых нужно замаскировать ИНН. |
- |
|
Set<String> |
Список наименований XML и JSON-элементов, в которых нужно замаскировать ИНН. |
- |
|
Set<String> |
Список наименований XML-атрибутов, значение которых нужно полностью замаскировать. |
- |
|
Set<String> |
Список наименований XML и JSON-элементов, значение которых нужно полностью замаскировать. |
- |
|
|
Список карт наименований XML-элементов и их атрибутов, значения которых нужно полностью замаскировать. Используется, когда есть повторяющиеся наименования XML-атрибутов. Важно! Тег не может быть пустым. Добавление данного тега, не содержащего элементов и аттрибутов для маскирования, приведет к ошибке загрузки Шлюза. |
- |
|
|
Список карт наименований XML-атрибутов и их значений, значения элементов которых необходимо полностью замаскировать. Используется, когда есть повторяющиеся наименования XML-элементов и XML-атрибутов. Важно! Тег не может быть пустым. Добавление данного тега, не содержащего аттрибутов и их значений для маскирования, приведет к ошибке загрузки Шлюза. |
- |
Пример настроек маскирования
logger:
mask:
enabled: true
cardNumElements:
- CardNum # Будет замаскировано значение элемента CardNum: <CardNum>44****9695</CardNum>
elements:
- Phone # # Будет замаскировано значение элемента Phone: <Phone>***********</Phone>
elementsWithAttribute:
ID:
- Value
- Name
AccountNumber:
- Value # Будет замаскировано значение аттрибута Value в элементе <AccountNumber Value=\"*******************\"></AccountNumber>
TaxId:
- Value
elementByAttribute:
type:
- CardNum
- DocNum
item:
- FIO # Будет замаскировано значение элементов, у которых аттрибут item имеет значение "FIO" <Value item="FIO">********** ******* ********</Value>
Шлюз позволяет осуществлять маскирование в экранированном XML. Пример маскирования экранированного XML
Настройка:
logger:
mask:
enabled: true
phoneNumElements:
- phone
docNumElements:
- doc
fioElements:
- Fio
Сообщение:
<Root xmlns:hdr="http://example.com/ESB/mq/headers">
<hdr:ElementTest>
<Contacts>
<phone>+7 (123) 456-78-90</phone>
</Contacts>
<Passport>
<doc>9911 123456</doc>
</Passport>
</hdr:ElementTest>
</Root>
Отражение в прикладном журнале:
<Root xmlns:hdr="http://example.com/ESB/mq/headers"> <hdr:ElementTest> <Contacts> <phone>+* (***) ***-78-90</phone> </Contacts> <Passport> <doc>**** ****56</doc> </Passport> </hdr:ElementTest> </Root>
Блок transform#
Тип TransformConfig#
Описание преобразования HTTP-заголовков в формат MQ и обратно:
Поле |
Тип |
Описание |
Обязательность |
Динамические настройки |
|---|---|---|---|---|
|
Правила преобразования MQ-заголовков в HTTP-заголовки |
+ |
+ |
|
|
Правила преобразования HTTP-заголовков в MQ-заголовки |
+ |
+ |
Тип MqHttpTransformConfig#
Правила преобразования MQ-заголовков в HTTP-заголовки:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
Map<String, List<ExtractionRule>> |
Список заголовков с правилами преобразования |
+ |
Пример настроек MQ-HTTP
mq-http:
headers:
MsgType:
type: fromConst
value: '8' #DATAGRAM(8)
MsgId:
type: fromHeader
value: 'MQMD.MsgId' #Из входящего ProtoMessage будет взят messageId и помещен в HttpMessage в заголовок MsgId
Тип HttpMqTransformConfig#
Правила преобразования MQ-заголовков в HTTP-заголовки:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
Map<String, List<ExtractionRule>> |
Список mqmd-заголовков с правилами преобразования |
- |
|
|
Map<String, List<ExtractionRule>> |
Список usr-заголовков с правилами преобразования |
- |
Пример настроек HTTP-MQ
http-mq:
mqmd:
MsgId:
type: fromHeader
value: 'MsgId'
MsgType:
type: fromConst
value: '8'
Persistence:
type: fromConst
value: '1'
ReplyToQ:
- type: fromHeader
value: ReplyToQ # можно задать очередь для ответа
DestinationQueue: # так можно задать очередь, в которую нужно отправить сообщение (если sendToCustomDestination: true)
- type: fromHeader
value: DestinationQueue
usr:
ServiceName:
type: fromConst
value: 'TestServiceName'
Блок mq#
Блок настроек в части MQ.
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Версия Шлюза, в которой появилось поле |
Динамические настройки |
|---|---|---|---|---|---|---|
|
String |
Используемый провайдер MQ (поддерживается только ActiveMQ Artemis) |
+ |
ARTEMIS_MQ |
||
|
String |
Имя системы, с которой осуществляется взаимодействие |
+ |
|||
|
Enum |
DOM/SAX Задает тип парсера для обработки XML. Используется для вычисления значений через Xpath. Менее требовательный к памяти SAX. При использовании SAX-парсера есть ограничения на использование Xpath-выражений. Допускаются: |
— |
DOM |
3.11.0 |
|
|
Enum |
Тип Шлюза: Шлюз потребителя или Шлюз поставщика. Значения: sp, sc, all |
+ |
|||
|
String |
Режим работы Шлюза: поддерживается только совмещенный синхронный и асинхронный (all) режим работы |
+ |
|||
|
Настройки подключения к MQ |
+ |
||||
|
List<SslConfig> |
Список настроек SSL для соединений из настройки |
- |
|||
|
Параметры считывания сообщений из MQ. Не используется при |
- |
||||
|
Параметры настройки сервиса получения ответов из MQ. Используется только при |
- |
||||
|
boolean |
Включает режим отката сообщения при ошибке. Шлюз вызывает синхронно Async и Sync интерфейс gRPC и, в случае ошибки, делает возврат считанного сообщения в очередь |
- |
false |
||
|
Параметры для исходящих в MQ сообщений |
- |
+ |
|||
|
Параметры ограничения одновременной обработки считанных сообщений |
- |
+ |
|||
|
Параметры ограничения скорости обработки считанных сообщений |
- |
+ |
|||
|
Int |
Ограничение размера обрабатываемых сообщений, получаемых из MQ. |
- |
100 |
||
|
String |
Задает размер памяти пользовательских заголовков, которые может вычитать шлюз (реализовано только в Go). Формат задаваемых значений: 1KB / 1MB / 1GB |
- |
1KB |
||
|
Параметры ограничения одновременной обработки синхронных вызовов |
- |
||||
|
Параметры ограничения отправки в MQ |
- |
||||
|
Параметры обновления SSL сертификатов |
- |
Тип mq.GlobalConnectionConfiguration#
Настройки MQ:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Версия Шлюза, в которой появилось поле |
Динамические настройки |
|---|---|---|---|---|---|---|
|
List<ConnectionConfiguration> |
Список соединений |
||||
|
List<String> |
Список имен очередей для чтения в режимах (workMode): sync, async, all. В режиме all сообщения из этих очередей будут обрабатываться асинхронно. Для синхронных запросов очереди для считывания ответов будут определяться в приоритете через заголовок с именем |
- |
|||
|
List<String> |
Список очередей для чтения сообщений для потребителя в режиме |
- |
|||
|
String |
Очередь для отправки сообщений. Может быть переопределено: - через заголовок |
- |
+ |
||
|
List<ParamQueue> |
Очереди для чтения в режиме ALL (поставщик+потребитель) |
- |
|||
|
Очереди по умолчанию для отправки в режиме ALL (поставщик+потребитель) |
- |
||||
|
boolean |
Если |
- |
false |
+ |
|
|
boolean |
Установка параметров групповых сообщений в отправляемом сообщении, из UserHeaders ProtoMessage. Устанавливаются заголовки с именами: JMSXGroupID, JMSXGroupSeq, JMS_IBM_Last_Msg_In_Group (при наличии) |
- |
false |
||
|
boolean |
Включение использования одного сокета для нескольких MQ-сессий. |
— |
true |
||
|
Настройки проверки доступности брокеров MQ |
- |
||||
|
int |
Размер кэша Sender влияет на ТПС и скорость восстановления соединения. Должен соответствовать настройке grpc.ThreadPoolConfiguration.maxConcurrentConsumers ± 10% |
- |
10 |
Тип ConnectionConfiguration#
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
String |
url подключения в формате <протокол>://<имя хоста>:<порт>, |
+ |
|
|
String |
username брокера |
- |
|
|
String |
password брокера |
- |
|
|
String |
Название профиля конфигурации SSL, который будет применен к этому соединению. Сопоставляется с именем из |
- |
|
Тип SslConfig#
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
String |
Имя профиля конфигурации SSL сопоставляется с |
- |
|
|
String |
Имя шифровального набора (формат соответствует формату, используемому на брокере). |
- |
|
|
|
Задает список DN сертификатов для проверки. Если не задан, будет использована проверка по имени хоста |
- |
|
|
|
Задает необходимость проверки сертификата брокера на соответствие имени хоста. Если задан список DN, то проверка на имя хоста не проводится |
- |
true |
|
SSLSocketFactoryConfiguration |
Параметры фабрики для создания SSL-сокетов |
- |
Тип mq.SSLSocketFactoryConfiguration#
Параметры фабрики для создания SSL-сокетов:
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
enum |
Протоколы, которые поддерживаются провайдером SunJSSE. Протоколы SSL_TLS, SSLv2, SSL_TLSv2 исключены из списка, т. к. не поддерживаются SunJSSE. Значения: |
+ |
|
String |
путь к файлу с личным ключом шлюза |
+ |
|
String |
путь к файлу с сертификатом шлюза |
+ |
|
String |
путь к файлу с сертификатами УЦ |
+ |
Тип HealthConfiguration#
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
int |
Количество успешных проверок, после которого брокер возвращается в балансировку |
- |
1 |
|
int |
Количество неуспешных проверок, после которого брокер исключается из балансировки |
- |
1 |
|
int |
Таймаут проверки |
- |
5 |
|
int |
Период опроса. |
- |
|
|
int |
Задержка перед началом опроса |
- |
Тип mq.ConsumerConfiguration#
Параметры считывания сообщений из MQ. Данный блок предназначен для тонкой настройки.
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Появилось в версии Шлюза |
Динамические настройки |
|---|---|---|---|---|---|---|
|
|
Признак включения или выключения MQ-listeners. При старте Шлюза настройка со значением |
- |
|
+ |
|
|
String |
Максимальное время выполнения транзакции в секундах. "-1" - время выполнения транзакции не ограничено. Требуется обязательное указание размерности (300s), если не указать, при загрузке ШЛюза настройка будет сброшена в значение по умолчанию, в системный лог будет выведено предупреждение. |
- |
300 |
||
|
int |
Максимальное количество кешированных сессий JMS |
- |
10 |
||
|
int |
Максимальное время выполнения считывания сообщения из MQ в миллисекундах |
- |
100 |
||
|
int |
Минимально количество потоков, одновременно выполняющих чтение из MQ |
- |
1 |
||
|
int |
Минимальное количество открытых очередей на чтение из MQ |
- |
1 |
||
|
boolean |
Признак копирования заголовка |
- |
false |
||
|
boolean |
Признак копирования заголовка |
- |
false |
||
|
Параметры пула потоков считывания сообщений из MQ |
- |
||||
|
List<string> |
Отключение чтения и отправки в указанный брокер. Список отключаемых брокеров в формате: <хост>:<порт> |
- |
пусто |
+ |
Тип mq.ThreadPoolConfiguration#
Параметры pool потоков считывания сообщений из MQ. Предназначен для тонкой настройки:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
int |
Минимальное количество потоков, обрабатывающих входящие сообщения из MQ |
- |
1 |
|
int |
Максимальное количество потоков, обрабатывающих входящие сообщения из MQ |
- |
5 |
|
int |
Время жизни потока в секундах после обработки последнего сообщения |
- |
60 |
Тип mq.SyncReceiveTaskConfig#
Параметры настройки сервиса получения ответов из MQ. Используется только при systemType=sp и workMode=sync.
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
enum |
Устанавливает режим чтения ответов от синхронного поставщика. Возможные значения: SHARED_SINGLE, // вычитка по селектору из общей очереди по CorelId с одного менеджера SHARED, // вычитка по селектору из общей очереди по CorelId (все менеджеры)UNIQUE, // вычитка из выделенной очереди для Pod/инстанса SHARED_SELECTOR // вычитка из общей очереди с фиксированным селектором по имени Pod |
- |
SHARED_SINGLE |
|
String |
Пользовательское имя заголовка — селектора для режима чтения ответов SHARED_SELECTOR |
- |
GWResponseSelector |
|
int |
Количество потоков в пуле обработчиков — потоков, считывающих ответы из MQ |
- |
20 |
|
int |
Время ожидания перед первым считыванием ответа, в мс |
- |
200 |
|
int |
Максимальное время между повторами считывания ответа, в мс |
- |
2000 |
|
int |
Максимальное время получения ответа, в мс. По истечении этого времени ответ не будет получен и клиенту будет отправлена отмена вызова. Должен быть больше любого тайм-аута на сервисе |
- |
30000 |
|
int |
Максимальное время ожидания ответов при остановке приложения, в мс |
- |
100000 |
|
int |
Тайм-аут на MQ GET, в мс. В течение данного времени MQ при выполнении GET ожидает ответ. По истечении данного периода поток возьмет следующее сообщение в очереди запросов и будет проверять наличие ответа для него. Значение = 0 приведет к бесконечному ожиданию ответа, устанавливать не рекомендуется, так как может привести к остановке считывания ответов, если ответы не будут приходить длительное время. Остальные тайм-ауты при этом не сработают. Отрицательное значение приведет к считыванию (GET) без ожидания |
- |
100 |
|
String |
Задает очередь для считывания ответов в случае если не задано через |
- |
|
|
Boolean |
при включение флага игнорирует то, что задано в запросе в заголовке |
- |
false |
|
Boolean |
При включенном флаге производит вычитку ответа по CorrelId равному CorrelId запроса, а не MsgId запроса. |
- |
false |
Пример настроек sync-receiver
mq:
sync-receiver:
replyToMode: SHARED_SINGLE #SHARED #SHARED_SELECTOR #UNIQUE
selectorName: GWResponseSelector # для режима SHARED_SELECTOR
poolSize: 10
startDelay: 100
maxDelay: 300
maxProcessingTime: 35000
maxStopTime: 100000
receiveTimeout: 100
Тип mq.ConcurrentLimiterConfig#
Параметры ограничения одновременной обработки считанных сообщений:
Пол |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
Включает режим ограничения |
- |
false |
|
int |
Кол-во одновременно обрабатываемых сообщений после считывания |
- |
10 |
Пример настроек concurrent-limiter
mq:
concurrentLimiter:
enable: true
limitConcurrent: 10
Тип mq.RateLimiterConfig#
Параметры ограничения скорости обработки считанных сообщений:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
Включает режим ограничения |
- |
false |
|
Map<String, RateLimiterSetting> |
Map профилей настроек ограничений по скорости в срезе очередей |
- |
- |
Пример настроек rate-limiter
mq:
#настройка ограничения скорости считывания из входящих очередей
rate-limiter:
enable: true
settings:
default:
limitRefreshPeriod: 1000
limitForPeriod: 100
"[UB.TEST.QUEUE]":
limitRefreshPeriod: 1000
limitForPeriod: 10
"[UB.TEST.QUEUE.SYNC]":
limitRefreshPeriod: 1000
limitForPeriod: 50
Тип RateLimiterSettings#
Параметры настройки ограничения по скорости обработки сообщений после считывания:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
long |
Период обновления ограничения, мс |
- |
1000 |
|
int |
Ограничение для вызова метода обработки сообщения за |
- |
100 |
Тип СoncurrentLimiterSendConfig#
Параметры ограничения одновременной обработки синхронных вызовов:
Пол |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
Включает режим ограничения |
- |
false |
|
int |
Кол-во одновременно обрабатываемых синхронных вызовов |
- |
30 |
Пример настроек concurrentLimiterSend
mq:
concurrentLimiterSend:
enable: true
limitConcurrent: 30
Тип LimiterSyncCall#
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
включение ограничителя |
- |
false |
|
int |
Ограничение для синхронных вызовов |
- |
5000 |
Тип SslCertUpdate#
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
включение механизма обновления сертификатов |
- |
false |
|
String |
периодичность проверки изменения файлов хранилища сертификатов |
- |
30000ms |
|
int |
опускать Readiness-пробу на время выполнения обновления сертификатов |
- |
false |
|
int |
количество интервалов (сегментов распределения) |
- |
20 |
|
int |
Интервал обновления — время применения сертификатов для одного Pod Шлюза |
- |
2 |
|
int |
интервал на который округляется (в большую сторону) момент изменения файлов хранилищ ключей |
- |
10 |
|
String |
Дополнительная фиксированная временная задержка, чтобы при несинхронном изменении файлов ключей и сертификатов со стороны внешней системы хранения сертификатов исключить излишние повторы процедуры обновления. |
- |
30s |
Тип mq.OutboundMqConfiguration#
Параметры для исходящих в MQ сообщений:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
Правило выбора имени сервиса |
+ |
||
|
List<ServiceConfig> |
Список именованных маршрутов |
+ |
|
|
boolean |
Признак необходимости копировать заголовки из запроса (который пришел по gRPC) в ответ (который пришел из MQ). Работает только для sync-sp Шлюза. Применятся для всех сообщений |
- |
false |
|
Настройки копирования заголовков из запроса в ответ. Применятся для всех сообщений |
- |
||
|
enum |
Значение по-умолчанию для признака персистентности отправляемых в MQ сообщений. Может иметь значения PERSISTENT, NON_PERSISTENT. Если задан — Шлюз будет принудительно проставлять его в каждом отправляемом в MQ сообщении. Если не задан — персистентность будет определяться заголовками в сообщении. Может быть переопределено для конкретного сервиса в секции serviceList |
- |
Пример настройки секции outbound
mq:
outbound: # параметры для исходящих в MQ сообщений
defaultPersistence: NON_PERSISTENT # Значение персистентности по умолчанию
serviceName: # определение названия сервиса
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
serviceList: # список сервисов с их правилами
- serviceName: default # поведение по умолчанию
usrHeaders: #заполняет usr-заголовки перед отправкой в MQ
ReplyToQueueHeader:
- type: fromDestination # из назначения MQ-сообщения
value: 'queue' # очередь назначения
AnotherHeader2: # ключ заголовка
- type: fromBody
value: //RqUID
AnotherHeader3:
- type: fromConst
value: 'someValue'
- serviceName: Service1
overridePersistence: PERSISTENT # переопределение персистентности по умолчанию для конкретного сервиса
parent: default # родительский профиль (его правила тоже применятся)
usrHeadersExt: # Расширенное заполнение пользовательских заголовков в исходящем MQ сообщении
- name: custom1
valueFrom:
- type: fromExpression
value: "variables['cust1']"
variables:
cust1:
type: fromConst
value: thereiscust1
expr: "'const1' + value + 'const2'"
- name: ExtLogRqTm
valueFrom:
- type: fromConst
value: yyyy-MM-dd'T'HH:mm:ss.SSSx':00'
expr: "dateNow(value)"
- name: ExtLogPersistence
valueFrom:
- type: fromHeader
value: Persistence
expr: "value == '2' ? '1' : '0'" # получить значение Persistence в формате MQ (в ProtoMessage в формате JMS)
Тип mq.outbound.VariableService#
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
List<ExtractionRule> |
Список правил вычисления, применяются по порядку указания в списке до получения ненулевого значения |
+ |
|
String |
Дополнительное SpEL-преобразование для вычисленного значения |
- |
Тип mq.outbound.ServiceConfig#
Поле |
Тип |
Описание |
Обязательность |
Значение по умолчанию |
|---|---|---|---|---|
|
String |
Имя сервиса. Используется при поиске сервиса по вычисленному в |
+ |
|
|
enum |
Фильтр режима, для которого задан профиль. Значения: SYNC_SP, ASYNC, SYNC_SC. Используется в объединенных Шлюзах для исключения конфликтов по настройкам |
- |
|
|
Map<String, List<ExtractionRule>> |
Правила определения usr-заголовков, которые нужно проставить при отправке сообщения в MQ для этого маршрута. Полученные заголовки помещаются в поле |
- |
|
|
Настройки копирования заголовков из запроса в ответ |
- |
||
|
enum |
Переопределение значения по-умолчанию для признака персистентности отправляемых в MQ сообщений, для конкретного сервиса. Может иметь значения PERSISTENT, NON_PERSISTENT. Если задан — Шлюз будет для данного сервиса принудительно проставлять его в каждом отправляемом в MQ сообщении. Если не задан — персистентность будет определяться общим дефолтным значением, а если оно не задано, то заголовками в сообщении. |
- |
Тип SendQueues#
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
ConfigSendQueue |
Очередь по умолчанию для отправки синхронному поставщику |
- |
|
ConfigSendQueue |
Очередь по умолчанию для отправки синхронному потребителю |
- |
|
ConfigSendQueue |
Очередь по умолчанию для асинхронной отправки (при асинхроне нельзя разделить поставщика и потребителя), можно использовать, если асинхронная отправка предполагается только в адрес поставщика или только в адрес потребителя. Иначе использовать |
- |
Тип ParamQueue#
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
String |
Название очереди |
+ |
|
String |
режим (sync/async) |
- |
|
String |
режим (sc/sp) |
- |
|
String |
Имя внешней системы (для логирования) |
- |
Тип ConfigSendQueue#
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
String |
Имя очереди |
- |
|
String |
Имя системы |
- |
Блок routing#
Параметры маршрутизации входящих сообщений. Обязательный блок.
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Динамические настройки |
|---|---|---|---|---|---|
|
Правило выбора имени маршрута |
+ |
+ |
||
|
List<RouteConfig> |
Список именованных маршрутов |
+ |
+ |
Тип routing.VariableRoute#
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
String |
Имя переменной |
+ кроме секции routing.routeName (см. пример настройки блока routing в данном документе) |
|
List<ExtractionRule> |
Список правил вычисления |
+ |
|
String |
Дополнительное SpEL-преобразование для вычисленного значения |
- |
Тип routing.RouteConfig#
Описание маршрута:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Доступно в версии Шлюза |
|---|---|---|---|---|---|
|
String |
Имя маршрута. Используется при поиске маршрута по вычисленному в |
+ |
||
|
enum |
Фильтр режима, для которого задан профиль. Значения: ASYNC_SP, SYNC_SC, ASYNC_SC. Используется в объединенных Шлюзах для исключения конфликтов по настройкам. |
- |
||
|
String |
Тип транспорта, который будет вызван после получения сообщения из MQ (GRPC/HTTP) |
- |
GRPC |
|
|
Настройки HTTP-транспорта для текущего маршрута (если задан общий корневой блок настроек http, то будут применены настройки из него) |
- |
|||
|
Настройки копирования заголовков MQ из запроса в ответ (работает для HTTP-транспорта) |
- |
|||
|
Настройки преобразования сообщения для HTTP-транспорта (если задан общий корневой блок http, будут применены настройки из общего корневого блока transform) |
||||
|
Map<String,List<ExtractionRule>> |
Правила определения gRPC-заголовков, которые нужно проставить при вызове для этого маршрута |
- |
||
|
Map<String,List<ExtractionRule>> |
Правила определения system-заголовков, которые нужно проставить при вызове для этого маршрута. Полученные заголовки помещаются в поле systemHeaders у Proto-сообщения |
- |
||
|
Map<String,List<ExtractionRule>> |
Правила определения user-заголовков, которые нужно проставить при вызове для этого маршрута. Полученные заголовки помещаются в поле |
- |
||
|
String |
SpEL-выражение для определения имени вызываемого хоста. Может быть заполнено константой. Пример: |
+ |
||
|
List<VariableRoute> |
Переменные для вычисления маршрута |
- |
||
|
Map<String,String> |
Дополнительный блок для определения маршрута. Если блок не задан, маршрутизировать будет сразу по значению, вычисленному из |
- |
Тип CopyHeadersFromRequestSettings#
Настройки копирования заголовков из запроса в ответ:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
|---|---|---|---|---|
|
boolean |
Копировать все mqmd-заголовки из запроса в ответ |
- |
|
|
boolean |
Копировать все usr-заголовки из запроса в ответ |
- |
|
|
Map<String,List<ExtractionRule>> |
Правила определения usr-заголовков, которые нужно скопировать из запроса в ответ |
- |
|
|
Map<String,List<ExtractionRule>> |
Правила определения mqmd-заголовков, которые нужно скопировать из запроса в ответ |
- |
Пример настройки блока routing
routing:
routeName:
valueFrom: # 1) сначала из тела сообщения xPath'ом(local-name(/*)) получаем RouteName (в данном случае — корневой тег). Можно получать не fromBody, а из usr-заголовков fromRfh2Header(в value название заголовка) или fromConst(в value строковую константу)
- type: fromBody
value: local-name(/*)
routeList: # 2) далее по полученному на шаге 1 routeName ищется маршрут в списке routeList с таким именем. Если не найден, то берется маршрут с именем default, как в этом примере
- routeName: default
destinationExpression: variables['SCName'] + '-' + variables['ServiceName'] + '-' + variables['SPName'] # 4) после вычисления всех переменных, вычисляется название вызываемого сервиса через SpEL-выражение. variables здесь - Map с переменными, полученными на шаге 3
variables: # 3) Далее Шлюз получает переменные для вычисления названия сервиса, в который отправится сообщение
- name: ServiceName
valueFrom: # 3.1.1) переменная ServiceName получается из тела (fromBody) xPath'ом local-name(/*)
- type: fromBody
value: local-name(/*)
expr: value[0:len(value)-2] # 3.1.2) потом к тому, что вычислено на шаге 3.1.1, применяется SpEL-выражение. value здесь - то, что было получено на шаге 3.1.1. Параметр expr необязательный. Можно оставить value без изменений
- name: SCName # 3.2.1) переменная SCName получается сначала из usr-заголовка SCName. Если его нет или он пустой, то берется константа UFS
valueFrom:
- type: fromRfh2Header
value: SCName
- type: fromConst
value: UFS
expr: ("urn:systems:99-ufs"==toLower(value))?"ufsuko":value) # 3.2.2) Далее к тому, что вычислено на шаге 3.2.1 применяется SpEL-выражение. Здесь значение urn:systems:99-ufs заменяется на ufsuko
- name: SPName # 3.3.1) переменная SPName получается сначала из usr-заголовка SPName. Если его нет или он пустой, то получается из тела xPath'ом //SystemID
valueFrom:
- type: fromRfh2Header
value: SPName
- type: fromBody
value: //SystemID
expr: value+'-rs' # 3.3.3) Далее к тому, что вычислено на шаге 3.3.1, применяется SpEL-выражение. Здесь добавляется суффикс rs
destinations:
'UFS-srvGetServiceApplicationDetail-ASBS-rs': 127.0.0.1
Вариант без маршрутизации
routing:
routeList:
- routeName: default
destinationExpression: '"ufs-srvgetcard-ucs"'
Название сервиса, который в итоге был вызван Шлюзом, можно найти в системном журнале по ключевому слову authority.
Пример конфигурации с grpcHeaders, systemHeaders, userHeaders
routing:
routeName:
valueFrom:
- type: fromBody
value: local-name(/*)
expr:
routeList:
- routeName: default
grpcHeaders:
x-synapse-mgr:
- type: fromRfh2Header
value: 'Mgr'
userHeaders:
RqUID:
- type: fromBody
value: //RqUID
systemHeaders:
Expiry:
- type: fromConst
value: 100000
Блок tracing#
Настройки трассировки:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Динамические настройки |
|---|---|---|---|---|---|
|
Map<String,ExtractionRule> |
Список имен полей заголовков трассировки и правил их вычисления |
- |
+ |
|
|
List<ParamTracingHeaders> |
Списки правил заполнения заголовков трассировки в разрезе режимов. Используется в объединенных Шлюзах. |
- |
+ |
|
|
boolean |
Признак необходимости генерации заголовков трассировки x-b3-* |
- |
|
+ |
|
boolean |
Признак генерации заголовка x-b3-traceid 128-битного формата. Необходимо установить в случае, если Шлюз является первым компонентом в цепочке gRPC-вызовов для корректной работы механизма трассировки Istio |
- |
|
+ |
Тип ParamTracingHeaders#
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
enum |
Фильтр режима, для которого задан профиль. Значения: ASYNC_SP, SYNC_SC, ASYNC_SC. Используется в объединенных Шлюзах для исключения конфликтов по настройкам. |
+ |
|
Map<String, <ExtractionRule> |
Список имен полей заголовков трассировки и правил их вычисления |
+ |
Пример настройки блока tracing
tracing:
generateXB3Headers: true
generate128bitTraceId: true
tracingHeaders:
x-b3-traceid: #перезапишет сгенерированный. обрежется до 16 символов при выставленном generate128bitTraceId
- type: fromBody
value: '//RqUID'
x-synapse-bussinesserrorcode-bin:
- type: fromBody
value: './/*[local-name()=''RoutingSet'']/errorCode/text()'
x-synapse-rquid:
- {type: fromBody, value: //RqUID}
x-synapse-rqtm:
- {type: fromBody, value: //RqTm}
x-synapse-custom1:
- type: fromInnerXML #
value: "/*[local-name()='QueueMessage']/system"
innerPath: "/*[local-name()='SYSTEM']/*[local-name()='Operation']/*[local-name()='Type']"
x-synapse-custom2:
- type: fromExpression #
value: "variables['SCName'] + '-' + toLower(variables['ServiceName'][0:len(variables['ServiceName'])-2]) + '-' + variables['SPName'] + '-rq'"
variables:
SCName:
type: fromConst
value: consumer
SPName:
type: fromConst
value: provider
ServiceName:
type: fromExpression
value: "variables['OperName'] + 'RecursiveRq'"
variables:
OperName:
type: fromConst
value: SomeService
Блок logging#
Настройки журналирования:
Поле |
Тип |
Описание |
Обязательность |
По умолчанию |
Динамические настройки |
|---|---|---|---|---|---|
|
String |
позволяет изменить уровень логирования |
Блок validator#
Блок настроек validator задает настройки подключения внешнего валидатора. Блок может быть размещен в отдельном файле validator-secret.yml в артефакте типа Secret.
Поле |
Тип |
Описание |
Обязательность |
Default |
Динамические настройки |
|---|---|---|---|---|---|
|
boolean |
Включает (true) валидацию сообщений. |
- |
false |
+ |
|
boolean |
При включенной валидации (enabled: true), если данная настройка имеет значение false, то сообщения, для которых не задан профиль валидации будут считаться валидными. если данная настройка имеет значение true - то невалидными. |
- |
false |
+ |
|
boolean |
Определяет, как для ответов об ошибке валидации отправляемых в MQ будет задаваться заголовок MQMD.CorrelId. Если параметр имеет значение false, то в CorrelID будет записываться MsgId запроса (стандартный вариант). Если параметр имеет значение true, то в CorrelId ответа будет записываться CorrelId запроса. |
- |
false |
+ |
|
boolean |
Определяет, нужно ли логировать тело сообщения при вызове валидатора. |
- |
false |
+ |
|
Настройки клиента HTTP для вызова валидатора |
+ |
+ |
||
|
Правила определения профиля валидации |
+ |
+ |
||
|
List< ServiceConfig > |
Правила определения параметра path вызова валидатора для профилей настроек |
- |
+ |
Тип validator.VariableService#
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
|
List< ExtractionRule > |
Список правил вычисления, которые применяются по порядку указания в списке до получения ненулевого значения. |
+ |
|
|
String |
Дополнительное преобразование для вычисленного значения |
- |
Тип validator.ServiceConfig#
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
|
String |
Наименование профиля настроек |
+ |
|
|
String |
Выражение для вычисления значения path. Кроме переменных описанных в списке variables в pathExpression можно использовать три встроенных переменных: direction (принимает значения inbound для сообщений считанных из MQ, и outbound для сообщений отправляемых в MQ), workMode (принимает значение sync в синхронных вызовах, и async в асинхронных), msgType (принимает значение rq при обработке синхронных запросов, rs при обработке синхронных ответов и "_" (подчерк) при асинхронных вызовах) |
+ |
|
|
Map<String, List<ExtractionRule>> |
Список правил определения заголовков для добавления к вызову валидатора |
- |
|
|
List<VariableRoute> |
Список правил определения переменных для вычисления и подстановки в pathExpression. |
- |
Пример настройки блока validator
validator:
enabled: true
invalidateByDefault: false
replyByCorrelId: false
loggingBody: false
http:
client:
url: http://127.0.0.1:8787/check
timeout: 3000
serviceName: # правила определения схем для сообщений
valueFrom:
- type: fromRfh2Header
value: ServiceName
expr:
serviceList:
- serviceName: address
pathExpression: ServiceName
headers: # Заполняется, если требуется передать дополнительные заголовки для вставки в ответ.
RqUID:
- type: fromBody
value: //RqUID
# Matching values
valueJson: $..RQID
variables:
- name: ServiceName
valueFrom:
- type: fromConst
value: "/"
expr:
- serviceName: address1
pathExpression: ServiceName
headers: # Заполняется, если требуется передать дополнительные заголовки для вставки в ответ.
x-foo-first:
- type: fromConst
value: foo1
variables:
- name: ServiceName
valueFrom:
- type: fromConst
value: "/ping"
expr:
- serviceName: address2
pathExpression: ("/bar2")
- servicename: address3
pathExpression: ("/bar")
- servicename: address4
pathExpression: ("/"+ServiceName)
variables:
- name: ServiceName
valueFrom:
- type: fromConst
value: "bar"
expr:
- servicename: address5
pathExpression: ("/"+variables['direction']+"/"+variables['workMode']+"/"+variables['msgType']+"/"+ServiceName)
variables:
- name: ServiceName
valueFrom:
- type: fromConst
value: "bar"
expr:
- servicename: address6
headers: # Заполняется, если требуется передать дополнительные заголовки для вставки в ответ.
Content-Type:
- type: fromConst
value: 'application/json'
pathExpression: ("/"+variables['direction']+"/"+variables['workMode']+"/"+variables['msgType']+"/"+ServiceName)
variables:
- name: ServiceName
valueFrom:
- type: fromConst
value: "foo"
Блок audit#
Блок настроек audit задает настройки регистрации событий аудита. Доступно с версии 2.9
Поле |
Тип |
Описание |
Обязательность |
Default |
Динамические настройки |
|---|---|---|---|---|---|
|
boolean |
Включает (true) отправку сообщений в аудит |
— |
false |
— |
|
enum |
Тип транспорта для отправки событий в ТС Аудит |
— |
HTTP |
— |
|
String |
Путь для записи метамодели для транспорта = FILE |
+ (для transportType==FILE) |
— |
|
|
Настройки HTTP-транспорта |
+ (для transportType==HTTP) |
— |
Тип AuditHttp#
Настройки HTTP-транспорта для ТС Аудит
Поле |
Тип |
Описание |
Обязательность |
Default |
Динамические настройки |
|---|---|---|---|---|---|
|
Настройки веб-клиента для вызова ТС Аудит |
+ |
— |
||
|
String |
Путь к endpoint для отправки событий |
— |
/event |
— |
|
String |
Путь к endpoint для отправки метамодели |
— |
/metamodel |
— |
|
int |
Таймаут вызова ТС Аудит для отправки событий, миллисекунд |
— |
5000 |
— |
|
int |
Размер буфера событий для Retry отправки |
— |
3000 |
— |
|
Настройки повторной отправки событий в случае неуспешной попытки |
— |
— |
Тип RetryConfig#
Поле |
Тип |
Описание |
Обязательность |
Default |
Динамические настройки |
|---|---|---|---|---|---|
|
int |
Количество попыток повторной отправки события в случае ошибки |
— |
10 |
— |
audit:
enable: true
transportType: http
http:
client:
httpMethod: POST
url: http://хост:порт
eventPath: /event_endpoint
metamodelPath: /metamodel_endpoint
responseTimeout: 10000
maxBufferSize: 3000
retry:
attempts: 10
Блок cleanFDC#
Только для реализации Шлюза MQ на Golang
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
enable |
Boolean |
включение механизма очистки |
- |
false |
path |
String |
Путь по которому искать .FDC файлы. Настройка не влияет на то где файлы формируются. |
- |
Если задана |
maxFilesSize |
String |
Суммарный размер .FDC файлов, при превышении которого включается очистка. |
- |
50MB |
freePercent |
Int |
Сколько процентов от суммарного размера должно быть освобождено при очистке |
- |
80 |
period |
String |
Период сканирования |
- |
60s |
outdatedScanTime |
String |
Время запуска удаления устаревших файлов |
- |
01:00 |
maxAgeInDays |
Int |
возраст в днях при достижении которого файлы считаются устаревшими |
- |
7 |
retry: |
Настройка количества повторных попыток, если при попытке удаления файл был заблокирован. |
Тип RetryClean#
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
attempts |
Int |
количество попыток |
- |
3 |
waitDuration |
String |
интервал между попытками |
- |
500ms |
Блок parser#
Только для реализации Шлюза MQ на Golang
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
xml |
Настройка разбора XML-сообщений |
Тип XmlParserConfig#
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
skipDeclaration |
Boolean |
Пропуск XML- декларации |
- |
false |
Блок refresh#
Поле |
Тип |
Описание |
Обязательность |
Default |
|---|---|---|---|---|
settingsPeriodCheckUpdateFile |
String |
Величина интервала через который Шлюз проверяет файлы конфигурации, и если они изменились, выполняет обновление параметров, которые допускают динамическое изменение |
30s |
Общие типы#
Тип extractor.ExtractionRule#
Правила получения значений из сообщения. Представляет собой именованный список, в котором для каждого имени заголовка определяются:
Поле |
Тип |
Описание |
Обязательность |
|---|---|---|---|
|
Место, откуда необходимо получить значение параметра |
+ |
|
|
String |
Имя заголовка, константа или xPath-выражение для получения значения из тела. Для типа fromInnerXML определяет элемент в сообщении, в котором находится вложенный XML |
+ (для всех типов кроме |
|
String |
Для типа |
- |
|
String |
только для типа fromInnerXML — XPath для получения значения из вложенного XML |
- |
|
Map<String, List< ExtractionRule>> |
Для типа fromExpression — набор правил определения переменных, составляющих выражение |
- |
Настройки value и valueJson типа fromBody применяются только к сообщениям своего формата. Для сообщений другого формата настройка игнорируется. Если настройка задана для одного формата, но не задана для другого, то при обработке сообщения формата, для которого настройка не задана, будет возвращаться пустое значение. Например, настройка прописана для XML, но не прописана для JSON, тогда, при обработке сообщения формата JSON, будет получено пустое значение.
Правило value корректно извлекает значения из тела сообщения даже если тело сообщения представляет собой строку полностью экранированного XML.
Например сообщения:
<Root>
<RqUID>d6e3fd28ab2f4f51968c9c7423f99113</RqUID>
<Message>Какое-то сообщение</Message>
</Root>
и
<Root><RqUID>d6e3fd28ab2f4f51968c9c7423f99113</RqUID><Message>Какое-то сообщение</Message></Root>
дадут одинаковый результат.
Пример:
- type: fromBody
value: local-name(/*)
- type: fromRfh2Header
value: SCName
- type: fromConst
value: UFS
- type: fromRfh2Header
value: SPName
- type: fromBody
value: //SystemID
valueJson: $.SystemID
- type: fromInnerXML
value: "/*[local-name()='QueueMessage']/system"
innerPath: "/*[local-name()='SYSTEM']/*[local-name()='Operation']/*[local-name()='Type']"
- type: fromExpression
value: "variables['SCName'] + '-' + toLower(variables['ServiceName'][0:len(variables['ServiceName'])-2]) + '-' + variables['SPName'] + '-rq'"
variables:
SCName:
type: fromConst
value: consumer
SPName:
type: fromConst
value: provider
ServiceName:
type: fromExpression
value: "variables['OperName'] + 'RecursiveRq'"
variables:
OperName:
type: fromConst
value: SomeService
Тип extractor.ExtractionType#
Способ получения значения из сообщения:
Значение |
Описание |
|---|---|
|
Заголовки |
|
rfh-заголовки |
|
Тело сообщения (XML или JSON) |
|
Константа |
|
Из SPEL выражения |
|
Из вложенного (экранированного) XML |
|
Из назначения MQ-сообщения. Используется только в секции |
Часто встречающиеся проблемы и пути их устранения#
Информация о часто встречающихся проблемах и путях их решения — в разделе «Часто встречающиеся проблемы и пути их устранения» документа «Руководство по системному администрированию».