中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

消息管理平臺的Java實現原理是什么

發布時間:2021-10-28 10:13:25 來源:億速云 閱讀:195 作者:iii 欄目:開發技術

本篇內容介紹了“消息管理平臺的Java實現原理是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

簡單認識《消息管理平臺》

「消息管理平臺」可能在不同的公司會有不同的叫法,有的時候我會叫它「推送系統」,有的時候我會叫它「消息管理平臺」,也有的同事叫它「觸達平臺」,甚至浮夸點我也可以叫它「消息中臺」

但是不管怎么樣,它的功能就是給用戶發消息。在公司里它是怎么樣的定位?只要以官方名義發送的消息,都走消息管理平臺。

一般你注冊一個APP/網站,你可以收到該APP/網站給你發什么消息呢?一般就以下吧?

  • 站內信(IM)消息:其實就是APP內聊天的消息

  • 通知欄(PUSH)消息:系統彈窗消息

  • 郵件(Email)消息

  • 短信(Sms)消息

  • 微信服務號消息

  • 微信小程序(服務通知)消息

為什么要有消息管理平臺?

可以說,只要是做APP的公司幾乎都會有消息管理平臺。

我們很多時候都會想給用戶發消息:

  • 有可能是用戶想要這樣的功能(預約活動提醒通知)

  • 也有可能是我們想通過發消息來「喚醒」/「告知」等操作,告訴用戶我們還在(大爺來玩啊)

那么問題來了,發消息困難嗎?發消息復雜嗎?

顯然,發消息非常簡單,一點兒也不復雜。

發短信無非就是調用第三方短信的API、發郵件無非就是調用郵件的API、發微信類的消息(手Q/小程序/微信服務號)無非就是調用微信的API、發通知欄消息(Push)無非就是調APNS/手機廠商的API、發IM消息也可以使用云服務,調云服務的API...

可能很多人的項目都是這么干的,無非發條消息,自己實現也不是不可以。

但這樣會帶來的問題就是在一個公司內部,會有很多個項目都會有「發送消息」的代碼實現。假設發消息出了問題,還得去自己解決。

首先是系統不好維護,其次是沒必要。我一個搞廣告的,雖然我要發消息,憑什么要我自己去實現?

我們在寫代碼時,可能會把公用的代碼抽成方法,供當前的項目重復調用。如果該公用的代碼被多個項目使用,可能我們又會抽成組件包,供多個項目使用。只要該公用的代碼被足夠多的人去用,那它就很有可能從組件上升為一個平臺(系統)級的東西。

如何實現消息管理平臺?

回到消息管理平臺的本質,它就是一個可以發消息的系統。那怎么設計和實現呢?我們從接口說起吧。

接口設計

消息管理平臺是一個提供消息發送服務的平臺,如果讓我去實現,我的想法可能是把每種類型的消息都寫一個接口,然后把這些接口對外暴露。

所以,可能會有以下的接口:

/** * content:發送的文案 * receiver:接收者 */  sendSms(String content,String receiver); sendIm(String content,String receiver); sendPush(String content,String receiver); sendEmail(String content,String receiver); sendTencent(String content,String receiver); //....

這樣實現好像也不是不可以,反正每個接口都挺清晰的,要發什么類型的消息,你調用哪個接口就好了。

假設我們定義了如上的接口,現在我們要發消息了,我們會有以下的場景:

  1. 文案:「你好,我是三歪」,接收人:「woshisanwai」 (一次只發給一個人)

  2. 文案:「你好,我是三歪」,接收人:「woshisanwai,java3y,javayyy」(相同的文案發給多個人)

假如你是新手,你可能會想:這簡單,我每種類型分開兩個接口,分別是單發和批量接口。

sendSingleSms(); sendBatchSms(); //...

上面這樣設計有必要嗎?其實沒啥必要。我將接收人定義為一個Array不就得了?Array的size==1,那我就把該文案發給這個人,Array的size>1,那我就把這個文案發給Array里邊的所有人。

所以我們的接口還是只有一個:

/** * content:發送的文案 * receiver:接收者(可多個,可單個) */ sendSms(String content,Set<String> receiver);

