Hello, I'm using Apache Artemis as MQTT broker for our IOT projects. It's a clean Artemis installation of version 1.5.1., on a server (CentOS 7) which has 2 vCPU, 8 GB of RAM (4GB of Heap Space dedicated to Artemis) and 50 GB of SSD data disk. After the installation of artemis Broker we started to test it with about 10-15 clients constantly connected, 150 subscribed topics and an average of 2 messages per minute per client. I think these are not huge numbers, right? For the few days after the installation, all was good and the broker worked perfectly: it was fast and reliable. But day by day performances have decreased and after about 10 days of usage it is became almost unusable: due to resources consumption. The following is my "top" situation on the server:
top - 08:59:50 up 2 days, 22:09, 1 user, load average: 2.56, 2.88, 3.00 Tasks: 92 total, 1 running, 91 sleeping, 0 stopped, 0 zombie %Cpu(s): 99.5 us, 0.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 7747288 total, 290968 free, 4697976 used, 2758344 buff/cache KiB Swap: 0 total, 0 free, 0 used. 2734768 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4352 mqtt 20 0 7043380 4.348g 15192 S 200.0 58.9 6153:54 java 1 root 20 0 128096 5176 2420 S 0.0 0.1 0:04.01 systemd Now I can see the broker starting to page on disk almost always. For sure it's a wrong configuration of ours. Currently, it seems that very old address/queue (and the related retained messages) are always kept, making memory and cpu consuption growing more and more. And even after a restart, the broker takes so much to get up. Before to become reachable, it starts to make many management operations like, for example, retrieve data from paging, etc.. But I also see the broker that starts to register old topics and queues we don't need. How to clean them? How to make a topic/queue expire? Inside my broker.xml I did set up the parameter last-value-queue=true, thinking that this was the problem ....but it doesn't solve. Or better: probably it's me that I've not understood the correct meaning of the parameter. I did check also the clients' parameters when they connect to the broker, to be sure they don't set, for example, clean-session = false (saying the broker to keep all messages also when a client disconnects). But they make it in the right way. The only thing is that they don't specify a client-id. They connect by using a username/password and certificate (over tls). So, every time a client connects, Artemis automatically provide a random client-id for it (if I understood well). Attached you can find my broker.xml configuration file: it's pretty much the same default created during the installation procedure, but for the acceptors (which I've customized for my MQTT purpose) and the addition of parameter last-value-queue = true inside the address-setting section. Please: some of you could help me? How I have to configure my broker instance to understand and solve these performance issues? Thanks in advance Francesco ________________________________ Ce message, ainsi que tous les fichiers joints à ce message, peuvent contenir des informations sensibles et/ ou confidentielles ne devant pas être divulguées. Si vous n'êtes pas le destinataire de ce message (ou que vous recevez ce message par erreur), nous vous remercions de le notifier immédiatement à son expéditeur, et de détruire ce message. Toute copie, divulgation, modification, utilisation ou diffusion, non autorisée, directe ou indirecte, de tout ou partie de ce message, est strictement interdite. This e-mail, and any document attached hereby, may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized, direct or indirect, copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.
<?xml version='1.0'?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd"> <jms xmlns="urn:activemq:jms"> <queue name="DLQ"/> <queue name="ExpiryQueue"/> </jms> <core xmlns="urn:activemq:core"> <name>0.0.0.0</name> <!-- <persistence-enabled>true</persistence-enabled> --> <persistence-enabled>true</persistence-enabled> <!-- this could be ASYNCIO or NIO --> <journal-type>ASYNCIO</journal-type> <paging-directory>./data/paging</paging-directory> <bindings-directory>./data/bindings</bindings-directory> <journal-directory>./data/journal</journal-directory> <large-messages-directory>./data/large-messages</large-messages-directory> <journal-datasync>true</journal-datasync> <journal-min-files>2</journal-min-files> <journal-pool-files>-1</journal-pool-files> <!-- You can specify the NIC you want to use to verify if the network <network-check-NIC>theNickName</network-check-NIC> --> <!-- Use this to use an HTTP server to validate the network <network-check-URL-list>http://www.apache.org</network-check-URL-list> --> <!-- <network-check-period>10000</network-check-period> --> <!-- <network-check-timeout>1000</network-check-timeout> --> <!-- this is a comma separated list, no spaces, just DNS or IPs it should accept IPV6 Warning: Make sure you understand your network topology as this is meant to validate if your network is valid. Using IPs that could eventually disappear or be partially visible may defeat the purpose. You can use a list of multiple IPs, and if any successful ping will make the server OK to continue running --> <!-- <network-check-list>10.0.0.1</network-check-list> --> <!-- use this to customize the ping used for ipv4 addresses --> <!-- <network-check-ping-command>ping -c 1 -t %d %s</network-check-ping-command> --> <!-- use this to customize the ping used for ipv6 addresses --> <!-- <network-check-ping6-command>ping6 -c 1 %2$s</network-check-ping6-command> --> <!-- This value was determined through a calculation. Your system could perform 1.91 writes per millisecond on the current journal configuration. That translates as a sync write every 524000 nanoseconds --> <journal-buffer-timeout>6468000</journal-buffer-timeout> <!-- how often we are looking for how many bytes are being used on the disk in ms --> <disk-scan-period>5000</disk-scan-period> <!-- once the disk hits this limit the system will block, or close the connection in certain protocols that won't support flow control. --> <max-disk-usage>90</max-disk-usage> <!-- the system will enter into page mode once you hit this limit. This is an estimate in bytes of how much the messages are using in memory --> <global-max-size>104857600</global-max-size> <acceptors> <!-- Acceptor for every supported protocol --> <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE</acceptor> <!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic.--> <!-- <acceptor name="amqp">tcp://0.0.0.0:5672?protocols=AMQP</acceptor> --> <!-- STOMP Acceptor. --> <!-- <acceptor name="stomp">tcp://0.0.0.0:61613?protocols=STOMP</acceptor> --> <!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. --> <!-- <acceptor name="hornetq">tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP</acceptor> --> <!-- MQTT Acceptor --> <!-- <acceptor name="mqtt">tcp://0.0.0.0:1883?protocols=MQTT</acceptor> --> <acceptor name="mqtt">tcp://172.16.2.5:1883?protocols=MQTT</acceptor> <acceptor name="mqtts">tcp://172.16.2.5:8883?protocols=MQTT;sslEnabled=true;needClientAuth=true;keyStorePath=/app/mqtt/activeMQ/brokers/eltbroker01/tls/brokerkeystore;keyStorePassword=changeit;trustStorePath=/app/mqtt/activeMQ/brokers/eltbroker01/tls/brokertruststore;trustStorePassword=changeit</acceptor> <acceptor name="mqtts2">tcp://172.16.2.5:8884?protocols=MQTT;sslEnabled=true;needClientAuth=false;keyStorePath=/app/mqtt/activeMQ/brokers/eltbroker01/tls/brokerkeystore;keyStorePassword=changeit;trustStorePath=/app/mqtt/activeMQ/brokers/eltbroker01/tls/brokertruststore;trustStorePassword=changeit</acceptor> </acceptors> <security-settings> <security-setting match="#"> <permission type="createNonDurableQueue" roles="mqtt"/> <permission type="deleteNonDurableQueue" roles="mqtt"/> <permission type="createDurableQueue" roles="mqtt"/> <permission type="deleteDurableQueue" roles="mqtt"/> <permission type="consume" roles="mqtt"/> <permission type="browse" roles="mqtt"/> <permission type="send" roles="mqtt"/> <!-- we need this otherwise ./artemis data imp wouldn't work --> <permission type="manage" roles="mqtt"/> </security-setting> </security-settings> <address-settings> <!--default for catch all--> <address-setting match="#"> <dead-letter-address>jms.queue.DLQ</dead-letter-address> <expiry-address>jms.queue.ExpiryQueue</expiry-address> <!-- <expiry-delay>3000</expiry-delay> --> <redelivery-delay>0</redelivery-delay> <!-- with -1 only the global-max-size is in use for limiting --> <max-size-bytes>-1</max-size-bytes> <message-counter-history-day-limit>10</message-counter-history-day-limit> <address-full-policy>PAGE</address-full-policy> <last-value-queue>true</last-value-queue> </address-setting> </address-settings> </core> </configuration>