對於乙個可靠的im系統,需要保證訊息的百分之百到達對端。即使是在極端情況下丟失一條訊息也是不能容忍的。乙個極其極其低概率的事件,若是放大到分布式系統中,那這個概率事件就成了必然事件。在開發測試中如果發現一次偶然的訊息丟失問題而忽略不查,那上線之後就必然會發生訊息丟失。所以作為技術,一定不能放過任何乙個極端情況下發生的問題。
在伺服器給客戶端傳送訊息的過程中,有兩種方式,1.主動推送訊息給客戶端;2.客戶端來拉訊息。這兩種方式都可以達到目的,下面就來分析一下兩者的區別。
a -> server -> b
上述描述一種簡單模型,a給b傳送一條訊息,首先會到達伺服器,然後伺服器將訊息**給客戶端b。這是推的方式,伺服器是直接將訊息推給客戶端的。那在複雜的網路環境中,如何保證訊息能夠到達b端?
這個例子有兩處需要做保證,第一是如何保證a發出去的訊息成功到達伺服器。第二處是伺服器推給b的訊息如何知道已經成功送達。
本文主要分析第二條。
2.對於沒推成功的情況,伺服器增加重推的機制,客戶端收到訊息後給伺服器回覆確認,伺服器取消後續推送。
新增的邏輯引入新的複雜度,需要解決。
1.要確保成功將訊息儲存在伺服器,如果儲存失敗,算是丟失訊息。這樣就要對儲存失敗的情況做檢測。一種是明確知道存失敗了,另一種是後端服務超時,不知道有沒有存成功。儲存失敗可以重試,儲存超時也可以簡單認為是儲存失敗,再重試。只要保證多次儲存同一訊息是冪等操作就可以,防止存了兩條。
2.對於重推,伺服器要實現重推邏輯,把推送操作加到定時器裡面,同時快取這條訊息。超時未收到客戶端的確認就再推一次。由於網路原因或者客戶端卡住,會導致推送的訊息到達了客戶端,但是客戶端的確認一直沒有到達伺服器,導致伺服器推送了多次訊息,所以客戶端需要對訊息做重複訊息的過濾。其次是多次推送後,客戶端一直沒有回覆確認,這個可能是網路原因,客戶端真沒收到,也可能客戶端收到了,客戶端的確認還在路上,但是已經到了伺服器重推次數,伺服器決定要不要將訊息儲存到伺服器?鑑於客戶端實現了訊息過濾機制,此處可以簡單地儲存訊息到伺服器。這就走1的邏輯。後續客戶端再上線時拉服務端儲存的訊息,並做重複過濾。能保證訊息不丟失。
3.既然會拉取之前儲存在伺服器的訊息,那拉取完成之後需要將伺服器儲存的訊息刪除,這一步客戶端在確認收到訊息後再發刪除請求即可。否則每次都會拉一遍,耗費流量,而且訊息多了會導致登陸後的收訊息流程越來越卡,由於有過濾機制,不會出現重複訊息顯示。
上述是推的方式實現訊息可靠送達的複雜度。之間還有些邏輯沒包含進來,比如push。客戶端沒收到訊息應該改推push。那這樣一來推push的情況就有很多。公司之前的老系統是採用推的方式,我們在這一塊踩過很多坑,服務端的實現邏輯也相當複雜,各種判斷,包括存訊息到伺服器,重推訊息給客戶端,推push給客戶端,考慮多裝置問題,根據客戶端的確認做重推取消等等。個人看法是:相信我,如果這樣做,後果很嚴重,你會因頻繁的訊息丟失問題沉浸在複雜的**邏輯中無法自拔,甚至,開始懷疑人生。
接下來分析下拉訊息的實現方式。
a -> server -> b
b <--> server
拉的方式下,可以先將訊息儲存到伺服器,再來給傳送者和接收者推通知。如果訊息儲存失敗,就可以簡單回覆訊息傳送失敗給傳送者,讓傳送者手動重發。對於後續流程,如下:
如此可能出現的問題是訊息亂序。客戶端可以根據訊息在服務端的生成時間排序,可以解決這個問題。就是會出現訊息突然跳躍順序。
在實現中,客戶端拉訊息應該是按照msgid範圍拉一批訊息,而且在服務端的實現中,msgid要保證遞增,無重複。客戶端重新聯網後應先保證處理拉伺服器訊息的流程先走完,再處理新的訊息通知。防止新的訊息打亂上次的拉取邏輯,中間出現丟訊息的情況。
另外乙個問題是伺服器連續推過來n條訊息通知,客戶端是不是應答這n條訊息通知,去拉n次?因為客戶端一次會拉一批訊息,或許處理第一條的訊息通知就已經把後續的新訊息都拉下來了,後面的拉取就成了重複動作,會導致訊息拉重複了。這種問題也好解決,從伺服器拉取回來後,判斷最大msgid是否比收到的通知中msgid要大,如果是,就忽略小的通知,不拉。如果拉到的最大msgid要比通知裡的msgid小,就應該繼續拉取。當然,客戶端對訊息的重複過濾邏輯還是要有的。
這樣的做法是在網路互動上,多了一步通知和拉取,耗費一些客戶端的流量。服務端的實現邏輯複雜度大大降低,客戶端需要多處理一些邏輯。
這兩種方案,我個人傾向於拉的方式。然後其中有幾個技術實現細節後續再寫。比如如何保證在分布式環境下msgid連續遞增不重複,如何保證客戶端對訊息的排序,訊息同步的具體方案,服務端對訊息的儲存等。
總體而言,推的方案,服務端需要處理複雜的邏輯,客戶端需要處理的相對較少。拉的方案,服務端需要處理的邏輯比較簡單,客戶端需要配合做一些保證。對於訊息可靠的保證方面,個人傾向於拉的方案,更靠譜。
訊息中介軟體 推還是拉
訊息系統內有兩個角色 消費者和生產者 需求是生產者產生了乙個業務內容,需要給消費者,這裡可以引入兩種方式來處理 1.生產者直接推內容給消費者 代表 apache flume 1 優點 i.開發方便。2 缺點 i.生產者決定內容推送速率,不同消費速率的消費者不好處理。ii.如果生產者推送內容速度大於消...
orace erp拉式物料和推式物料的區別
理解1 簡單地說,成本低廉 數量不易統計 不易分割地物料都屬於拉式物料 比如螺釘 成本低廉 單位為公斤 瓶 公尺等 不易分割 的物料 oracle的erp系統中 拉式物料是依任務需求自動扣庫存的,推式就是需依任務需求手工發料 理解2 在生產製造中有兩種工作方式,一種是推式工作方式,另一種是拉式。兩種...
觀察者模式中,訊息採用推和拉方式來傳遞的比較
觀察者模式,指的是定義一種物件間的一對多的關係,當乙個物件的狀態發生變化的時候,所有依賴於它的物件都將得到通知並更新自己。現在要說的分歧在這裡 推 的方式是指,subject維護乙份觀察者的列表,每當有更新發生,subject會把更新訊息主動推送到各個observer去。拉 的方式是指,各個obse...