其實在我們這也不是定義Array,我的接口receiver仍然是String,如果有多個用,號分隔就可以了。

/** * content:發送的文案 * receiver:接收者(可多個,可單個),多個用逗號分隔開 */ sendSms(String content,String receiver);

現在還有個場景,不同的文案發給不同的人怎么辦?有的人就說,這不已經實現了嗎?直接調用上面的接口就完事了啊。你又不是不能重復調用,比如說:

  1. 文案:「你好,我是Java3y」,接收人:「woshisanwai」

  2. 文案:「你好,我是三歪」,接收人:「3y」

  3. 文案:「你好,woshisanwai」,接收人:「三歪」

  4. .....

確實如此,本來就可以這樣做的。但不夠好

舉個真實的場景:現在有一個主播開播了,得發送一條消息告訴訂閱該主播的人趕緊去看。為了提高該條通知的效果  ,在文案上我們是這樣設計的:{用戶昵稱},你訂閱的主播三歪已經開播了,趕緊去看吧!

這種消息我們肯定是要求實時性的(假設推送消息的速度太慢了,等到用戶收到消息了,主播都下播了,那用戶不得錘死你?)

畫外音:顯然這種情況屬于不同的文案發給不同的人

這種消息在業務層是怎么做的呢?可能是掃DB表,遍歷出訂閱該主播的粉絲,然后給他們推送消息。

那現在我們只能每掃出一個訂閱該主播的粉絲,就得調用send()接口發送消息。如果該主播有500W的粉絲,那就得調用500W次send接口,這不是很可怕?這調用次數,這網絡開銷...

于是乎,我們得提供一個“批量”接口,可以讓調用方一次傳入不同文案所攜帶不同的人。那怎么做呢?也很簡單,實際上就是上面接口再封裝一層,讓調用方能“批量”傳進來就好了。所以代碼可以是這樣的:

/** * 一次傳入多個(文案以及發送者)的“組”進來 * List<SendParam> * SendParam 里邊 定義了 content 和receiver */ sendBatchSms(List<SendParam> sendParam);

現在接口的“雛形”已經出現了,到這里我們實現了消息管理平臺最基本的功能:發消息

我們先不管內部的實現是如何,假設我們已經適配好調通好對應的API了,現在我們的接口在發消息層面上已經有充分必要的條件了:只要你傳入接收者和發送內容,我就可以給你發消息。

但我們對外稱可是一個平臺啊,怎么能搞得像是只封裝了幾個方法似的,平臺就該有平臺的樣子。

我舉個日常最最最基本的功能:有人調用了我的接口發了條短信,這條短信的文案是一條內容為驗證碼類型,他問我這條短信到底下發到用戶手上了沒有。

消息管理平臺的Java實現原理是什么

如果接入過短信的同學就會知道:發送短信到用戶收到是一個異步的過程

  • 調用短信提供商的API,假設你的入參沒有問題,它會告訴你“調用”成功。你想真正地知道此條內容到底有沒有下發到用戶手上,你有兩種辦法:一、提供一個接口給短信服務商調用,等真正處理完了,短信服務商會調用你的接口,告訴你最終的結果是什么。二、你去輪詢短信服務商的接口,獲取最終的結果。

消息管理平臺的Java實現原理是什么

回到問題上,他想要他調用我的接口有沒有把短信發送成功,那我只要問他拿到手機號和文案,然后有以下步驟:

  1. 判斷該手機號和文案在下發時是否正常(有沒有真正調用下發短信的接口)

  2. 假設調用短信接口下發成功,那看下返回的回執(下發結果)是否正常

那目前我們在現有的接口,還是很完美地支持上面的問題的,對吧?只要我們記錄了下發的結果和回執的信息,我們就可以告訴他所提供的手機號和文案究竟有沒有下發到用戶手上。

那今天他又過來問了:今天有很多人來反饋收不到驗證碼短信(不是全部人收不到,是大部分人),我想了解一下今天驗證碼短信下發的成功率是多少。

此時的我,只能去匹配(like %%)他的文案調用我的接口下發了多少人,調用短信服務商的API下發成功多少人,收到的成功回執(結果)有多少人。

