KCML Message Queue Support Library, kmsgq.so
KCML performance metrics and message queues are both handled by a support library, kmsgq.so. The library takes messages from KCML and then uses AMQP to send them to a RabbitMQ server cluster.
Message queue support is available in KCML 07.16.00.23055 or later for AIX 7 and Linux 2.6.
By default message queue support is disabled. To enable message queue support, the location, and credentials, of the RabbitMQ server must be specified in /etc/kcml/msgq.conf Systems that have been executed as a Connection Manager Service may also define their own configuration in /etc/kcml/msgq.$SERVICE.conf. If /etc/kcml/msgq.$SERVICE.conf does not exist then the configuration will be loaded from /etc/kcml/msgq.conf.
For example :-
[global] server=mqserver.domain.com port=5672 vhost=virthost user=mquser passwd=mqpwd # Optional settings maxmsg=25000 reconnect_interval=10 connect_retries=4 flush_timeout=5
An optional maxmsg value can be used to limit the maximum number of messages that are buffered. The default limit is 50000 messages if this value is not specified.
If the RabbitMQ server uses SSL then the ssl value should be set in the configuration. The default port when using SSL is 5671.
[global] ... port=5671 ssl=1 ...
If the connection to the RabbitMQ server is interrupted then kmsgq.so will attempt to reconnect. The first attempt to reconnect will happen during a message being sent. If that fails then further reconnects are deferred for 30 seconds. Reconnecting will not be attempted after five consecutive failures. The number of reconnect attempts and the delay between them can be configured using the connect_retries & reconnect_interval values. For example, the above configuration would wait 10 seconds between each reconnect and then stop after 4 failed attempts.
Any unsent messages will be flushed when a KCML process is about to finish. By default kmsgq.so will wait upto 2 seconds for these messages to be sent. This time can be changed by using the flush_timeout value, so the above configuration example would increase this time to 5 seconds.
Named queues need to be defined. RabbitMQ identifies each queue using a Routing Key and an Exchange.
[queue:myQueue] exchange=myExchange routingkey=myRoutingKey persist=1
Like all configuration files in /etc/kcml, msgq.conf must have secure permissions, ie owned by the root super-user and only read access granted for groups and other users.
By default messages sent to a queue are non-persistent and the RabbitMQ server may drop them if no consumer is waiting on the routed queue. Persistent messages can be sent by setting the optional persist value to 1, as above. However, the RabbitMQ server may block while flushing buffered messages to disk.
Messages that are sent to the Unix System Log from kcml, and its utilies, can also be forwarded onto a message queue.
This is enabled by naming the queue in the optional [syslog] section to msgq.conf.
For example, the following would send syslog messages to the above queue:-
[syslog] queue=myQueue
The message that is sent to the queue is prefixed with "syslog=" then severity of the message. Then the same set of common identifiers that are shared with Performance Metrics are appended before the actual content of the message. For for example, running
WRITE LOG _LOG_INFORMATION, "Hello World" WRITE LOG _LOG_WARNING, "Warning" WRITE LOG _LOG_ERROR, "Severe Error"
would produce a RabbitMQ message of the form:-
syslog="INFO",host="centos6.kcml.com",user="fred",pid=6481,uuid="884a1fc0-65f9-4a53-9d8e-875172abf5b6",ts=1488216010824575,exe="kcml",service="MyApp",part=1015,msg="Hello World" syslog="WARNING",host="centos6.kcml.com",user="fred",pid=6481,uuid="884a1fc0-65f9-4a53-9d8e-875172abf5b6",ts=1488216010824876,exe="kcml",service="MyApp",part=1015,msg="Warning" syslog="ERROR",host="centos6.kcml.com",user="fred",pid=6481,uuid="884a1fc0-65f9-4a53-9d8e-875172abf5b6",ts=1488216010825172,exe="kcml",service="MyApp",part=1015,msg="Sever Error"
Setting the optional level value in the [syslog] section can be used to control what types of syslog messages are forwarded to the RabbitMQ server.
Valid values of the level key are:
| Level | Meaning |
|---|---|
| 0 | Allows all levels of syslog messages through |
| 1 | Filter out _LOG_INFORMATION messages. Allow _LOG_WARNING, _LOG_ERROR and audit log messages to be forwarded |
| 2 | Filter out _LOG_INFORMATION & _LOG_WARNING messages. Allow _LOG_ERROR and audit log messages to be forwarded |
| 3 | Filter out _LOG_INFORMATION, _LOG_WARNING and audit messages. Only _LOG_ERROR messages are forwarded |
So setting and running the above WRITE LOG statements
[syslog] queue=myQueue level=3
would result in only the "Sever Error" message being forwared to the RabbitMQ server.
There are built-in functions that allow the application to make use of message queues.
| Function | Description |
|---|---|
| rc = 'KCML_MessageQueue_IsEnabled("myQueue", BYREF errbuf$) | Tests if a named queue has been configured |
| 'KCML_MessageQueue_Send("myQueue", Message$) | Send a message to a named queue |
| 'KCML_RabbitMQ_Send("myRoutingKey", "myExchange", Message$, bPersist) | Sends a message directly to RabbitMQ, no named queue needs to be defined in msgq.conf |
| 'KCML_PerfMetric_Send("myQueue", "my.app.metric", StatsList$) | Sends a comma separated list of key=value pair performance metrics to the named queue. If the queue cannot be found then the queue used by KCML's own internal performance metrics is used. |
Given the configuration above, the example calls to 'KCML_MessageQueue_Send() & 'KCML_RabbitMQ_Send() are equivalent.
If 'KCML_MessageQueue_IsEnabled() returns FALSE, then an appropriate message is stored in the buffer passed as the second argument. Reasons for failure include:-
From build 24172 of the KCML 7.18 version of kmsgq.so load balancing & fail-over support is available.
Multiple RabbitMQ servers can be configured in msgq.conf by specifying more than one server value.
Eg:
[global] server=mqserver1.domain.com server=mqserver2.domain.com server=mqserver3.domain.com ... ... server=mqserverN.domain.com port=5672 vhost=virthost user=mquser passwd=mqpwd # Optional settings maxmsg=25000 reconnect_interval=10 connect_retries=4 flush_timeout=5
Each RabbitMQ server should be configured to listen on the same port, provide the same virtual host and authenticate with the same credentials.
The server for the initial connection is chosen randomly, thus providing a simple means of load balancing across all the RabbitMQ servers. If the connection to the RabbitMQ server is interrupted the next available server will be used. When the list of servers is exhausted and no connection has been made then kmsgq.so will go back to the start of the list. If no connection has been made after checking all servers, then kmsgq.so will defer further reconnection attempts by the time specified by the reconnect_interval value.