-
Notifications
You must be signed in to change notification settings - Fork 0
/
rabbitmqxi-lie-di-yi-pian.html
401 lines (361 loc) · 21.1 KB
/
rabbitmqxi-lie-di-yi-pian.html
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="CatsAction" />
<meta property="og:type" content="article" />
<meta name="twitter:card" content="summary">
<meta name="keywords" content="MQ, RabbitMQ, " />
<meta property="og:title" content="RabbitMQ系列第一篇 - 基本概念和常见工作模式"/>
<meta property="og:url" content="./rabbitmqxi-lie-di-yi-pian.html" />
<meta property="og:description" content="RabbitMQ特性 支持多种消息协议(Multi-protocols) 支持AMQP,STOMP,MQTT,HTTP和WebSockets 灵活的路由,多种交换类型(Flexible routing, multi-Exchange) 后面的工作模式小节会详细阐述RabbitMQ几种常见的模式 消息队列发送确认 多语言,跨语言编程(Go,Python,Java) RabbitMQ支持多种协议,只要实现特定协议的生产者和消费者,都能和RabbitMQ通信,对语言没有限制 集群及分布式部署 RabbitMQ支持集群和高可用,而且通过插件支持Federation特性。所谓Federation特性,是指有不同的用户和 vhosts的broker,而且各broker所属RabbitMQ版本可以不一致。名词含义见RabbitMQ基本概念 丰富的工具和插件 提供基于HTTP的管理和监控界面API RabbitMQ基本概念 Message 消息,消息是不具名的,它由消息头和消息体组成。 消息体是不透明的,而消息头则由一系列的可选属性组成, 这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等 …" />
<meta property="og:site_name" content="CatsAction's blog" />
<meta property="og:article:author" content="CatsAction" />
<meta property="og:article:published_time" content="2019-01-05T00:00:00+08:00" />
<meta name="twitter:title" content="RabbitMQ系列第一篇 - 基本概念和常见工作模式">
<meta name="twitter:description" content="RabbitMQ特性 支持多种消息协议(Multi-protocols) 支持AMQP,STOMP,MQTT,HTTP和WebSockets 灵活的路由,多种交换类型(Flexible routing, multi-Exchange) 后面的工作模式小节会详细阐述RabbitMQ几种常见的模式 消息队列发送确认 多语言,跨语言编程(Go,Python,Java) RabbitMQ支持多种协议,只要实现特定协议的生产者和消费者,都能和RabbitMQ通信,对语言没有限制 集群及分布式部署 RabbitMQ支持集群和高可用,而且通过插件支持Federation特性。所谓Federation特性,是指有不同的用户和 vhosts的broker,而且各broker所属RabbitMQ版本可以不一致。名词含义见RabbitMQ基本概念 丰富的工具和插件 提供基于HTTP的管理和监控界面API RabbitMQ基本概念 Message 消息,消息是不具名的,它由消息头和消息体组成。 消息体是不透明的,而消息头则由一系列的可选属性组成, 这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等 …">
<title>RabbitMQ系列第一篇 - 基本概念和常见工作模式 ·
CatsAction's blog
</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="./theme/image/logo.ico" />
<link rel="stylesheet" type="text/css" href="./theme/css/elegant.prod.css" media="screen">
<link rel="stylesheet" type="text/css" href="./theme/css/custom.css" media="screen">
</head>
<body>
<div id="content">
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="./"><span class=site-name>CatsAction's blog</span></a>
<div class="nav-collapse collapse">
<ul class="nav pull-right top-menu">
<li >
<a href=
.
>Home</a>
</li>
<li ><a href="./categories.html">Categories</a></li>
<li ><a href="./tags.html">Tags</a></li>
<li ><a href="./archives.html">Archives</a></li>
<li><form class="navbar-search" action="./search.html" onsubmit="return validateForm(this.elements['q'].value);"> <input type="text" class="search-query" placeholder="Search" name="q" id="tipue_search_input"></form></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span1"></div>
<div class="span10">
<article itemscope>
<div class="row-fluid">
<header class="page-header span10 offset2">
<h1>
<a href="./rabbitmqxi-lie-di-yi-pian.html">
RabbitMQ系列第一篇
<small class="subtitle">
基本概念和常见工作模式
</small>
</a>
</h1>
</header>
</div>
<div class="row-fluid">
<div class="span8 offset2 article-content">
<h4>RabbitMQ特性</h4>
<ol>
<li>
<p>支持多种消息协议(Multi-protocols)<br/>
支持AMQP,STOMP,MQTT,HTTP和WebSockets</p>
</li>
<li>
<p>灵活的路由,多种交换类型(Flexible routing, multi-Exchange)<br/>
后面的<a href="#rabbitmq-work-mode">工作模式</a>小节会详细阐述RabbitMQ几种常见的模式</p>
</li>
<li>
<p>消息队列发送确认</p>
</li>
<li>
<p>多语言,跨语言编程(Go,Python,Java)<br/>
RabbitMQ支持多种协议,只要实现特定协议的生产者和消费者,都能和RabbitMQ通信,对语言没有限制</p>
</li>
<li>
<p>集群及分布式部署<br/>
RabbitMQ支持集群和高可用,而且通过插件支持Federation特性。所谓Federation特性,是指有不同的用户和
vhosts的broker,而且各broker所属RabbitMQ版本可以不一致。名词含义见<a href="#rabbitmq-concept">RabbitMQ基本概念</a></p>
</li>
<li>
<p>丰富的工具和插件</p>
</li>
<li>
<p>提供基于HTTP的管理和监控界面API</p>
</li>
</ol>
<h4><span id="rabbitmq-concept">RabbitMQ基本概念</span></h4>
<p><img alt="RabbitMQ内部结构" src="./images/rabbitmq.webp"></p>
<ol>
<li>
<p>Message<br/>
消息,消息是不具名的,它由消息头和消息体组成。 消息体是不透明的,而消息头则由一系列的可选属性组成,
这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。</p>
</li>
<li>
<p>Publisher<br/>
消息的生产者,也是一个向交换器发布消息的客户端应用程序。</p>
</li>
<li>
<p>Exchange<br/>
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。Exchange有四种类型:direct,fanout,topic,headers。
后面的<a href="#rabbitmq-work-mode">工作模式</a> 小节会针对四种类型单独分析。</p>
</li>
<li>
<p>Binding<br/>
绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。</p>
</li>
<li>
<p>Queue<br/>
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。</p>
</li>
<li>
<p>Connection<br/>
网络连接,比如一个TCP连接。</p>
</li>
<li>
<p>Channel<br/>
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP命令都是通过信道发出去的,
不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。</p>
</li>
<li>
<p>Consumer<br/>
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。</p>
</li>
<li>
<p>Virtual Host<br/>
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。
每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在连接时指定,RabbitMQ默认的vhost是/。</p>
</li>
<li>
<p>Broker<br/>
表示消息队列服务器实体。</p>
</li>
</ol>
<h4><span id="rabbitmq-work-mode">RabbitMQ工作模式</span></h4>
<p>1, simple模式</p>
<p><img alt="simple模式" src="./images/rabbitmq-simple-mode.webp"></p>
<p>创建队列时,需要指定一个Queue name(队列名),Publisher通过Queue name和Queue绑定。</p>
<p>2, work模式</p>
<p><img alt="work模式" src="./images/rabbitmq-work-mode.webp"></p>
<p>比模式1多了几个Consumer。需要指定队列名。其实模式1,2是一种特例,它们Exchange为""(默认的匿名Exchange)</p>
<p>3, publish/subscribe发布订阅(共享资源)</p>
<p><img alt="publish模式" src="./images/rabbitmq-publish-mode.webp"></p>
<p>上面的<em>X</em>指Exchange。Exchange type是fanout,Routing key是""。
通常不需要指定Queue name(匿名队列),由Exchange 根据Routing key确认分发到哪个Queue。
由于Routing key为空,所以这种模式消息会被分发到所有的Queue。通常由Consumer创建相应的Queue,并绑定到相应的Exchange。</p>
<p>4, routing模式</p>
<p><img alt="routing模式" src="./images/rabbitmq-route-mode.webp"></p>
<p>Exchange type为direct,Routing key不为空。和第3种模式相比,Routing key会指定一个字符串。
Exchange根据Routing key精确匹配,和对应Routing key绑定的Queue会收到相应消息。
如果一个消息的Routing key和任何Binding都不匹配,就会被丢弃,避免了Queue的拥塞。这也是提倡Consumer创建Binding的原因,
因为Consumer最清楚自己需要哪一种类的消息。</p>
<p>5, topic模式</p>
<p><img alt="topic模式" src="./images/rabbitmq-topic-mode.webp"></p>
<p>Exchange type为topic,Routing key支持模式匹配, 匹配规则为"*"匹配单个单词,"#"匹配多个单词。
Routing key以点分割单词,如"stock.usd.nyse"。<br/>
结合上图,Routing key被设置为"quick.orange.rabbit"的消息将被发到两个Queue。"quick.orange.fox"消息
将仅仅发送到第一个Queue,而"lazy.brown.fox"仅仅发送到第二个Queue。"lazy.pink.rabbit"虽然匹配第二个Queue
两次绑定,但是第二个Queue仍然只会收到一次。</p>
<p>6, headers模式</p>
<p><img alt="headers模式" src="./images/rabbitmq-headers-mode.png"></p>
<p>headers模式很像topic模式,只是基于headers代替Routing key来匹配Binding。如上图,x-match字段是必须的,它有
all和any两个值。all标识headers的其它字段都得匹配,any标识headers的其它字段至少匹配一个。header能基于integer或者hash构造,
而不仅仅是string。</p>
<p>7, rpc模式</p>
<p><img alt="rpc模式" src="./images/rabbitmq-rpc-mode.webp"></p>
<p>rpc模式严格说只是其他模式的应用。如上图,C端利用模式2(当然也可以是其他模式)发起一个rpc调用,并通过设置replay_to参数,
告诉S端Response时的Queue name,然后S端就能通过模式2返回Response了。
基于RabbitMQ实现rpc调用需要解决如下问题:<br/></p>
<ul>
<li>S端执行过慢,或者负载过大时,支不支持扩展。利用模式2显然是能支持多S端工作的。</li>
<li>确保Request和Response仅仅一个消息。如图使用唯一Queue传递消息,能保证,但是代码层面扔需要做相应检查。</li>
<li>C端需要处理没有S运行情形。可以使用Publisher Confirm保证消息是否被正常分发。</li>
<li>C端需要处理调用超时无应答问题。</li>
<li>如果S端执行挤过异常,如何和C端确认传输的消息。</li>
<li>消息非法的检测。</li>
</ul>
<blockquote>
<p>综上,第1,2种模式可归为一类,它们使用未命名Exchange(默认""),Publisher直接将消息发送到Queue。他们分发消息的路由方式,是Publisher通过Queue name(队列名)
直接绑定Queue。这两种方式有很明显的缺点。首先它们Queue只有一个,不好扩展。其次消息分发不够灵活,如不能根据消息的主题决定分发方式。<br/>
第3,4,5模式可以归为一类,他们通过Exchange分发消息,不同的是Exchange type不同。这很好的解决了1,2种模式的缺点。<br/>
rpc模式严格上只是RabbitMQ其他模式的应用,下面的表对比了前5种模式。</p>
</blockquote>
<table>
<thead>
<tr>
<th align="left">模式名</th>
<th align="left">Exchange</th>
<th align="left">Routing key</th>
<th align="left">特点</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">simple模式</td>
<td align="left">""</td>
<td align="left">使用Queue name</td>
<td align="left">单一Queue,单一P,C</td>
</tr>
<tr>
<td align="left">worker模式</td>
<td align="left">""</td>
<td align="left">使用Queue name</td>
<td align="left">多个worker</td>
</tr>
<tr>
<td align="left">publish/subscribe模式</td>
<td align="left">type值为fanout</td>
<td align="left">""</td>
<td align="left">需要绑定Exchange和Queue,即创建Binding。多个Queue都会收到消息</td>
</tr>
<tr>
<td align="left">routing模式</td>
<td align="left">type值为direct</td>
<td align="left">需要指定</td>
<td align="left">精确匹配, 需要绑定Exchange和Queue,即创建Binding</td>
</tr>
<tr>
<td align="left">topic模式</td>
<td align="left">type值为topic</td>
<td align="left">需要指定</td>
<td align="left">模式匹配, 需要绑定Exchange和Queue,即创建Binding</td>
</tr>
</tbody>
</table>
<h4>RabbitMQ和Kafka对比</h4>
<ul>
<li>Kafka支持消息回溯,RabbitMQ不支持。</li>
<li>RabbitMQ支持消费者推,而Kafka不支持。</li>
<li>Kafka消息被有序的追加到每个主题消息分区。</li>
<li>Kafka消费者通过维护分区的偏移(或者说索引)来顺序的读出消息,然后消费消息。</li>
<li>rabbitMQ支持对消息的可靠的传递,支持事务,不支持批量的操作。</li>
<li>kafka具有高的吞吐量,内部采用消息的批量处理,zero-copy机制,数据的存储和获取是本地磁盘顺序批量操作,具有O(1)的复杂度,消息处理的效率很高。</li>
</ul>
<hr />
<aside>
<nav>
<ul class="articles-timeline">
<li class="previous-article">« <a href="./mysqlji-zhu-nei-mu-innodbcun-chu-yin-qing-du-shu-bi-ji.html"
title="Previous: 《MySQL技术内幕:InnoDB存储引擎》读书笔记">《MySQL技术内幕:InnoDB存储引擎》读书笔记</a></li>
<li class="next-article"><a href="./rabbitmqxi-lie-di-er-pian.html"
title="Next: RabbitMQ系列第二篇 - 如何保证消息可靠性">RabbitMQ系列第二篇 <small class="subtitle">如何保证消息可靠性</small></a> »</li>
</ul>
</nav>
</aside>
</div>
<section id="article-sidebar" class="span2">
<h4>Published</h4>
<time itemprop="dateCreated" datetime="2019-01-05T00:00:00+08:00"> 1
5, 2019</time>
<!---->
<h4>Category</h4>
<a class="category-link"
href="./categories.html#rabbitmq-ref">RabbitMQ</a>
<h4>Tags</h4>
<ul class="list-of-tags tags-in-article">
<li><a href="./tags.html#mq-ref">MQ
<span>3</span>
</a></li>
</ul>
<h4>Stay in Touch</h4>
<div id="sidebar-social-link">
<a href="mailto:catsaction@126.com" title="My Email Address" target="_blank" rel="nofollow noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Mail" role="img" viewBox="0 0 512 512"><rect width="512" height="512" rx="15%" fill="#328cff"/><path d="m250 186c-46 0-69 35-69 74 0 44 29 72 68 72 43 0 73-32 73-75 0-44-34-71-72-71zm-1-37c30 0 57 13 77 33 0-22 35-22 35 1v150c-1 10 10 16 16 9 25-25 54-128-14-187-64-56-149-47-195-15-48 33-79 107-49 175 33 76 126 99 182 76 28-12 41 26 12 39-45 19-168 17-225-82-38-68-36-185 67-248 78-46 182-33 244 32 66 69 62 197-2 246-28 23-71 1-71-32v-11c-20 20-47 32-77 32-57 0-108-51-108-108 0-58 51-110 108-110" fill="#fff"/></svg>
</a>
<a href="https://github.com/boyaziqi" title="catsaction Github Repository" target="_blank" rel="nofollow noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="GitHub" role="img" viewBox="0 0 512 512"><rect width="512" height="512" rx="15%" fill="#1B1817"/><path fill="#fff" d="M335 499c14 0 12 17 12 17H165s-2-17 12-17c13 0 16-6 16-12l-1-50c-71 16-86-28-86-28-12-30-28-37-28-37-24-16 1-16 1-16 26 2 40 26 40 26 22 39 59 28 74 22 2-17 9-28 16-35-57-6-116-28-116-126 0-28 10-51 26-69-3-6-11-32 3-67 0 0 21-7 70 26 42-12 86-12 128 0 49-33 70-26 70-26 14 35 6 61 3 67 16 18 26 41 26 69 0 98-60 120-117 126 10 8 18 24 18 48l-1 70c0 6 3 12 16 12z"/></svg>
</a>
<a href="https://www.linkedin.com/feed/" title="My LinkedIn" target="_blank" rel="nofollow noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="LinkedIn" role="img" viewBox="0 0 512 512" fill="#fff"><rect width="512" height="512" rx="15%" fill="#0077b5"/><circle cx="142" cy="138" r="37"/><path stroke="#fff" stroke-width="66" d="M244 194v198M142 194v198"/><path d="M276 282c0-20 13-40 36-40 24 0 33 18 33 45v105h66V279c0-61-32-89-76-89-34 0-51 19-59 32"/></svg>
</a>
</div>
<h4>Friendship Links</h4>
<ul class="list-of-tags tags-in-article">
<li>
<a href="https://leetcode-cn.com/" title="力扣中国站点" target="_blank" rel="nofollow noopener noreferrer">
LeetCode
</a>
</li>
<li>
<a href="https://coolshell.cn/about" title="陈皓酷壳" target="_blank" rel="nofollow noopener noreferrer">
CoolShell
</a>
</li>
<li>
<a href="https://yikun.github.io/" title="姜毅坤博客" target="_blank" rel="nofollow noopener noreferrer">
Yikun
</a>
</li>
<li>
<a href="https://www.nowcoder.com/" title="牛客网" target="_blank" rel="nofollow noopener noreferrer">
牛客网
</a>
</li>
</ul>
</section>
</div>
</article>
</div>
<div class="span1"></div>
</div>
</div>
</div>
<footer>
<div>
<span class="site-name">CatsAction's blog</span> - It's a wonderful world
</div>
<div id="fpowered">
Powered by: <a href="http://getpelican.com/" title="Pelican Home Page" target="_blank" rel="nofollow noopener noreferrer">Pelican</a>
Theme: <a href="https://elegant.oncrashreboot.com/" title="Theme Elegant Home Page" target="_blank" rel="nofollow noopener noreferrer">Elegant</a>
</div>
</footer> <script src="//code.jquery.com/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script>
function validateForm(query)
{
return (query.length > 0);
}
</script>
<script>
(function () {
if (window.location.hash.match(/^#comment-\d+$/)) {
$('#comment_thread').collapse('show');
}
})();
window.onhashchange=function(){
if (window.location.hash.match(/^#comment-\d+$/))
window.location.reload(true);
}
$('#comment_thread').on('shown', function () {
var link = document.getElementById('comment-accordion-toggle');
var old_innerHTML = link.innerHTML;
$(link).fadeOut(200, function() {
$(this).text('Click here to hide comments').fadeIn(200);
});
$('#comment_thread').on('hidden', function () {
$(link).fadeOut(200, function() {
$(this).text(old_innerHTML).fadeIn(200);
});
})
})
</script>
</body>
<!-- Theme: Elegant built for Pelican
License : MIT -->
</html>