Skip to content

Commit 3900768

Browse files
authored
Merge pull request #4 from jbertram/andy-master
Broker protection content
2 parents 355681a + 4422286 commit 3900768

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# Protecting the Broker in AMQ 7
2+
3+
This worksheet covers some broker protection features in the AMQ 7 broker. By the end of this worksheet you should know:
4+
5+
1. How to configure the behavior of the broker when an address becomes "full"
6+
2. How to use resource-limit-settings to restrict how many queues and/or connections a specific user can create
7+
3. How to configure an acceptor to limit the number of allowed TCP connections
8+
9+
## Address-full policies
10+
11+
As messages accumulate in the broker there is a chance that the JVM could run out of heap space. There are several options to deal with this possibility which can be configured in a matching `<address-setting>`:
12+
13+
* **max-size-bytes** How large an address can be before it's considered "full". The size of an address is calculated by summing the sizes of all the queues bound to the address. This includes durable, non-durable, statically created, and dynamically (i.e. auto) created queues. Note, this is done on a per-address basis so even though the `match` of the `<address-setting>` may be `#` the `max-size-bytes` applies to each individual address and not every matching address as a whole.
14+
* **address-full-policy** What to do when the address becomes full. Options are:
15+
* **PAGE** messages will be stored on disk
16+
* **DROP** messages will be silently dropped (i.e. deleted)
17+
* **FAIL** messages will be dropped and the relevant producer will receive an error
18+
* **BLOCK** relevant producer will be blocked from sending additional messages; only clients which support flow-control (i.e. core JMS, AMQP) will block
19+
20+
Aside from the per-address limits there are also global limits:
21+
22+
* **global-max-size** When all the message data in the broker reaches this limit then all addresses will apply their respective `<address-full-policy>`. Measured in bytes; supports byte notation (e.g. Mb, GB, kb, etc.). Defaults to Xmx/2.
23+
* **max-disk-usage** When disk utilization reaches this percentage (for any reason) then all clients supporting flow control will be blocked and those that don't will be disconnected.
24+
25+
These are the parts of the default configuration relevant to this discussion:
26+
27+
```xml
28+
<max-disk-usage>90</max-disk-usage>
29+
30+
<global-max-size>100Mb</global-max-size>
31+
32+
<address-setting match="#">
33+
<dead-letter-address>DLQ</dead-letter-address>
34+
<expiry-address>ExpiryQueue</expiry-address>
35+
<redelivery-delay>0</redelivery-delay>
36+
<!-- with -1 only the global-max-size is in use for limiting -->
37+
<max-size-bytes>-1</max-size-bytes>
38+
<message-counter-history-day-limit>10</message-counter-history-day-limit>
39+
<address-full-policy>PAGE</address-full-policy>
40+
<auto-create-queues>true</auto-create-queues>
41+
<auto-create-addresses>true</auto-create-addresses>
42+
<auto-create-jms-queues>true</auto-create-jms-queues>
43+
<auto-create-jms-topics>true</auto-create-jms-topics>
44+
</address-setting>
45+
```
46+
47+
### Hands on
48+
49+
Create a fresh broker instance:
50+
51+
```
52+
$ <AMQ_HOME>/bin/artemis create --user <myuser> --password <mypassword> --role admin --require-login <AMQ_HOME>/instances/myprotectedbroker
53+
```
54+
55+
Open `AMQ_INSTANCE/etc/broker.xml` and change `<max-disk-usage>` as the default value (i.e. 90) can inadvertently trigger blocking if your disk is close to full:
56+
57+
```xml
58+
<max-disk-usage>100</max-disk-usage>
59+
```
60+
61+
Then change the `<address-full-policy>` for `<address-setting match="#">` to:
62+
63+
```xml
64+
<address-full-policy>BLOCK</address-full-policy>
65+
```
66+
67+
And also change the `<max-size-bytes>` to:
68+
69+
```xml
70+
<max-size-bytes>1MB</max-size-bytes>
71+
```
72+
73+
Now send messages to the broker:
74+
75+
```
76+
$ <AMQ_INSTANCE>/bin/artemis producer --user <myuser> --password <mypassword> --message-size 1050
77+
```
78+
79+
The producer should block with this:
80+
81+
```
82+
AMQ212054: Destination address=TEST is blocked. If the system is configured to block make sure you consume messages on this configuration.
83+
```
84+
85+
Kill the producer (e.g. using Ctrl-C), and consume all the messages:
86+
87+
```
88+
$ <AMQ_INSTANCE>/bin/artemis consumer --user <myuser> --password <mypassword> --receive-timeout 1000 --break-on-null
89+
```
90+
91+
Check the AMQ 7 log and you'll see where the broker blocked and unblocked during the exercise.
92+
93+
## Resource limits
94+
95+
Broker administrators may be concerned with how many connections or queues a particular user is allowed to create. This can be configured via `<resource-limit-settings>`, e.g.:
96+
97+
```xml
98+
<resource-limit-settings>
99+
<resource-limit-setting match="myuser">
100+
<max-queues>100</max-queues>
101+
<max-connections>10</max-connections>
102+
</resource-limit-setting>
103+
</resource-limit-settings>
104+
```
105+
106+
The `match` attribute on `<resource-limit-setting>` matches a username. Wildcards are not supported on this match. The `<max-queues>` is how many queues the user is allowed to create either manually or via auto-creation. The `<max-connections>` is how many connections the user is allowed to create.
107+
108+
## Hands on
109+
110+
Add this to your `AMQ_INSTANCE/etc/broker.xml`:
111+
112+
```xml
113+
<resource-limit-settings>
114+
<resource-limit-setting match="myuser">
115+
<max-queues>0</max-queues>
116+
</resource-limit-setting>
117+
</resource-limit-settings>
118+
```
119+
120+
Restart the broker (because `<resource-limit-settings>` is not automatically picked up when changed at runtime) and try to send messages:
121+
122+
```
123+
$ <AMQ_INSTANCE>/bin/artemis producer --user <myuser> --password <mypassword>
124+
```
125+
126+
This should fail since the producer will attempt to create the queue "TEST" by default:
127+
128+
```
129+
javax.jms.JMSException: AMQ119111: Too many queues created by user '<myuser>'. Queues allowed: 0.
130+
```
131+
132+
Now change the `<resource-limit-settings>`:
133+
134+
```xml
135+
<resource-limit-settings>
136+
<resource-limit-setting match="myuser">
137+
<max-queues>10</max-queues>
138+
<max-connections>3</max-connections>
139+
</resource-limit-setting>
140+
</resource-limit-settings>
141+
```
142+
143+
Run a consumer with 2 threads. Note, even though there's just 2 threads the core JMS client will actually create 3 core sessions - 1 for the JMS connection and 1 each for the JMS sessions (1 per thread) for a total of 3.
144+
145+
```
146+
$ <AMQ_INSTANCE>/bin/artemis consumer --user <myuser> --password <mypassword> --threads 2 --receive-timeout 100 --break-on-null
147+
```
148+
149+
This will run without problems. However, a consumer with 3 threads (i.e. 4 core sessions) will fail:
150+
151+
```
152+
$ <AMQ_INSTANCE>/bin/artemis consumer --user <myuser> --password <mypassword> --threads 3 --receive-timeout 100 --break-on-null
153+
```
154+
155+
Here's the output:
156+
157+
```
158+
javax.jms.JMSException: AMQ119110: Too many sessions for user '<myuser>'. Sessions allowed: 3.
159+
```
160+
161+
## Limiting Connections on an Acceptor
162+
163+
Instead of limiting connections on a user-by-user basis you can also apply a global limit on connections to an acceptor using the `connectionsAllowed` URL property.
164+
165+
### Hands on
166+
167+
Stop your broker instance, remove the `<resource-limit-settings>`, and change the `artemis` acceptor to this (adding `;connectionsAllowed=1` to the end):
168+
169+
```xml
170+
<acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;connectionsAllowed=1</acceptor>
171+
```
172+
173+
Restart the broker and connect a consumer:
174+
175+
```
176+
$ <AMQ_INSTANCE>/bin/artemis consumer --user myuser --password mypass
177+
```
178+
179+
This will succeed. Note, even though the consumer is creating multiple core sessions it's only using a single TCP connection.
180+
181+
Connect another consumer:
182+
183+
```
184+
$ <AMQ_INSTANCE>/bin/artemis consumer --user myuser --password mypass
185+
```
186+
187+
This will fail after a bit and ask you for a working URL. The broker will report something like this:
188+
189+
```
190+
AMQ222206: Connection limit of 1 reached. Refusing connection from /127.0.0.1:57918
191+
```
192+
193+
The broker here is simply closing the TCP connection which may result in different behavior in the different supported clients.

0 commit comments

Comments
 (0)