通過匹配文案的方式最終也是可以告訴他結果的,但是這種是很傻X的做法。歸根到底還是因為系統提供的服務還是太薄弱了。

那怎么解決上面所講的問題呢?其實也很簡單,既然匹配文案很傻X,那我給他這一批驗證碼的短信取個唯一的Id那不就可以了嗎?

像我們去接入短信服務商一樣,我們需要去新建一個短信模板,這個模板代表了你要發送的內容,新建模板后會給你個模板Id,你下發的時候指定這個模板Id就好了。

消息管理平臺的Java實現原理是什么

那我們的平臺也可以這樣玩啊,你想發消息對吧?可以,先來我的平臺新建一個”模板“,到時候把模板Id發給我就行。

于是,我們就完美地解決上面所提到的問題了。

我們現在再來討論一下有沒有必要不同的消息類型(短信、郵件、IM等)需要分開不同的的接口,其實是沒必要的了。因為只要抽象了”模板“這個概念,消息類型自然我們就可以在模板上固化掉,只要傳了模板Id,我就知道你發的是什么類型消息。

這樣一來,我們最終會有兩個接口:批量與單個發送接口。

/**  * 發送消息接口  * @author java3y  */ public interface SendService {      /**      * 相同文案,發給0~N 人      * @param sendParam      */     void send(SendParam sendParam);      /**      * 不同文案,發給不同人,一次可接收多組      * @param sendParam      */     void batchSend(BatchSendParam sendParam); }  public class SendParam {      /**      * 模板Id      */     private String templateId;      /**      * 消息參數      */     private MsgParam msgParam; }  public class MsgParam {      /**      * 接收者:假設有多個,則用「,」分隔開      */     private String receiver;      /**      * 自定義參數(文案)      */     private Map<String, String> variables;  }

單個接口指的是:一次給1~N人發送消息,這批人收到的是相同的文案

批量接口指的是:一次給1個人發送一個文案,但一次調用可以傳N個人及對應的文案

這里的單個和批量不是以發送人的維度去定義的,而是人所對應的消息文案。

再再再舉個例子,現在我給關注我的同學都發一條消息:「大哥大嫂新年好」,這種情況我只需要使用send方法就好了,相同的文案我給一批人發,這批人收到的文案是一模一樣的。

一次單推接口調用的請求參數:

{     "templateId": 12345,     "msgParam":          {              "receivers": "三歪,敖丙,雞蛋,米豆",             "variables": {                 "content": "大哥大哥新年好",                 "title": "來個贊吧,親"             }         } }

如果我要給關注我的同學都發一條消息:「{微信用戶名},大哥大哥新年好」,這種情況我一般用batchSend方法,在發送之前組合人所對應的文案封裝成一個List,一次調用接口對調用方而言就是一次發了List.size()組人。

一次批量接口調用的請求參數:

{     "templateId": 12345,     "msgParam": [         {              "receivers": "敖丙",             "variables": {                 "content": "敖丙,大哥大哥新年好",                 "title": "來個贊吧,親"             }         },         {             "receivers": "雞蛋",             "variables": {                 "content": "雞蛋,大哥大哥新年好",                 "title": "來個贊吧,親"             }         }     ] }

沒想到單單接口這塊我這篇就寫了這么長,主要是照顧沒有經驗的同學哈~

回顧設計接口的思路:

  1. 起初是想每種消息類型分開不同的接口

  2. 考慮到同一個文案會下發給多個人,所以接收者參數得是支持”批量“的傳入

  3. 考慮到會有批量調用接口的場景,所以需要一個批量接口

  4. 考慮到需要統計下發消息的場景,所以需要抽象出”模板“,在平臺下發的消息都得有”模板“

  5. 有了”模板“,可以將很多信息固化到模板中,所以最終我們抽象出兩個接口:單推和批量。

再來聊聊模板

在前面我們已經定義好接口了,跟簡單你們所實現的發消息功能最主要的區別就是多了”模板“的概念。

