【原创】RabbitMQ 之 mandatory
1.什么情况会导致 blackholed?
两种情况:
- 声明 exchange 后未绑定任何 queue ,此时发送到该 exchange 上的 message 均被 blackholed ;
- 声明 exchange 后绑定了 queue ,但发送到该 exchange 上的 message 所使用的 routing_key 不匹配任何 binding_key ,则 blackholed 。
决定 message 将被如何处理,是被 exchange 直接丢弃还是由其发回给 producer (Basic.Return+Content-Header+Content-Body)。
3.mandatory 和 Publisher confirm 机制的区别?
Publisher confirm 机制是用来确认 message 的可靠投递,mandatory 参数是用来确保在 queue 不存在的情况下,message 不会被 blackholed 。
queue 存在时,开启 mandatory 的情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
[warn] evsignal_init: socketpair: No error drive_machine: [conn_init] --- in TCP 3-way connecting!
drive_machine: [conn_connecting] --- connection timeout 1 time on socket(6040)
drive_machine: [conn_connected] --- connected on socket(6040) 6040: conn_state change connected ==> snd_protocol_header --> Send Protocol.Header!
6040: conn_state change snd_protocol_header ==> rcv_connection_start_method <-- Recv Connection.Start Method frame!
6040: conn_state change rcv_connection_start_method ==> snd_connection_start_rsp_method --> Send Connection.Start-Ok Method frame!
6040: conn_state change snd_connection_start_rsp_method ==> rcv_connection_tune_method drive_machine: wait for Connection.Tune method another 10 seconds!!
<-- Recv Connection.Tune Method frame!
6040: conn_state change rcv_connection_tune_method ==> snd_connection_tune_rsp_method --> Send Connection.Tune-Ok Method frame!
6040: conn_state change snd_connection_tune_rsp_method ==> snd_connection_open_method --> Send Connection.Open Method frame!
6040: conn_state change snd_connection_open_method ==> rcv_connection_open_rsp_method <-- Recv Connection.Open-Ok Method frame!
6040: conn_state change rcv_connection_open_rsp_method ==> snd_channel_open_method --> Send Channel.Open Method frame!
6040: conn_state change snd_channel_open_method ==> rcv_channel_open_rsp_method drive_machine: wait for Channel.Open-Ok method another 10 seconds!!
<-- Recv Channel.Open-Ok Method frame!
6040: conn_state change rcv_channel_open_rsp_method ==> idle drive_machine: [conn_idle] --- [PRODUCER]: Find something to send! 6040: conn_state change idle ==> snd_basic_publish_method --> Send Basic.Publish Method frame!
6040: conn_state change snd_basic_publish_method ==> snd_basic_content_header --> Send Content-Header frame!
6040: conn_state change snd_basic_content_header ==> snd_basic_content_body --> Send Content-Body frame!
6040: conn_state change snd_basic_content_body ==> idle drive_machine: [conn_idle] --- [PRODUCER]: Find nothing to send! wait for another 10 seconds
drive_machine: [conn_idle] --- [PRODUCER]: Find nothing to send! wait for another 10 seconds
|
queue 不存在时,开启 mandatory 的情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
[warn] evsignal_init: socketpair: No error drive_machine: [conn_init] --- in TCP 3-way connecting!
drive_machine: [conn_connecting] --- connection timeout 1 time on socket(8088)
drive_machine: [conn_connected] --- connected on socket(8088) 8088: conn_state change connected ==> snd_protocol_header --> Send Protocol.Header!
8088: conn_state change snd_protocol_header ==> rcv_connection_start_method drive_machine: wait for Connection.Start method another 10 seconds!!
<-- Recv Connection.Start Method frame!
8088: conn_state change rcv_connection_start_method ==> snd_connection_start_rsp_method --> Send Connection.Start-Ok Method frame!
8088: conn_state change snd_connection_start_rsp_method ==> rcv_connection_tune_method <-- Recv Connection.Tune Method frame!
8088: conn_state change rcv_connection_tune_method ==> snd_connection_tune_rsp_method --> Send Connection.Tune-Ok Method frame!
8088: conn_state change snd_connection_tune_rsp_method ==> snd_connection_open_method --> Send Connection.Open Method frame!
8088: conn_state change snd_connection_open_method ==> rcv_connection_open_rsp_method <-- Recv Connection.Open-Ok Method frame!
need to code something! 8088: conn_state change rcv_connection_open_rsp_method ==> snd_channel_open_method --> Send Channel.Open Method frame!
8088: conn_state change snd_channel_open_method ==> rcv_channel_open_rsp_method drive_machine: wait for Channel.Open-Ok method another 10 seconds!!
<-- Recv Channel.Open-Ok Method frame!
need to code something! 8088: conn_state change rcv_channel_open_rsp_method ==> idle drive_machine: [conn_idle] --- [PRODUCER]: Find something to send! 8088: conn_state change idle ==> snd_basic_publish_method --> Send Basic.Publish Method frame!
8088: conn_state change snd_basic_publish_method ==> snd_basic_content_header --> Send Content-Header frame!
8088: conn_state change snd_basic_content_header ==> snd_basic_content_body --> Send Content-Body frame!
8088: conn_state change snd_basic_content_body ==> rcv_basic_return_method <-- Recv Basic.Return Method frame!
### reply_code: 312, reply_text: NO_ROUTE, exchange=amq.direct, routing_key=test1
8088: conn_state change rcv_basic_return_method ==> idle drive_machine: [conn_idle] --- [PRODUCER]: Find nothing to send! wait for another 10 seconds
drive_machine: [conn_idle] --- [PRODUCER]: Find nothing to send! wait for another 10 seconds
|
该图显示了在 Basic.Publish 中设置 mandatory 为 true 。
该图中显示了当 queue 不存在时,服务器返回 Basic.Return + Content.Header + Content.Body 的内容。
下图为正常情况和异常情况。