學(xué)習(xí)記錄之消息隊(duì)列
Dubbo遠(yuǎn)程調(diào)用的性能問題
Dubbo調(diào)用普遍存在于我們的微服務(wù)項(xiàng)目中
這些Dubbo調(diào)用全部是同步的操作
這里的"同步"指:消費(fèi)者A調(diào)用生產(chǎn)者B之后,A的線程會(huì)進(jìn)入阻塞狀態(tài),等待生產(chǎn)者B運(yùn)行結(jié)束返回之后,A才能運(yùn)行之后的代碼

Dubbo消費(fèi)者發(fā)送調(diào)用后進(jìn)入阻塞狀態(tài),這個(gè)狀態(tài)表示該線程仍占用內(nèi)存資源,但是什么動(dòng)作都不做
如果生產(chǎn)者運(yùn)行耗時(shí)較久,消費(fèi)者就一直等待,如果消費(fèi)者利用這個(gè)時(shí)間,那么可以處理更多請(qǐng)求,業(yè)務(wù)整體效率會(huì)提升
實(shí)際情況下,Dubbo有些必要的返回值必須等待,但是不必要等待的服務(wù)返回值,我們可以不等待去做別的事情
這種情況下我們就要使用消息隊(duì)列
什么是消息隊(duì)列
消息隊(duì)列(Message Queue)簡(jiǎn)稱MQ
消息隊(duì)列是采用"異步(兩個(gè)微服務(wù)項(xiàng)目并不需要同時(shí)完成請(qǐng)求)"的方式來傳遞數(shù)據(jù)完成業(yè)務(wù)操作流程的業(yè)務(wù)處理方式
消息隊(duì)列的特征

消息隊(duì)列的特征(作用):
利用異步的特性,提高服務(wù)器的運(yùn)行效率,減少因?yàn)檫h(yuǎn)程調(diào)用出現(xiàn)的線程等待\阻塞
削峰填谷:在并發(fā)峰值超過當(dāng)前系統(tǒng)處理能力時(shí),我們將沒處理的信息保存在消息隊(duì)列中,在后面出現(xiàn)的較閑的時(shí)間中去處理,直到所有數(shù)據(jù)依次處理完成,能夠防止在并發(fā)峰值時(shí)短時(shí)間大量請(qǐng)求而導(dǎo)致的系統(tǒng)不穩(wěn)定
消息隊(duì)列的延時(shí):因?yàn)槭钱惒綀?zhí)行,請(qǐng)求的發(fā)起者并不知道消息何時(shí)能處理完,如果業(yè)務(wù)不能接受這種延遲,就不要使用消息隊(duì)列

常見消息隊(duì)列軟件
Kafka:性能好\功能弱:適合大數(shù)據(jù)量,高并發(fā)的情況,大數(shù)據(jù)領(lǐng)域使用較多
RabbitMQ:功能強(qiáng)\性能一般:適合發(fā)送業(yè)務(wù)需求復(fù)雜的消息隊(duì)列,java業(yè)務(wù)中使用較多
RocketMQ:阿里的
ActiveMQ:前幾年流行的,老項(xiàng)目可能用到
消息隊(duì)列異常處理:
問:消息隊(duì)列運(yùn)行時(shí)發(fā)生異常,沒有完成業(yè)務(wù),怎么通知消息的發(fā)送者,完成數(shù)據(jù)的回滾?
當(dāng)消息隊(duì)列中發(fā)生異常時(shí),在異常處理的代碼中,我們可以向消息的發(fā)送者發(fā)送消息,然后通知發(fā)送者處理,消息的發(fā)送者接收到消息后,一般要手寫代碼回滾,如果回滾代碼過程中再發(fā)送異常
可以將這個(gè)信息直接發(fā)送給"死信隊(duì)列"
死信隊(duì)列沒有任何處理者,通常情況下會(huì)有專人周期性的處理死信隊(duì)列的消息
Kafka
Kafka是由Apache軟件基金會(huì)開發(fā)的一個(gè)開源流處理平臺(tái),由Scala和Java編寫。該項(xiàng)目的目標(biāo)是為處理實(shí)時(shí)數(shù)據(jù)提供一個(gè)統(tǒng)一、高吞吐、低延遲的平臺(tái)。Kafka最初是由LinkedIn開發(fā),并隨后于2011年初開源。
kafka軟件結(jié)構(gòu)
Kafka是一個(gè)結(jié)構(gòu)相對(duì)簡(jiǎn)單的消息隊(duì)列(MQ)軟件
kafka軟件結(jié)構(gòu)圖

Kafka Cluster(Kafka集群)
Partition(分片)
Producer:消息的發(fā)送方,也就是消息的來源,Kafka中的生產(chǎn)者
Consumer:消息的接收方,也是消息的目標(biāo),Kafka中的消費(fèi)者
Topic:話題或主題的意思,消息的收發(fā)雙方要依據(jù)同一個(gè)話題名稱,才不會(huì)將信息錯(cuò)發(fā)給別人
Record:消息記錄,就是生產(chǎn)者和消費(fèi)者傳遞的信息內(nèi)容,保存在指定的Topic中
Kafka的特征與優(yōu)勢(shì)
Kafka作為消息隊(duì)列,它和其他同類產(chǎn)品相比,突出的特點(diǎn)就是性能強(qiáng)大
Kafka將消息隊(duì)列中的信息保存在硬盤中
Kafka對(duì)硬盤的讀取規(guī)則進(jìn)行優(yōu)化后,效率能夠接近內(nèi)存
硬盤的優(yōu)化規(guī)則主要依靠"順序讀寫,零拷貝,日志壓縮等技術(shù)"
Kafka處理隊(duì)列中數(shù)據(jù)的默認(rèn)設(shè)置:
Kafka隊(duì)列信息能夠一直向硬盤中保存(理論上沒有大小限制)
Kafka默認(rèn)隊(duì)列中的信息保存7天,可以配置這個(gè)時(shí)間,縮短這個(gè)時(shí)間可以減少Kafka的磁盤消耗
Kafka的安裝和配置
必須將我們kafka軟件的解壓位置設(shè)置在一個(gè)根目錄,文件夾名稱盡量短(例如:kafka)
然后路徑不要有空格和中文
我們要?jiǎng)?chuàng)建一個(gè)空目錄用于保存Kafka運(yùn)行過程中產(chǎn)生的數(shù)據(jù)
本次創(chuàng)建名稱為data的空目錄
下面進(jìn)行Kafka啟動(dòng)前的配置
先到F:\kafka\config下配置有文件zookeeper.properties
找到dataDir屬性修改如下
dataDir=F:/data
修改完畢之后要Ctrl+S進(jìn)行保存,否則修改無效!!!!
注意F盤和data文件夾名稱,匹配自己電腦的真實(shí)路徑和文件夾名稱
還要修改server.properties配置文件
log.dirs=F:/data
修改注意事項(xiàng)和上面相同
啟動(dòng)kafka
要想啟動(dòng)Kafka必須先啟動(dòng)Zookeeper
Zookeeper介紹
zoo:動(dòng)物園
keeper:園長(zhǎng)
可以引申為管理動(dòng)物的人
Linux服務(wù)器中安裝的各種軟件,很多都是有動(dòng)物動(dòng)物形象的
如果這些軟件在Linux中需要修改配置信息的話,就需要進(jìn)入這個(gè)軟件,去修改配置,每個(gè)軟件都需要單獨(dú)修改配置的話,工作量很大
我們使用Zookeeper之后,可以創(chuàng)建一個(gè)新的管理各種軟件配置的文件管理系統(tǒng)
在Zookeeper中,可以修改服務(wù)器系統(tǒng)中的所有軟件配置
長(zhǎng)此以往,很多軟件就刪除了自己寫配置文件的功能,而直接從Zookeeper中獲取
Kafka就是需要將配置編寫在Zookeeper中的軟件之一
Zookeeper啟動(dòng)
進(jìn)入路徑F:\kafka\bin\windows
輸入cmd進(jìn)入dos命令行
kafka啟動(dòng)
總體方式一樣,輸入不同指令
在啟動(dòng)kafka時(shí)有一個(gè)常見錯(cuò)誤
wmic不是內(nèi)部或外部命令
這樣的提示,需要安裝wmic命令,安裝方式參考
https://zhidao.baidu.com/question/295061710.html
Kafka使用演示
啟動(dòng)的zookeeper和kafka的窗口不要關(guān)閉
我們?cè)赾small項(xiàng)目中編寫一個(gè)kafka使用的演示
csmall-cart-webapi模塊
添加依賴
修改yml文件進(jìn)行配置
在SpringBoot啟動(dòng)類中添加啟動(dòng)Kafka的注解
下面我們就可以實(shí)現(xiàn)周期性的向kafka發(fā)送消息并接收的操作了
編寫消息的發(fā)送
創(chuàng)建一個(gè)叫Consumer的類來接收消息
RabbitMQ
什么是RabbitMQ
RabbitMQ?是一個(gè)由?Erlang?語言開發(fā)的?AMQP?的開源實(shí)現(xiàn)。?AMQP?:Advanced Message Queue,高級(jí)消息隊(duì)列協(xié)議。它是應(yīng)用層協(xié)議的一個(gè)開放標(biāo)準(zhǔn),為面向消息的中間件設(shè)計(jì),基于此協(xié)議的客戶端與消息中間件可傳遞消息,并不受產(chǎn)品、開發(fā)語言等條件的限制。?RabbitMQ?最初起源于金融系統(tǒng),用于在分布式系統(tǒng)中存儲(chǔ)轉(zhuǎn)發(fā)消息,在易用性、擴(kuò)展性、高可用性等方面表現(xiàn)不俗。
RabbitMQ特征
1.可靠性(Reliability)?RabbitMQ?使用一些機(jī)制來保證可靠性,如持久化、傳輸確認(rèn)、發(fā)布確認(rèn)。
2.靈活的路由(Flexible Routing)?在消息進(jìn)入隊(duì)列之前,通過?Exchange?來路由消息的。對(duì)于典型的路由功能,RabbitMQ已經(jīng)提供了一些內(nèi)置的?Exchange?來實(shí)現(xiàn)。針對(duì)更復(fù)雜的路由功能,可以將多個(gè)Exchange?綁定在一起,也通過插件機(jī)制實(shí)現(xiàn)自己的?Exchange?。
3.消息集群(Clustering)?多個(gè)?RabbitMQ?服務(wù)器可以組成一個(gè)集群,形成一個(gè)邏輯?Broker
4.高可用(Highly Available Queues)?隊(duì)列可以在集群中的機(jī)器上進(jìn)行鏡像,使得在部分節(jié)點(diǎn)出問題的情況下隊(duì)列仍然可用。
5.多種協(xié)議(Multi-protocol)?RabbitMQ?支持多種消息隊(duì)列協(xié)議,比如?STOMP、MQTT?等等。
6.多語言客戶端(Many Clients)?RabbitMQ?幾乎支持所有常用語言,比如?Java、.NET、Ruby?等等。
7.管理界面(Management UI)?RabbitMQ?提供了一個(gè)易用的用戶界面,使得用戶可以監(jiān)控和管理消息?Broker?的許多方面。
8.跟蹤機(jī)制(Tracing)?如果消息異常,RabbitMQ?提供了消息跟蹤機(jī)制,使用者可以找出發(fā)生了什么。
9.插件機(jī)制(Plugin System)?RabbitMQ?提供了許多插件,來從多方面進(jìn)行擴(kuò)展,也可以編寫自己的插件。
下載軟件
RabbitMQ是Erlang語言開發(fā)的,所以要先安裝Erlang語言的運(yùn)行環(huán)境
下載Erlang的官方路徑
https://erlang.org/download/otp_versions_tree.html

