Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add mqtt.max_connections per-node connection limit (backport #16367) (backport #16391)#16412

Merged
michaelklishin merged 7 commits into
v4.2.xfrom
mergify/bp/v4.2.x/pr-16391
May 13, 2026
Merged

Add mqtt.max_connections per-node connection limit (backport #16367) (backport #16391)#16412
michaelklishin merged 7 commits into
v4.2.xfrom
mergify/bp/v4.2.x/pr-16391

Conversation

@mergify
Copy link
Copy Markdown

@mergify mergify Bot commented May 13, 2026

Closes #16347 (partial - adds mqtt.max_connections).

What this PR does

Adds mqtt.max_connections, a per-node connection limit for the MQTT plugin. When the limit is reached, the broker sends a CONNACK with return code not_authorized (MQTT 3.x/4) or reason code quota_exceeded (MQTT 5) and closes the connection.

How it works

The limit is checked in rabbit_mqtt_processor:process_connect/5 as the first step in the CONNECT packet handler, before authentication. It does not operate at the Ranch transport layer, so the TCP listen queue is unaffected and Ranch continues accepting connections normally.

The active connection count uses ets:info(persistent_term:get(?PG_SCOPE), size). The MQTT plugin creates a node-local PG scope in rabbit_mqtt_sup; each connection joins it via pg:join/3 in register_client_id/4, using {VHost, ClientId} as the group key. Since the MQTT spec requires unique client IDs per vhost, which RabbitMQ enforces, each group has exactly one member. The PG scope ETS table therefore has one row per active connection node-wide, covering all listeners and transports (plain TCP, TLS, and Web MQTT). ets:info/2 reads this count in O(1) - important given that MQTT nodes can host a very large number of connections.

The check runs before register_client_id/4, so the current connection is not yet counted; the limit comparison is >= max_connections.

Configuration

mqtt.max_connections = 1000

The default is infinity (no limit). The setting accepts a non-negative integer or infinity.

Testing

Adds node_connection_limit to the limit group in auth_SUITE. The test sets the limit to 0 via RPC so the first CONNECT attempt is rejected, covering both MQTT v4 and v5 via the existing expected_connection_limit_error/1 helper.


This is an automatic backport of pull request #16367 done by [Mergify](https://mergify.com).
This is an automatic backport of pull request #16391 done by [Mergify](https://mergify.com).

lukebakken and others added 7 commits May 13, 2026 01:26
Add the `mqtt.max_connections` configuration key, which sets a
node-wide limit on the number of concurrent MQTT connections.

The limit is checked in `rabbit_mqtt_processor:process_connect/5`
as the first step in the CONNECT packet handler, before
authentication. When exceeded, the broker returns a CONNACK with
reason code `quota_exceeded` (MQTT 5) or return code
`not_authorized` (MQTT 3.x/4).

The active connection count is obtained via
`ets:info(persistent_term:get(?PG_SCOPE), size)`. The MQTT plugin
creates a node-local PG scope in `rabbit_mqtt_sup`; each connection
joins it via `pg:join/3` in `register_client_id/4`, using
`{VHost, ClientId}` as the group key. Since the MQTT spec requires
unique client IDs per vhost, which RabbitMQ enforces, each group
has exactly one member. The PG scope ETS table therefore has one
row per active connection node-wide, covering all listeners and
transports (plain TCP, TLS, and Web MQTT). `ets:info/2` reads this
count in O(1) - important given that MQTT nodes can host a very
large number of connections.

The check runs before `register_client_id/4`, so the current
connection is not yet counted; the limit comparison is `>= Limit`.

When `mqtt.max_connections` is absent, `application:get_env/3`
returns `infinity` and no check is performed.

A `node_connection_limit` test is added to the `limit` group in
`auth_SUITE`.

(cherry picked from commit 9c1683a)
(cherry picked from commit ef7427a)
(cherry picked from commit 7613f9a)
(cherry picked from commit a8202d3)
(cherry picked from commit a4d56ad)
(cherry picked from commit d098468)
(cherry picked from commit eff88a3)
(cherry picked from commit bd7ed74)
(cherry picked from commit 1291866)
(cherry picked from commit 20e16eb)
…nel_closed`

This change reduces the polling and message generation frequency
to what the sibling tests use.

(cherry picked from commit 52b9a29)
`rabbit_mqtt_keepalive:handle/2` returns `{error, _}` when
`inet:getstat/2` fails on an already-closed socket (typically
`einval`). Route these through `network_error/2` so the pending
`{tcp_closed, Socket}` message handles teardown cleanly, instead
of crashing the reader which in turn makes
the test fail.

(cherry picked from commit ee8fedd)
(cherry picked from commit 54b6566)
@michaelklishin michaelklishin added this to the 4.2.7 milestone May 13, 2026
@michaelklishin michaelklishin merged commit 59858cf into v4.2.x May 13, 2026
300 checks passed
@michaelklishin michaelklishin deleted the mergify/bp/v4.2.x/pr-16391 branch May 13, 2026 03:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants