Rabbitmq topic exchange routes messages according to rules. Note that the topic expression used here is not a regular expression. In the Getting Started tutorial [click the link], we briefly describe how to write rules:
* (STAR) can substitute for exactly one word.
# (Hash) can substitute for zero or more words.
The above statement is easy to misunderstand. I will try to explain it:
. Used to divide the routing key into several parts)
* Match a complete Part
# Match one or more parts
The conclusion above is very simple. We can use the client to create different exchanges to verify this point. Another simpler method is to find the implementation logic of rabbitmq, which is easy to find as the name suggests .. \ rabbitmq-server-2.8.7 \ SRC \ rabbit_exchange_type_topic.erl file, the latest version of the code this part of the logic has been written more complex, back to the earlier version of rabbitmq-server-2.2.0 \ SRC \ rabbit_exchange_type_topic.erl, this is much clearer, check its code:
split_topic_key(Key) -> string:tokens(binary_to_list(Key), ".").topic_matches(PatternKey, RoutingKey) -> P = split_topic_key(PatternKey), R = split_topic_key(RoutingKey), topic_matches1(P, R).topic_matches1(["#"], _R) -> true;topic_matches1(["#" | PTail], R) -> last_topic_match(PTail, [], lists:reverse(R));topic_matches1([], []) -> true;topic_matches1(["*" | PatRest], [_ | ValRest]) -> topic_matches1(PatRest, ValRest);topic_matches1([PatElement | PatRest], [ValElement | ValRest]) when PatElement == ValElement -> topic_matches1(PatRest, ValRest);topic_matches1(_, _) -> false.last_topic_match(P, R, []) -> topic_matches1(P, R);last_topic_match(P, R, [BacktrackNext | BacktrackList]) -> topic_matches1(P, R) or last_topic_match(P, [BacktrackNext | R], BacktrackList).
Check the code. Everything is clear. Check the following test code: rabbit_exchange_type_topic: topic_matches.
Eshell V5.9 (abort with ^G)1> rabbit_exchange_type_topic:topic_matches(<<"a.#">>,<<"a.b">>).true2> rabbit_exchange_type_topic:topic_matches(<<"a.#">>,<<"a.bc">>).true3> rabbit_exchange_type_topic:topic_matches(<<"a.#">>,<<"a.bc.bc">>).true4> rabbit_exchange_type_topic:topic_matches(<<"a.#">>,<<"a1.b">>).false5> rabbit_exchange_type_topic:topic_matches(<<"b.a.#">>,<<"a1.b">>).false6> rabbit_exchange_type_topic:topic_matches(<<"b.a.#">>,<<"a.b">>).false7> rabbit_exchange_type_topic:topic_matches(<<"a.*">>,<<"a.b">>).true8> rabbit_exchange_type_topic:topic_matches(<<"a.*">>,<<"a.bc">>).true9> rabbit_exchange_type_topic:topic_matches(<<"a.a*">>,<<"a.bc">>).false10> rabbit_exchange_type_topic:topic_matches(<<"a.a*">>,<<"a.ac">>).false11> rabbit_exchange_type_topic:topic_matches(<<"a.a#">>,<<"a.ac">>).false12> rabbit_exchange_type_topic:topic_matches(<<"a.*">>,<<"a.bc.a">>).false13> rabbit_exchange_type_topic:topic_matches(<<"a.*.*">>,<<"a.bc.a">>).true14> rabbit_exchange_type_topic:topic_matches(<<"a.b*">>,<<"a.bc">>).false15> rabbit_exchange_type_topic:topic_matches(<<"a.*.*">>,<<"a.b*">>).false16> rabbit_exchange_type_topic:topic_matches(<<"a.*">>,<<"a.b*">>).true17> rabbit_exchange_type_topic:topic_matches(<<"a.b*">>,<<"a.b*">>).true18> rabbit_exchange_type_topic:topic_matches(<<"*.a">>,<<"a.a">>).true19> rabbit_exchange_type_topic:topic_matches(<<"*.a">>,<<"a.a.b">>).false20> rabbit_exchange_type_topic:topic_matches(<<"*.a.b">>,<<"a.a">>).false21> rabbit_exchange_type_topic:topic_matches(<<"#.a">>,<<"a.a.b">>).false22> rabbit_exchange_type_topic:topic_matches(<<"#.a">>,<<"a.a">>).true23> rabbit_exchange_type_topic:topic_matches(<<"#.a">>,<<"a.a.a">>).true24>24> rabbit_exchange_type_topic:topic_matches(<<"a.*.a">>,<<"a.a.a">>).true25> rabbit_exchange_type_topic:topic_matches(<<"a.*a.a">>,<<"a.aa.a">>).false26>26> rabbit_exchange_type_topic:topic_matches(<<"*">>,<<"a.aa.a">>).false27> rabbit_exchange_type_topic:topic_matches(<<"*">>,<<"a">>).true28> rabbit_exchange_type_topic:topic_matches(<<"a.*.#">>,<<"a.b">>).true29> rabbit_exchange_type_topic:topic_matches(<<"a.*.#">>,<<"a.b.c">>).true30> rabbit_exchange_type_topic:topic_matches(<<"*.#">>,<<"a.b.c">>).true31> rabbit_exchange_type_topic:topic_matches(<<"*.#">>,<<"a.b.c">>).true32>
Check whether you really understand the problem and try to answer the last several abnormal questions in the tutorials document:
- Will "*" binding catch a message sent with an empty routing key?
- Will "#. *" catch a message with a string "..." as a key? Will it catch a message with a single word key?
- How different is "A. *. #" from ".#"?
At last, I have a thumbnail. Good night!