安裝的話就是雙擊
安裝過程中都可以使用默認(rèn)設(shè)置,需要注意的是
不要安裝在中文路徑和有空格的路徑下!!!
下載RabbitMQ的官方網(wǎng)址
https://www.rabbitmq.com/install-windows.html

安裝也是雙擊即可
不要安裝在中文路徑和有空格的路徑下!!!
RabbitMQ的結(jié)構(gòu)
RabbitMQ軟件支持很多種消息隊(duì)列的發(fā)送方式的
使用的比較多的是路由模式

和Kafka不同,Kafka是使用話題名稱來收發(fā)信息,結(jié)構(gòu)簡(jiǎn)單
RabbitMQ是使用交換機(jī)\路由key指定要發(fā)送消息的隊(duì)列
消息的發(fā)送者發(fā)送消息時(shí),需要指定交換機(jī)和路由key名稱
消息的接收方接收消息時(shí),只需要指定隊(duì)列的名稱
在編寫代碼上,相比于Kafka,每個(gè)業(yè)務(wù)要編寫一個(gè)配置類
這個(gè)配置類中要綁定交換機(jī)和路由key的關(guān)系,以及路由Key和隊(duì)列的關(guān)系
配置Erlang的環(huán)境變量
要想運(yùn)行RabbitMQ必須保證系統(tǒng)有Erlang的環(huán)境變量
配置Erlang環(huán)境變量
把安裝Erlang的bin目錄配置在環(huán)境變量Path的屬性中