在上面提到了一點:有了”模板“,可以將很多信息固化到模板中。那我們固化了什么東西到模板中呢?

  • 能夠發送的消息種類。消息管理平臺是可以發多種類型的消息的,所以我們模板是需要有字段區分不同的消息類型。別想得這么難,其實我們就用1表示短信,2表示郵件...

  • 模板創建者信息(手機號、姓名),這個跟發消息的實質內容沒有任何關系,只是如果模板出現了什么不可描述的問題,背鍋俠總得找出來吧,如果模板創建者離職了怎么辦?沒事,我會根據創建者把所在部門給找到,那就找部門背鍋(嘿嘿)

  • 消息的文案。綜合上面所看到的消息,我們可以看到一條消息無非由以下部分所組成:內容、標題、圖片、鏈接、視頻...不同的消息能發的文案也不一樣,像短信頂多就只有內容和鏈接,而像通知欄消息(Push)就可以有標題、內容、圖片、鏈接所組成。所以,我們會把消息的文案用json的格式存儲在一個字段中。

  • 消息的業務規則。這里所講的業務規則并不是真正的細節業務,而是對不同消息類型上的平臺性約束。比如說,在產品層面上,希望晚上用戶收不到通知欄推送(畢竟會對用戶進行打擾);希望用戶一個小時內不會接收到兩條,一天最多收到N條通知欄推送(也是出于用戶的體驗)。這些平臺性的約束就適合放在消息管理平臺上做,你可以理解為是一個兜底的功能。

  • 發送賬號。什么?發條消息還有賬號的概念?你搞錯了吧,三歪?。其實是真的有的,在發郵件的時候可以選取不同的郵件賬號,在發微信公眾號消息時可以選取不同的微信公眾號(小程序同理),在發IM消息時可以使用不同的賬號發送。而在接入短信的時候其實是分了兩種類型的:通知和營銷。我們會把這些都抽象為賬號。

  • 接收者Id類型。站內的IM消息用的是站內的userId,發通知欄消息(PUSH)用的是did,發短信用的是手機號,發微信類的消息用的是openId。指定接收者的Id類型,表明這個模板你要傳入哪種類型的id。假設你指明是userId,但你要發短信,消息管理平臺就需要將userId轉成手機號。這里也是用一個字段標識,1表示userId,2表示did  ...

可以發現的是,我們把一條消息所需要的信息(甚至不需要的信息)都塞進模板里面了,等調用方傳入模板Id時,我就能拿到我想要的所有信息了。

這是一個模板的全部了嗎?當然不是咯。上面提到的是模板共性的內容,我們按模板的使用場景還劃分兩種類型:

  • 運營模板:運營要給指定一批人在某時某刻發送消息。(這一批人是T+1離線的)。例子:如果用戶注冊登錄了APP,可以隔一天(甚至更長時間)給用戶發消息。這種屬于非實時(離線)推送,這種就不需要技術來承接,去圈選人群后設置對應的時間即可推送。

  • 技術模板:系統根據業務條件自動觸發一批消息,接收者名單也依賴業務場景(這批人一般是實時的)。例子:如果用戶注冊登錄了APP,就立馬需要給該用戶發消息。這種屬于實時推送,需要對應的技術來承接。

隨著系統和業務的演進,運營模板和技術模板的界限會越來越模糊。從本質上就是提供了兩種發消息的方式:

  1. 圈定一批人群,通過使用定時任務到點調用接口觸發(接收者、文案、發送時間都已明確)。

  2. 技術調用接口發送消息(接收者,文案,發送時間均由業務邏輯所產生)。例子:歡迎關注三歪,你的驗證碼是:888。有內鬼,終止交易。(當你關注三歪時,系統觸發一條消息。發送時間、驗證碼值、人員均不確定)

用戶在平臺創建模板時,不同類型的模板需要填寫的字段是不一樣的:運營模板需要填寫人群和任務觸發時間,而技術模板壓根就不需要填人群和任務觸發時間,所以我們模板會有一個字段標識該模板是運營類型還是技術類型。1表示運營類型,2表示技術類型...

你覺得已經完了嗎?nonono,還沒有。我們還會區分消息的類型,目前最主要由三類組成:通知、營銷和驗證碼。

