平安保險基于 SPI 機制的 RocketMQ 定制化應用
發(fā)布時間:2022-01-25 點擊數(shù):1646
01
首要跟咱們聊聊咱們?yōu)槭裁磿x用 RocketMQ,在做技能選型的進程中,運用場景應該是最先考慮清楚的,只要確認好了運用場景在做技能選型的進程中才有清晰的目標和衡量的標準。像異步、解耦、削峰填谷這些音訊中間件共有的特性就不逐個介紹了,這些特性是決議你的場景需不需求運用音訊中間件,這兒主要講述下在確認運用音訊中間件后,又是怎么去選擇哪款音訊中間件的。
1 同步雙寫,確保事務數(shù)據(jù)安全可靠不丟失
2 多 topic 運用場景下,功能仍舊強悍
3 支撐事務音訊、次序音訊、推遲音訊、音訊消費失利重試等
4 社區(qū)建設活潑,阿里開源體系
介紹完為什么選用 RocketMQ 后,接下來給咱們介紹下咱們是怎么基于 SPI 機制運用 RocketMQ 的。SPI 全稱為 (Service Provider Interface) ,是 JDK 內(nèi)置的一種服務供給發(fā)現(xiàn)機制,我個人簡略理解便是面向接口編程,留給運用者一個擴展的點,像 springBoot 中的 spring.factories 也是 SPI 機制的一個運用。如圖給咱們展示的是 RocketMQ 中 SPI 的一個運用。咱們基于 SPI 機制的 RocketMQ 客戶端的運用的靈感也是來自于 MQ 中 SPI 機制的運用。RocketMQ 在完成 ACL 權(quán)限校驗的時分,是經(jīng)過完成 AccessValidator 接口,PlainAccessValidator 是 MQ 中的默許完成。權(quán)限校驗這一塊,或許由于安排架構(gòu)的不一樣會有不同的完成辦法,經(jīng)過 SPI 機制供給一個接口,為開發(fā)者定制化開發(fā)供給擴展點。在有定制化需求時只需求重新完成 AccessValidator 接口,不需求對源碼大動干戈。
接下來先給咱們介紹下咱們裝備文件的一個簡略模型,在這個裝備文件中除了 sendMsgService、consumeMsgConcurrently、consumeMsgOrderly 這三個裝備項外其他的都是 RocketMQ 原生的裝備文件,發(fā)送音訊和消費音訊這三個裝備項呢便是 SPI 機制的運用,是為詳細完成供給的接口?;蛟S有的同學會有疑問,SPI 的裝備文件不是應該放在 META-INF.service 途徑下么?這兒呢咱們是為了便利裝備文件的辦理,索性就跟 MQ 裝備文件放在了一同。前面也提到了,META-INF.service 僅僅一個默許的途徑罷了,為了便利辦理做相應的修正也沒有違背SPI機制的思維。
咱們再看下這個裝備文件模型,這兒的裝備項呢包括了運用 MQ 時所要裝備的一切選項,proConfigs 支撐一切的 MQ 原生裝備,這樣呢也就完成了裝備與運用完成的解耦,運用端只需呀重視的詳細的事務邏輯即可,出產(chǎn)者顧客的完成和顧客消費的 topic 都能夠經(jīng)過裝備文件來指定。別的該裝備文件也支撐多 nameserver 的多環(huán)境運用,在較雜亂的運用中支撐往多套 RocketMQ 環(huán)境發(fā)送音訊和消費多套不同環(huán)境下的音訊。顧客供給了兩個接口主要是為了支撐 RocketMQ 的并發(fā)消費和次序消費。接下來呢給咱們共享下怎么依據(jù)這個裝備文件來初始化出產(chǎn)者顧客。首要給咱們先介紹下咱們抽象出來的客戶端加載的一個中心流程。
03
圖中咱們能夠看到,客戶端的中心流程咱們抽象成了三部分,分別是發(fā)動期、運行期和停止期。首要加載裝備文件呢便是加載剛剛介紹的那個裝備文件模型,在裝備與運用完全解耦的狀態(tài)下,必須先加載完裝備文件才能初始化后續(xù)的流程。在初始化出產(chǎn)者和顧客之前應當先創(chuàng)立好運用完成的出產(chǎn)者和顧客的事務邏輯目標 供出產(chǎn)者和顧客運用。在運行期監(jiān)聽裝備文件的變化,依據(jù)變化動態(tài)的調(diào)整出產(chǎn)者和顧客實例。這兒仍是要再強調(diào)下裝備與運用的解耦為動態(tài)調(diào)整供給了或許。停止期就比較簡略了,便是封閉出產(chǎn)者和顧客,并從容器中移除。這兒的停止期指的出產(chǎn)者和顧客的停止,并不是整個運用的停止,出產(chǎn)者和顧客的停止或許出現(xiàn)在動態(tài)調(diào)整的進程中,所以停止了的實例必定要從容器中移除,便利初始化后續(xù)的出產(chǎn)者和顧客。介紹完基本流程后,接下來給咱們介紹下裝備文件的加載進程。
1 怎么加載裝備文件
裝備文件加載這一塊的話,流程是比較簡略的。這兒主要講的是怎么去兼容比較老的項目。RocketMQ 客戶端支撐的 JDK 最低版本是 1.6,所以在封裝客戶端時應該要考慮到新老項目兼容的問題。在這兒呢咱們客戶端的中心包是支撐 JDK1.6 的,spring 早期的項目裝備文件一般都是放在在 resources 途徑下,咱們是自己完成了一套讀取裝備文件的和監(jiān)聽裝備文件的辦法,詳細的咱們能夠參閱 acl 中裝備文件的讀取和監(jiān)聽。在中心包的基礎上用 springBoot 又封裝了一套主動加載裝備文件的包供微服務項目運用,裝備文件的讀取和監(jiān)聽都用的 spring 的那一套。裝備文件加載完之后, 裝備文件中運用完成的出產(chǎn)者和顧客是怎么與 RocketMQ 的出產(chǎn)者和顧客相相關(guān)的呢?接下來給咱們共享下這方面的內(nèi)容。
2 怎么將出產(chǎn)顧客與事務完成相關(guān)
首要先看下顧客是怎么完成相關(guān)的,上圖是 MQ 顧客的音訊監(jiān)聽器,需求咱們?nèi)ネ瓿稍敿毜氖聞者壿嬏幚?。?jīng)過將裝備文件中完成的消費邏輯相關(guān)到這兒就能完成裝備文件中的顧客與 RocketMQ 顧客的相關(guān)。顧客的接口界說也是很簡略,便是去消費音訊。消費音訊的類型能夠經(jīng)過泛型指定,在初始化顧客的時分獲取詳細完成的參數(shù)類型,并將
與顧客不一樣的是出產(chǎn)者需求將初始化好的 producer 目標傳遞到運用代碼中去,而顧客是去獲取運用中完成的邏輯目標,那怎么將 producer 傳遞到事務運用中去呢?事務代碼中完成的出產(chǎn)者需求繼承 SendMessage,這樣事務代碼就獲得了 RmqProducer 目標,這是一個被封裝后的出產(chǎn)者目標,該目標對發(fā)送音訊的辦法進行的標準化界說,使之符合公司的相應標準制度,該目標中的辦法也會對 topic 的命名標準進行檢查,標準 topic 有一個一致的命名標準。
3 怎么動態(tài)調(diào)整出產(chǎn)顧客
nameserver產(chǎn)生變化的時分,需求重新初始化一切的出產(chǎn)者和顧客,這個一般是在 MQ 做搬遷或許當時 MQ 集群不可用是需求緊迫切換 MQ;
增減實例的場景只要發(fā)動或封閉相應的實例即可,添加運用實例的場景一般是在需求添加一個顧客來消費新的 topic 的,減少顧客一般是在某個顧客產(chǎn)生反常時需求緊迫封閉這個顧客,及時止損。
調(diào)整顧客線程的場景中咱們對源碼進行了一點修正,讓運用端能獲取到顧客的線程池目標,以便對線程池的中心線程數(shù)進行動態(tài)調(diào)整。這個的運用場景一般是在當某個顧客消費的數(shù)據(jù)比較多,占用過多的 CPU 資源時,導致優(yōu)先級更高的音訊得不到及時處理,能夠先將該顧客的線程調(diào)小一些。
為什么選用 RocketMQ
Cloud Native
首要跟咱們聊聊咱們?yōu)槭裁磿x用 RocketMQ,在做技能選型的進程中,運用場景應該是最先考慮清楚的,只要確認好了運用場景在做技能選型的進程中才有清晰的目標和衡量的標準。像異步、解耦、削峰填谷這些音訊中間件共有的特性就不逐個介紹了,這些特性是決議你的場景需不需求運用音訊中間件,這兒主要講述下在確認運用音訊中間件后,又是怎么去選擇哪款音訊中間件的。
1 同步雙寫,確保事務數(shù)據(jù)安全可靠不丟失
2 多 topic 運用場景下,功能仍舊強悍
3 支撐事務音訊、次序音訊、推遲音訊、音訊消費失利重試等
4 社區(qū)建設活潑,阿里開源體系
別的,在選用音訊中間件時也要考慮下社區(qū)的活潑度和源碼所運用的開發(fā)言語,RocketMQ 運用 Java 開發(fā),對 Java 開發(fā)人員就比較友愛,不管是閱覽源碼排查問題仍是在 MQ 的基礎上做二次開發(fā)都比較簡略一點。社區(qū)里同學大都是國內(nèi)的小伙伴,對咱們參加 RocketMQ 開源奉獻也是比較接近的,這兒呢也是期望更多的小伙伴能參加進來,為國內(nèi)開源項目多做奉獻。
SPI 機制簡介及運用
Cloud Native
介紹完為什么選用 RocketMQ 后,接下來給咱們介紹下咱們是怎么基于 SPI 機制運用 RocketMQ 的。SPI 全稱為 (Service Provider Interface) ,是 JDK 內(nèi)置的一種服務供給發(fā)現(xiàn)機制,我個人簡略理解便是面向接口編程,留給運用者一個擴展的點,像 springBoot 中的 spring.factories 也是 SPI 機制的一個運用。如圖給咱們展示的是 RocketMQ 中 SPI 的一個運用。咱們基于 SPI 機制的 RocketMQ 客戶端的運用的靈感也是來自于 MQ 中 SPI 機制的運用。RocketMQ 在完成 ACL 權(quán)限校驗的時分,是經(jīng)過完成 AccessValidator 接口,PlainAccessValidator 是 MQ 中的默許完成。權(quán)限校驗這一塊,或許由于安排架構(gòu)的不一樣會有不同的完成辦法,經(jīng)過 SPI 機制供給一個接口,為開發(fā)者定制化開發(fā)供給擴展點。在有定制化需求時只需求重新完成 AccessValidator 接口,不需求對源碼大動干戈。
接下來先給咱們介紹下咱們裝備文件的一個簡略模型,在這個裝備文件中除了 sendMsgService、consumeMsgConcurrently、consumeMsgOrderly 這三個裝備項外其他的都是 RocketMQ 原生的裝備文件,發(fā)送音訊和消費音訊這三個裝備項呢便是 SPI 機制的運用,是為詳細完成供給的接口?;蛟S有的同學會有疑問,SPI 的裝備文件不是應該放在 META-INF.service 途徑下么?這兒呢咱們是為了便利裝備文件的辦理,索性就跟 MQ 裝備文件放在了一同。前面也提到了,META-INF.service 僅僅一個默許的途徑罷了,為了便利辦理做相應的修正也沒有違背SPI機制的思維。
咱們再看下這個裝備文件模型,這兒的裝備項呢包括了運用 MQ 時所要裝備的一切選項,proConfigs 支撐一切的 MQ 原生裝備,這樣呢也就完成了裝備與運用完成的解耦,運用端只需呀重視的詳細的事務邏輯即可,出產(chǎn)者顧客的完成和顧客消費的 topic 都能夠經(jīng)過裝備文件來指定。別的該裝備文件也支撐多 nameserver 的多環(huán)境運用,在較雜亂的運用中支撐往多套 RocketMQ 環(huán)境發(fā)送音訊和消費多套不同環(huán)境下的音訊。顧客供給了兩個接口主要是為了支撐 RocketMQ 的并發(fā)消費和次序消費。接下來呢給咱們共享下怎么依據(jù)這個裝備文件來初始化出產(chǎn)者顧客。首要給咱們先介紹下咱們抽象出來的客戶端加載的一個中心流程。
03
客戶端中心流程概況
Cloud Native
圖中咱們能夠看到,客戶端的中心流程咱們抽象成了三部分,分別是發(fā)動期、運行期和停止期。首要加載裝備文件呢便是加載剛剛介紹的那個裝備文件模型,在裝備與運用完全解耦的狀態(tài)下,必須先加載完裝備文件才能初始化后續(xù)的流程。在初始化出產(chǎn)者和顧客之前應當先創(chuàng)立好運用完成的出產(chǎn)者和顧客的事務邏輯目標 供出產(chǎn)者和顧客運用。在運行期監(jiān)聽裝備文件的變化,依據(jù)變化動態(tài)的調(diào)整出產(chǎn)者和顧客實例。這兒仍是要再強調(diào)下裝備與運用的解耦為動態(tài)調(diào)整供給了或許。停止期就比較簡略了,便是封閉出產(chǎn)者和顧客,并從容器中移除。這兒的停止期指的出產(chǎn)者和顧客的停止,并不是整個運用的停止,出產(chǎn)者和顧客的停止或許出現(xiàn)在動態(tài)調(diào)整的進程中,所以停止了的實例必定要從容器中移除,便利初始化后續(xù)的出產(chǎn)者和顧客。介紹完基本流程后,接下來給咱們介紹下裝備文件的加載進程。
1 怎么加載裝備文件
裝備文件加載這一塊的話,流程是比較簡略的。這兒主要講的是怎么去兼容比較老的項目。RocketMQ 客戶端支撐的 JDK 最低版本是 1.6,所以在封裝客戶端時應該要考慮到新老項目兼容的問題。在這兒呢咱們客戶端的中心包是支撐 JDK1.6 的,spring 早期的項目裝備文件一般都是放在在 resources 途徑下,咱們是自己完成了一套讀取裝備文件的和監(jiān)聽裝備文件的辦法,詳細的咱們能夠參閱 acl 中裝備文件的讀取和監(jiān)聽。在中心包的基礎上用 springBoot 又封裝了一套主動加載裝備文件的包供微服務項目運用,裝備文件的讀取和監(jiān)聽都用的 spring 的那一套。裝備文件加載完之后, 裝備文件中運用完成的出產(chǎn)者和顧客是怎么與 RocketMQ 的出產(chǎn)者和顧客相相關(guān)的呢?接下來給咱們共享下這方面的內(nèi)容。
2 怎么將出產(chǎn)顧客與事務完成相關(guān)
首要先看下顧客是怎么完成相關(guān)的,上圖是 MQ 顧客的音訊監(jiān)聽器,需求咱們?nèi)ネ瓿稍敿毜氖聞者壿嬏幚?。?jīng)過將裝備文件中完成的消費邏輯相關(guān)到這兒就能完成裝備文件中的顧客與 RocketMQ 顧客的相關(guān)。顧客的接口界說也是很簡略,便是去消費音訊。消費音訊的類型能夠經(jīng)過泛型指定,在初始化顧客的時分獲取詳細完成的參數(shù)類型,并將
與顧客不一樣的是出產(chǎn)者需求將初始化好的 producer 目標傳遞到運用代碼中去,而顧客是去獲取運用中完成的邏輯目標,那怎么將 producer 傳遞到事務運用中去呢?事務代碼中完成的出產(chǎn)者需求繼承 SendMessage,這樣事務代碼就獲得了 RmqProducer 目標,這是一個被封裝后的出產(chǎn)者目標,該目標對發(fā)送音訊的辦法進行的標準化界說,使之符合公司的相應標準制度,該目標中的辦法也會對 topic 的命名標準進行檢查,標準 topic 有一個一致的命名標準。
3 怎么動態(tài)調(diào)整出產(chǎn)顧客
nameserver產(chǎn)生變化的時分,需求重新初始化一切的出產(chǎn)者和顧客,這個一般是在 MQ 做搬遷或許當時 MQ 集群不可用是需求緊迫切換 MQ;
增減實例的場景只要發(fā)動或封閉相應的實例即可,添加運用實例的場景一般是在需求添加一個顧客來消費新的 topic 的,減少顧客一般是在某個顧客產(chǎn)生反常時需求緊迫封閉這個顧客,及時止損。
調(diào)整顧客線程的場景中咱們對源碼進行了一點修正,讓運用端能獲取到顧客的線程池目標,以便對線程池的中心線程數(shù)進行動態(tài)調(diào)整。這個的運用場景一般是在當某個顧客消費的數(shù)據(jù)比較多,占用過多的 CPU 資源時,導致優(yōu)先級更高的音訊得不到及時處理,能夠先將該顧客的線程調(diào)小一些。