為什么會需要消息隊列(MQ)?
一、消息隊列概述
消息隊列中間件是分布式系統中重要的組件,主要解決應用解耦,異步消息,流量削鋒等問題,實現高性能,高可用,可伸縮和最終一致性架構。目前使用較多的消息隊列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ
二、消息隊列應用場景
以下介紹消息隊列在實際應用中常用的使用場景。異步處理,應用解耦,流量削鋒和消息通訊四個場景。
2.1異步處理
場景說明:用戶注冊后,需要發注冊郵件和注冊短信。傳統的做法有兩種 1.串行的方式;2.並行方式
a、串行方式:將注冊信息寫入數據庫成功后,發送注冊郵件,再發送注冊短信。以上三個任務全部完成后,返回給客戶端。
b、並行方式:將注冊信息寫入數據庫成功后,發送注冊郵件的同時,發送注冊短信。以上三個任務完成后,返回給客戶端。與串行的差別是,並行的方式可以提高處理的時間
假設三個業務節點每個使用50毫秒鍾,不考慮網絡等其他開銷,則串行方式的時間是150毫秒,並行的時間可能是100毫秒。
因為CPU在單位時間內處理的請求數是一定的,假設CPU1秒內吞吐量是100次。則串行方式1秒內CPU可處理的請求量是7次(1000/150)。並行方式處理的請求量是10次(1000/100)
小結:如以上案例描述,傳統的方式系統的性能(並發量,吞吐量,響應時間)會有瓶頸。如何解決這個問題呢?
引入消息隊列,將不是必須的業務邏輯,異步處理。改造后的架構如下:
2.2應用解耦
例子1:
傳統模式的缺點:
- 系統間耦合性太強,如上圖所示,系統A在代碼中直接調用系統B和系統C的代碼,
如果將來D系統接入,系統A還需要修改代碼,過於麻煩!
中間件模式的的優點:
- 將消息寫入消息隊列,需要消息的系統自己從消息隊列中訂閱,從而系統A不需要做任何修改。
例子2:
2.3流量削鋒
流量削鋒也是消息隊列中的常用場景,一般在秒殺或團搶活動中使用廣泛。
應用場景:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入消息隊列。
a、可以控制活動的人數
b、可以緩解短時間內高流量壓垮應用
用戶的請求,服務器接收后,首先寫入消息隊列。假如消息隊列長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面。
秒殺業務根據消息隊列中的請求信息,再做后續處理
2.4日志處理
日志處理是指將消息隊列用在日志處理中,比如Kafka的應用,解決大量日志傳輸的問題。架構簡化如下
日志采集客戶端,負責日志數據采集,定時寫受寫入Kafka隊列
Kafka消息隊列,負責日志數據的接收,存儲和轉發
日志處理應用:訂閱並消費kafka隊列中的日志數據
2.5消息通訊
消息通訊是指,消息隊列一般都內置了高效的通信機制,因此也可以用在純的消息通訊。
比如實現點對點消息隊列,或者聊天室等
點對點通訊:
客戶端A,客戶端B,客戶端N訂閱同一主題,進行消息發布和接收。實現類似聊天室效果。
以上實際是消息隊列的兩種消息模式,點對點或發布訂閱模式。模型為示意圖,供參考。
三、使用了消息隊列會有什么缺點?
分析:一個使用了MQ的項目,如果連這個問題都沒有考慮過,就把MQ引進去了,那就給自己的項目帶來了風險。我們引入一個技術,要對這個技術的弊端有充分的認識,才能做好預防。要記住,不要給公司挖坑!
回答:回答也很容易,從以下兩個個角度來答
- 系統可用性降低:你想啊,本來其他系統只要運行好好的,那你的系統就是正常的。現在你非要加個消息隊列進去,那消息隊列掛了,你的系統不是呵呵了。因此,系統可用性降低
- 系統復雜性增加:要多考慮很多方面的問題,比如一致性問題、如何保證消息不被重復消費,如何保證保證消息可靠傳輸。因此,需要考慮的東西更多,系統復雜性增大。
但是,我們該用還是要用的。
四、消息中間件示例
消息隊列采用高可用,可持久化的消息中間件。比如Active MQ,Rabbit MQ,Rocket Mq。
(1)應用將主干邏輯處理完成后,寫入消息隊列。消息發送是否成功可以開啟消息的確認模式。(消息隊列返回消息接收成功狀態后,應用再返回,這樣保障消息的完整性)
(2)擴展流程(發短信,配送處理)訂閱隊列消息。采用推或拉的方式獲取消息並處理。
(3)消息將應用解耦的同時,帶來了數據一致性問題,可以采用最終一致性方式解決。比如主數據寫入數據庫,擴展應用根據消息隊列,並結合數據庫方式實現基於消息隊列的后續處理。
3.2日志收集系統
分為Zookeeper注冊中心,日志收集客戶端,Kafka集群和Storm集群(OtherApp)四部分組成。
Zookeeper注冊中心,提出負載均衡和地址查找服務
日志收集客戶端,用於采集應用系統的日志,並將數據推送到kafka隊列
Kafka集群:接收,路由,存儲,轉發等消息處理
Storm集群:與OtherApp處於同一級別,采用拉的方式消費隊列中的數據
五、常見消息隊列
特性 | ActiveMQ | RabbitMQ | RocketMQ | kafka |
---|---|---|---|---|
開發語言 | java | erlang | java | scala |
單機吞吐量 | 萬級 | 萬級 | 10萬級 | 10萬級 |
時效性 | ms級 | us級 | ms級 | ms級以內 |
可用性 | 高(主從架構) | 高(主從架構) | 非常高(分布式架構) | 非常高(分布式架構) |
功能特性 | 成熟的產品,在很多公司得到應用;有較多的文檔;各種協議支持較好 | 基於erlang開發,所以並發能力很強,性能極其好,延時很低;管理界面較豐富 | MQ功能比較完備,擴展性佳 | 只支持主要的MQ功能,像一些消息查詢,消息回溯等功能沒有提供,畢竟是為大數據准備的,在大數據領域應用廣。 |
六、安裝 RabbitMQ
總結:
需要先安裝erlang語言 socat 再安裝 rabbitMQ erlang下載列表:https://github.com/rabbitmq/erlang-rpm/releases rabbitMQ下載列表:https://github.com/rabbitmq/rabbitmq-server/releases
rpm -ivh erlang-20.3.8.20-1.el7.x86_64.rpm
yum install socat.x86_64
rpm -ivh rabbitmq-server-3.7.12-1.el7.noarch.rpm
安裝筆記:
第一種方法:手動
安裝yum epel倉庫 epel-release.noarch
安裝 erlang語言 yum install erlang.x86_64
官網下載rpm包,安裝 rabbitMQ rpm -ivh rabbitmq-server-3.7.12-1.el7.noarch.rpm
報錯:
# rpm -ivh rabbitmq-server-3.7.12-1.el7.noarch.rpm warning: rabbitmq-server-3.7.12-1.el7.noarch.rpm: Header V4 RSA/SHA256 Signature, key ID 6026dfca: NOKEY error: Failed dependencies: erlang >= 20.3 is needed by rabbitmq-server-3.7.12-1.el7.noarch
socat is needed by rabbitmq-server-3.7.12-1.el7.noarch
先解決第二個錯誤 yum -y install socat
第一個錯誤是用epel倉庫安裝的erlang版本太低,是
# yum list |grep erlang erlang.x86_64 R16B-03.18.el7 @epel
這里需要用20.3以上版本的
到官網下載新版本的erlang
erlang-20.3.8.20-1.el7.x86_64
安裝新版本:rpm -ivh erlang-20.3.8.20-1.el7.x86_64.rpm
報錯:提示與以前版本沖突
]# rpm -ivh erlang-20.3.8.20-1.el7.x86_64.rpm warning: erlang-20.3.8.20-1.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID 6026dfca: NOKEY Preparing... ################################# [100%] file /usr/lib64/erlang/bin/epmd from install of erlang-20.3.8.20-1.el7.x86_64 conflicts with file from package erlang-erts-R16B-03.18.el7.x86_64 file /usr/lib64/erlang/bin/erl from install of erlang-20.3.8.20-1.el7.x86_64 conflicts with file from package erlang-erts-R16B-03.18.el7.x86_64
卸載以前版本:yum remove erlang-erts-R16B-03.18.el7.x86_64
再次安裝:
# rpm -ivh erlang-20.3.8.20-1.el7.x86_64.rpm warning: erlang-20.3.8.20-1.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID 6026dfca: NOKEY Preparing... ################################# [100%] Updating / installing... 1:erlang-20.3.8.20-1.el7 ################################# [100%]
查看erlang版本,並安裝rabbitMQ
# erl Erlang/OTP 20 [erts-9.3.3.9] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] Eshell V9.3.3.9 (abort with ^G) 1> BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution [root@localhost rabbitmq]# rpm -ivh rabbitmq-server-3.7.12-1.el7.noarch.rpm warning: rabbitmq-server-3.7.12-1.el7.noarch.rpm: Header V4 RSA/SHA256 Signature, key ID 6026dfca: NOKEY Preparing... ################################# [100%] Updating / installing... 1:rabbitmq-server-3.7.12-1.el7 ################################# [100%]
安裝成功!
第二種方法 全yum
下載rpm倉庫:wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm 安裝rpm倉庫 rpm -Uvh erlang-solutions-1.0-1.noarch.rpm 安裝erlang yum -y install erlang 備注:上面可能會出現報錯,我安裝就出現缺少epel-release包,缺少就安裝即可解決。 安裝epel-release yum install -y epel-release 下載RabbitMQ包 wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el6.noarch.rpm 安裝RabbitMQ yum install rabbitmq-server-3.6.6-1.el6.noarch.rpm -y
七、使用管理 rabbitMQ
對應一種安裝方法:
啟動rabbitmq,並驗證啟動情況
rabbitmq-server --detached &ps aux |grep rabbitmq
以服務的方式啟動
service rabbitmq-server start
檢查端口5672是否打開
/sbin/iptables -I INPUT -p tcp --dport 5672 -j ACCEPT
/etc/rc.d/init.d/iptables save
/etc/init.d/iptables restart
/etc/init.d/iptables status
啟用維護插件 15672端口
rabbitmq-plugins enable rabbitmq_management
重啟rabbitmq
service rabbitmq-server restart
登錄
http://192.168.110.60:15672/ 用戶名密碼 guest
無法登陸
登錄遇到問題:User can only log in via localhost
解決問題:
找到這個文件rabbit.app
/usr/lib/rabbitmq/lib/rabbitmq_server-3.7.7/ebin/rabbit.app
將:{loopback_users, [<<”guest”>>]},
改為:{loopback_users, []},
原因:rabbitmq從3.3.0開始禁止使用guest/guest權限通過除localhost外的訪問
重啟服務就OK了 systemctl restart rabbitmq-server.service
user:guest
pwd:guest
對應第二種安裝方法:
進入bin下,使用下面命令開啟管理頁面
# whereis rabbitmq
rabbitmq: /usr/lib/rabbitmq /etc/rabbitmq
# cd /usr/lib/rabbitmq/bin/
#./rabbitmq-plugins enable rabbitmq_management
創建用戶 root 密碼 123456
#rabbitmqctl add_user root 123456 #rabbitmqctl set_user_tags root administrator
給用戶授予讀寫權限
rabbitmqctl set_permissions -p / root ".*" ".*" ".*"
這條命令里面 / 的意思
虛擬主機vhost
每一個RabbitMQ服務器都能創建虛擬消息服務器,我們稱之為虛擬主機。每一個vhost本質上是一個mini版的RabbitMQ服務器,
擁有自己的交換機、隊列、綁定等,擁有自己的權限機制。vhost之於Rabbit就像虛擬機之於物理機一樣。
他們通過在各個實例間提供邏輯上分離,允許為不同的應用程序安全保密的運行數據,
這很有,它既能將同一個Rabbit的眾多客戶區分開來,又可以避免隊列和交換器的命名沖突。RabbitMQ提供了開箱即用的默認的虛擬主機“/”,
如果不需要多個vhost可以直接使用這個默認的vhost,通過使用缺省的guest用戶名和guest密碼來訪問默認的vhost。 vhost之間是相互獨立的,這避免了各種命名的沖突,就像App中的沙盒的概念一樣,每個沙盒是相互獨立的,且只能訪問自己的沙盒,以保證非法訪問別的沙盒帶來的安全隱患。
重啟rabbitmq,然后直接訪問http://IP:15672就可以看到相應的管理web界面
----------------------------------------------------------------------------分割線----------------------------------------------------------------------------
1、服務器啟動與關閉
啟動:service rabbitmq-server start
關閉:service rabbitmq-server stop
重啟:service rabbitmq-server restart
2、用戶管理
新增 rabbitmqctl add_user admin admin
刪除 rabbitmqctl delete_user admin
修改 rabbitmqctl change_password admin admin123
用戶列表 rabbitmqctl list_users
設置角色 rabbitmqctl set_user_tags admin administrator monitoring policymaker management
設置用戶權限 rabbitmqctl set_permissions -p VHostPath admin ConfP WriteP ReadP
查詢所有權限 rabbitmqctl list_permissions [-p VHostPath]
指定用戶權限 rabbitmqctl list_user_permissions admin
清除用戶權限 rabbitmqctl clear_permissions [-p VHostPath] admin