問題來了,為什么我們要區分消息的類型呢?做統計用嗎?當然不是了,就這幾個粒度的類型有什么好統計的。

還是以例子來說明吧:在2020-02-30日,運營同學圈選了一個5000W的人群選擇在晚上8點發送一條短信,大致的情況就是告訴用戶三歪文章更新了,不看血虧。系統在晚上8點準時執行任務,讀取該模板的模板信息下發。5000W人,系統能秒發嗎?顯然是不行的

畫外音:除了考慮自身的系統能力,還得考慮下游能承受的能力。你瞎搞,人家就不帶你玩了。

所以,這5000W人肯定是需要一定的時間才能完全下發的,現在我們假設是15分鐘完全下發完畢吧。在8點2分觸發了一條驗證碼的短信,結果因為這個5000W的人群所導致驗證碼的消息延遲發送,這合理嗎?顯然不合理。

怎么導致的?原因是這5000W的消息和驗證碼的消息走的是同一個通道,導致驗證碼的消息被阻塞掉了。我們將不同的消息類型走不同的通道,就可以解決掉上面的問題。

所以,我們的系統在設計層面上就把運營模板默認設置為營銷類型的消息,而技術模板的消息類型由調用者自行選擇。在現實場景中,能堵的就只有營銷類的消息。

消息管理平臺的Java實現原理是什么

畫外音:上面所講的這些實踐都是跟使用場景和具體業務所關聯的,肯定不是一朝一夕就可以全想出來的。

  • 模板也已經聊完了,還有些細節的東西我這就不贅述了。我再來簡要總結一下:

  • 我們把發送一條消息所必要的信息(文案、發送賬號、傳入的接收者Id類型、消息類型:通知、營銷和驗證碼)、平臺性的信息(業務規則:是否去重、屏蔽、展示邏輯等)和基本信息(業務方信息、消息名稱)全都塞到模板中

由于使用場景,模板會分為運營模板和技術模板。運營模板主要的特點是需要填寫人群信息和發送時間,運營模板由消息管理平臺自身進行調度發送消息。

接口實現

BB了這么久了,可能很多人只是想來看看:三歪這逼在標題還敢還寫個揭秘,發消息誰不會,不就調個API嘛,還能給你玩出花來?

別急嘛,現在就寫。前面已經鋪墊了接口的設計和模板究竟是什么了,現在我們還是回到接口的實現上吧。

首先我們簡單來看看消息管理平臺的系統架構鏈路圖:

消息管理平臺的Java實現原理是什么

畫外音:上面我們所說的接口定義在統一調用層(接入層)中

調用者調用我們的send/batchSend方法,會直接調用下游的API下發消息嗎?不會

直接調用下游的API下發消息風險太大了,接口1W+QPS都是很正常的事,所以我們接收到消息后只是做簡單的參數校驗處理和信息補全就把消息發到消息隊列上。這樣做的好處就是接口接入層十分輕量級,只要Kafka抗得住,請求就沒問題。

消息管理平臺的Java實現原理是什么

發到消息隊列時,會根據不同的消息類型發到不同的topic上,發送層監聽topic進行消費就好了。架構大致如下:

消息管理平臺的Java實現原理是什么

發送層消費topic后,會把消息放在各自的內存隊列上,多個線程消費內存隊列的消息來實現消息的下發。

可以看到的是:從接入層發到消息隊列上我們就已經做了分topic來實現業務上的隔離,在消費時我們也是放到各自的內存隊列中來進行消費。這就實現了:不同渠道和同渠道的不同類型的消息都互不干擾。

看到上面這張圖,如果思考過的同學肯定會問:這要內存隊列干啥啊?反正你在上層已經分了topic了,不用內存隊列也可以實現你所講的“業務隔離”啊。

也的確,這里使用內存隊列的主要原因是為了提高并發度。提高了并發度,這意味著下發速度可以更快(在下發消息的過程中,最耗時的還是網絡交互,像短信這種可以多開點線程進行消費)。