啟動(dòng)RabbitMQ
找到RabbitMQ的安裝目錄
可能是:
具體路徑根據(jù)自己的情況尋找
地址欄運(yùn)行cmd
輸入啟動(dòng)指令如下
結(jié)果如下

運(yùn)行完成后
可以在Window任務(wù)管理器中的服務(wù)選項(xiàng)卡里找到RabbitMQ的服務(wù)(Ctrl+Shift+ESC)
另外的驗(yàn)證方法:
因?yàn)镽abbitMQ自帶一個(gè)管理的界面,所以我們可以訪問這個(gè)界面來驗(yàn)證它的運(yùn)行狀態(tài)
http://localhost:15672

登錄界面用戶名密碼
guest
guest
登錄成功后看到RabbitMQ運(yùn)行的狀態(tài)
如果啟動(dòng)失敗,需要重新安裝
參考路徑如下
https://baijiahao.baidu.com/s?id=1720472084636520996&wfr=spider&for=pc
利用RabbitMQ完成消息的收發(fā)
csmall-stock-webapi項(xiàng)目中測(cè)試RabbitMQ
可以利用之前我們使用Quartz實(shí)現(xiàn)的每隔一段時(shí)間輸出當(dāng)前日期信息的方法改為發(fā)送消息
添加依賴
yml文件配置
交換機(jī)\路由Key\隊(duì)列的配置類
RabbitMQ要求我們?cè)趈ava代碼級(jí)別設(shè)置交換機(jī)\路由Key\隊(duì)列的關(guān)系
我們?cè)趒uartz包下,創(chuàng)建config包
包中創(chuàng)建配置信息類
RabbitMQ發(fā)送消息
我們?cè)赒uartzJob類中輸出時(shí)間的代碼后繼續(xù)編寫代碼
實(shí)現(xiàn)RabbitMQ消息的發(fā)送
我們可以通過修改QuartzConfig類中的Cron表達(dá)式修改調(diào)用的周期
接收RabbitMQ的消息
quartz包下再創(chuàng)建一個(gè)新的類用于接收信息
RabbitMQConsumer代碼如下
啟動(dòng)Nacos\RabbitMQ\Seata
啟動(dòng)stock-webapi
根據(jù)Cron表達(dá)式,消息會(huì)在0/10/20/30/40/50秒數(shù)時(shí)運(yùn)行
測(cè)試成功表示一切正常