在前面所提到的業務規則就是在下發層這兒做的,包括夜間屏蔽、1小時去重和Id轉換等

  • 夜間屏蔽就是判斷是否在晚上,如果勾選了夜間屏蔽并且在晚上,過濾掉就好了

  • 1小時去重就是拿userId+消息渠道作為Key,看是否存在Redis上,假設存在,則過濾掉

  • id轉換這功能我們做成了個系統,這塊我放在下面簡單說一下吧,這就不在贅述了。

畫外音:這種場景最好使用Pipeline來讀寫Redis

隨后就是適配各個渠道的接口,調用API下發消息了,這塊就跟你們單個的實現沒什么大的區別了,調用個接口還能給你玩出花來?(代碼風格會稍好一些,模板方法模式、責任鏈、生產者與消費者模式等在項目中都有對應的應用)

總結一下接口的實現:

  1. 調用方調用接口時,接口不會同步直接調用下游的API發送消息,而是放入消息隊列上(支持高并發)

  2. 放入隊列時,會根據不同渠道以及不同類型的消息進行分類,放到不同的topic(業務隔離)

  3. 消費隊列時,會在本地使用阻塞隊列來提高并發度(加快消費的速度)

Id轉換

(擴展)在前面也提到了,發不同類型的消息會需要有不同的id類型:微信類需要openId、短信需要手機號、push通知欄推送需要did。

在大多數情況下,一般調用者就傳入userId給到我,我這邊需要根據不同的消息類型對userId進行轉換。

那在我們這邊是怎么實現該系統的呢?主要的步驟和邏輯有以下:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 監聽用戶變更和微信公眾號訂閱/取關的topic,在Flink清洗出一個統一的數據模型,將清洗后的數據寫到另一個的topic。

  3. Id映射系統監聽Flink清洗出的topic,實時寫到數據源(這里我們用的是搜索引擎)

看著也不會很難,對吧?

有沒有想過一個問題,為什么要用一個Id映射系統去監聽Flink洗出來的topic,而不是在Flink直接寫到數據源呢?

其實通過Flink直接寫到數據源也是完全沒問題的,而封裝了一個Id映射系統,就可以把這活做得更細致。

從描述可以發現的是:在上面只實現了實時增量。很多時候我們會擔心增量存在問題,導致部分數據的不準確或者丟失,都會寫一份全量,Id映射也是同樣的。

那Id映射的全量是怎么做的呢?用戶數據通過各種關聯關系會在Hive形成一張表,而Id映射的全量就是基于這張Hive表來實現全量(每天凌晨會讀取Hive表的信息,再寫一遍數據源)。

基于上面這些邏輯,專門給Id映射做了個后臺管理(可以手動觸發全量、是否開啟增量/全量、修改全量觸發的時間)

消息管理平臺的Java實現原理是什么

數據統計

我覺得這塊是消息管理平臺最最最精華的一部分。

夢回我們當初的接口設計環節,我們就是因為有“數據統計”的需求,才引入了模板的概念。現在我們已經有了一個模板Id了,在我們這邊是怎么實現數據的統計的呢?我們對消息的統計都是基于模板的維度來實現的。

在創建模板時就會有一個模板Id生成,基于這個模板Id,我們生成了一個叫做umpId的值:第一位分為技術/運營推送,最后八位是日期,中間六位是模板Id

消息管理平臺的Java實現原理是什么

因為所有的消息都會經過接入層,只要消息帶有鏈接,我們就會給鏈接后加上umpid參數,鏈接會一直下發透傳,直至用戶點擊

消息管理平臺的Java實現原理是什么

每個系統在執行消息的時候都會可能導致這條消息發不出去(可能是消息去重了,可能是用戶的手機號不正確,可能是用戶太久沒有登錄了等等都有可能)。我們在這些『關鍵位置』都打上日志,方便我們去排查。

這些「關鍵位置」我們都給它用簡單的數字來命個名。比如說:我們用「11」來代表這個用戶沒有綁定手機號,用「12」來代表這個用戶10分鐘前收到了一條一模一樣的消息,用「13」來代表這個用戶屏蔽了消息.....

「11」「12」「13」「14」「15」「16」這些就叫做「點位」,把這些點位在關鍵的位置中打上日志,這個就叫做「埋點」

有了埋點,我們要做的就是將這些點位收集起來,然后統一處理成我們的數據格式,輸出到數據源中。

  1. 收集日志

  2. 清洗日志

  3. 輸出到數據源

有logAgent幫我們收集日志到Kafka,實時清洗日志我們用的是Flink,清洗完我們輸出到Redis(實時)/Hive(離線)。

Hive表的數據樣例(主要用于離線報表統計):

消息管理平臺的Java實現原理是什么

Redis會以多維度來進行存儲,以便支撐我們的業務需要。比如,要查一條消息為何發送失敗,通過userId搜一下,直接完事(實時的都記錄在Redis中,所以這里讀取的是Redis的數據)

消息管理平臺的Java實現原理是什么

比如,通過模板Id,查某條消息的整體下發情況:

消息管理平臺的Java實現原理是什么

為什么我說這是消息管理平臺最最最精華的呢?umpId貫穿了所有消息管理平臺經過的系統,只要是在消息管理平臺發的消息,都會被記錄下來發送,可以通過點位來快速追蹤消息的下發情況。

消息管理平臺的Java實現原理是什么

總結一下數據統計:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 設計出業務上的umpid,給所有的消息推送鏈接都加上umpdId 參數

  3. 打通上下游,共同設計和維護關鍵點位,統一日志格式來實現跨平臺的收集和清洗

  4. 兼顧實時和離線需求寫到不同的數據源,實時以多維度統計來快速定位問題

聊聊運營層

面前面提到了,運營的模板是需要圈選一批人群,然后下發消息的,那這群人從哪里來?

在很久之前,消息管理平臺也把人群給做掉了,大致的思路就是可以支持文件上傳和hivesql上傳兩種方式去圈選人群,圈出來上傳到hdfs進行讀取,支持對人群的更新/切分/導出等功能。

有了人群的概念,你會發現你收到的消息其實都是跟你息息相關的(不是瞎給你推送的,你在里面,才能圈到你)。可能是因為你看了幾天的連衣裙,所以給你推送連衣裙的消息,吸引去你購買。

后來,由于公司內部DMP系統崛起,人群就都交由DMP給管理了。但實現的思路也都是類似的,只不過還是同樣的:人家做的是平臺,功能肯定比會自己寫幾個接口要完善不少。

做推送就免不了發錯了消息,特別是在運營側(分分鐘就推送千萬人),我們平臺又做了什么措施去盡可能避免這種問題的發生呢?

在運營圈定人群后,我們會有單獨的測試功能去「測試單個用戶」是否能正常下發消息,文案鏈接是否存在問題。

這一個步驟是必須要做的,給用戶發出的消息,首先要經過自己的校驗。如果確認鏈接和文案都無問題后,則提交任務,走工單審批后才能發送。

消息管理平臺的Java實現原理是什么

如果在啟動之后發現文案/鏈接存在問題,還可以攔截剩余未發的消息。

消息管理平臺的Java實現原理是什么

針對于(技術方推送),我們在預發環境下配置了「白名單」才能收到消息。

  • 線上消息有「去重」的邏輯:

  • 在某段時間內,過濾掉重復消息

運營類消息推送(圈定人群的方式去下發消息)同一個用戶需要相隔一段時間才能下發一次。

消息管理平臺的Java實現原理是什么

雖然說,我們制定了很多的規則去盡量避免事故的發生,但不得不說推送還是一個容易出現事故的功能。

“消息管理平臺的Java實現原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莱州市| 灵川县| 定结县| 磴口县| 丹阳市| 遂平县| 神农架林区| 新化县| 慈溪市| 广东省| 资源县| 浦东新区| 垣曲县| 南投县| 随州市| 临猗县| 封丘县| 仪陇县| 广西| 西乌珠穆沁旗| 安庆市| 盘锦市| 定远县| 瓦房店市| 巴东县| 华安县| 闸北区| 南城县| 南丰县| 宁城县| 璧山县| 星子县| 蓬莱市| 阜南县| 鄯善县| 潞城市| 竹北市| 洮南市| 兴山县| 甘德县| 太和县|