android編譯grpc
『壹』 android集成Grpc,使用grpc進行數據交互網路通信
集成
1、首先在project的gradle文件中的dependencies里進行如下配置
2、在app的gradle文件中操作
在最頂部添加
添加protobuf編譯器
添加grpc的相關引用
ok好了至此已經集成完畢了,接下來就是使用了含逗
proto生成java文件
(1) 把自己的proto文件復制粘貼到芹老讓main/proto目錄下,點擊Android Studio中的Build菜單下的Rebuild Project即可
(2) Java文件生成位置:app/build/generated/source/proto/……
(3) 將Java文件嫌局復制出來即可使用
『貳』 gRPC入坑記
概要
由於gRPC主要是谷歌開發的,由於一些已知的原因,gRPC跑demo還是不那麼順利的。單獨寫這一篇,主要是gRPC安裝過程中的坑太多了,記錄下來讓大家少走彎路。
主要的坑:
本文講解gRPC demo的同時,會介紹如何解決這些坑。本文對應的Github地址:https://github.com/52fhy/grpc-sample 。該倉庫存儲了demo示例,以及部分系統編譯好的二進制包,大家覺得有些步驟里耗時實在太長了,可以直接clone該倉庫,復制二進制包到對應目錄(僅限測試開發,生產環境還是老老實實自己編譯吧)。
升級GCC
gRPC命令行工具編譯需要使用 GCC4.8及以上版本。CentOS6系列的內置版本是GCC4.7。
如果你的系統GCC版本>=4.8,可以忽略本節。如果僅使用golang、java,請忽略本節。
如果需要升級gcc至4.8或更高版本,建議直接採用安裝SCL源之後安裝devtoolset-6(devtoolset-6目前gcc版本為6.3),因為devtoolset-4及之前的版本都已經結束支持,只能通過其他方法安裝。
升級到gcc 6.3:
需要注意的是scl命令啟用只是 臨時 的,退出shell或重啟就會恢復原系統gcc版本。如果要長期使用gcc 6.3的話:
這樣退出shell重新打開就是新版的gcc了。其它版本同理。
升級到gcc 7.3:
已經停止支持的devtoolset4(gcc 5.2)及之前版本的安裝方法,可能比較慢,大家感興趣的話可以嘗試。
編譯gRPC命令行工具
gRPC分C、JAVA、GO、NodeJS版本,C版本包括C++, Python, Ruby, Objective-C, php, C#,這些語言都是基於C版本開發的,共用代碼庫一個代碼庫。
如果使用C版本的gRPC,最終要從源碼里編譯出下列工具:
這些工具作為插件供proto編譯器使用。需要先下載 grpc/grpc github上的源碼。
這里有2個坑:
1、grpc/grpc倉庫比較大,鑒於國內訪問的網速,建議使用國內鏡像。碼雲(https://gitee.com)提供了同步更新的鏡像地址:
這樣下載速度提高了不少。
2、git submole update這個命令實際就是在下載.gitmoles文件里定義的第三方依賴項到third_party目錄,這個依賴項有很多,大家可以打開.gitmoles文件查看下詳情。依賴的倉庫都在github上,下載沒幾個小時是下載不下來的,就等著慢慢下載吧。
回頭想想,我們花費了很多時間,結果只是為了得到grpc的proto編譯插件。
PHP相關支持
PHP暫時不支持作為grpc的服務端。作為客戶端是可以的,需要機器安裝:
其中protoc和protobuf c擴展已經在 Protobuf 小試牛刀 介紹過了,這里不再贅述。上一小節里如果安裝成功,那麼grpc_php_plugin也是有了的。下面介紹如何安裝PHP版的gRPC庫。
安裝grpc c擴展:
要求:GCC編譯器需要4.8及以上版本。可以使用pecl安裝:
也可以指定版本:
或者下載源碼(http://pecl.php.net/package/grpc)安裝:
grpc/grpc代碼庫里也有PHP擴展的C源碼,在grpc/src/php/ext/grpc目錄,進去也可以直接編譯。
編譯完成後在php.ini里添加,使用php --ri grpc可以查看信息。
安裝完C擴展後,還需要使用composer安裝grpc的庫:
gRPC示例
編寫gRPC proto
一共定義了三個文件:
其中 User 作為 Model定義,Response 用於 RPC統一返回定義,GreeterService 則是服務介面定義。
限於篇幅,proto文件詳見 https://github.com/52fhy/grpc-sample 倉庫的proto目錄。
GreeterService.proto文件內容如下:
這裡面定義了一個service,相當於定義了一個服務介面,我們把方法名、參數定義好了,後面需要去實現它。由於gRPC不支持PHP作為服務端,這里我們使用Golang作為服務端。
首先需要使用proto工具編譯出golang的代碼:
執行成功,會在 Pb_Go目錄里生成Go代碼:
如果需要生成PHP客戶端的代碼,則需要使用grpc php的命令行工具grpc_php_plugin,前面小結如果執行成功,這個工具已經有了。然後:
最終生成的文件:
注意:編譯那裡如果我們不加--grpc_out=../$out --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin,生成的PHP類是沒有GreeterClient的。這個文件是gRPC編譯工具自動生成的,用於連接gRPC服務端。
go編寫服務
我們用Golang寫服務端。上面雖然生成了Golang的部分代碼,但真正的服務還沒有寫呢。
main.go
首先我們新建個main.go,代碼不多,我直接貼出來:
然後就可以編譯了。
有個大坑:go build main.go的時候會先下載go.mod里定義的依賴(依賴比較多,詳情查看:https://github.com/52fhy/grpc-sample/blob/master/go.mod),其中下面這條非常慢,倉庫太大了,雖然重定向到github:
為了快速下載,我在碼雲上做了鏡像,地址:gitee.com/52fhy/google-api-go-client 。改了之後下載快多了。
編譯成功後,生成了二進制文件main。我們可以直接運行:
go test
為了測試我們寫的服務是否正常,可以寫測試用例:
test_client.go
運行:
運行有點慢,感覺依賴的庫多了。
php客戶端
使用gRPC PHP客戶端,確保你已經安裝了:
示例:
client_test.php
運行後輸出:
常見問題
1、CentOS6使用 go mod獲取第三方依賴包unknown revision xxx錯誤
解決:其實go mod調用鏈中會用到一些git指令,當git版本比較舊時,調用失敗產生錯誤,並給出歧義的提示信息。方法就是升級git版本,CentOS6自帶的git是1.7版本。升級完畢後,再嘗試go mod。
快速升級方法:
centos6:
2、PHP報錯:Fatal error: Class ' not found
解決:請安裝PHP的protobuf c擴展。
3、PHP報錯:Fatal error: Class 'GrpcBaseStub' not found
解決:使用composer require grpc/grpc安裝grpc。另外對應的grpc C擴展也要安裝。
4、下載 github release包很慢怎麼辦?
解決:下載Mac版 Free Download Manager 下載工具可以解決Github 下載緩慢或失敗問題。速度嗖嗖的。
參考
1、為CentOS 6、7升級gcc至4.8、4.9、5.2、6.3、7.3等高版本
http://www.vpser.net/manage/centos-6-upgrade-gcc.html
2、centos 6.x/7.x使用yum升級git版本 - 夜空
https://blog.slogra.com/post-721.html
3、Protobuf 小試牛刀 - 飛鴻影
https://www.cnblogs.com/52fhy/p/11106670.html
(本文完)
『叄』 對GRPC的通用封裝
通過封裝將grpc的技術使用難度降低到普通Java程序的開發。
cn.com.yd.commons.grpc提供了4種形式的服務介面定義以適應不同的應用場景。
cn.com.yd.commons.grpc將請求參數和響應參數定義為bytes以統一因業務不同而導致的差異性;使用cglib進行動態代理,在grpc的方法中執行具體的業務處理。
在具體應用中應將此工程使用Maven打包後作為依賴引入目標工程中。
JDK:1.8
GRPC:1.6.1
Protobuf:3.3.0
cglib:3.2.5
IDE:開發工具IDEA
IDEA自帶插件支持grpc開發,所以開發工具選擇IDEA。在正式開始之前需要先安裝Protobuf Support插件。
依次點擊Intellij中的「File」-->"Settings"-->"Plugins"-->"Browse repositories",如圖
輸入Protobuf,如下所示
在main目錄下新建一個名為proto的隱鋒文件夾,請森肢確保文件夾的所處位置以及名稱都正確,否則將不能進行編譯,而且不報任何錯誤。
proto文件編寫完成灶春晌後進行編譯以生成對應的class文件,編譯後的效果大致如圖
其中包含了Request、Response與JSONObject之間的轉換等,主要是對應用的輔助。
暫不公開。
『肆』 Uber實時推送平台是如何打造的
原文:Uber』s Real-Time Push Platform
譯者:LZM
Uber 建立的出行平台每天在處理全球數以百萬計的打車訂單。
實時打車市場是一個十分活躍的市場。一次行程包括多個參與者(乘客、司機),他們需要能在 APP 上實時查看、修改當前旅程的狀態。因此,Uber 需要保證每個參與者和他們的 APP 實時同步相關信息,無論是接車時間、達到時間還是行駛路線和附近的司機。
今天,手機端呈現的功能日益豐富,而這些功能對實時信息同步的需求也逐漸增多。本文將介紹 Uber 工程團隊如何把 Uber 平台信息同步機制從輪詢轉為基於 gRPC 的雙向消息流協議。
在 Uber 後台,一個行程連接了現實世界中的乘客和司機。在行程過程中,這兩個實體需要實時更新後台系統的信息。
我們思考一個場景:乘客發出打車請求,而司機在系統上等待接單。Uber 配對系統在後台自動匹配二者,向司機發送訂單。到此為止,每一方(乘客、司機、後台)應該彼此同步他們的內容。
如果一個新訂單帶來,司機 APP 會每隔幾秒輪詢一次信息以及時更新訂單狀態。與此同時,乘客 APP 也會每隔幾秒輪詢一個信息來查看司機時候接單。
輪詢的頻率由數據改變的速率決定。對於一個大型 APP(例如 Uber APP),這個變化速率從幾秒到幾個小時不等,變化范圍十分寬泛。
80% 的後台 API 請求都是來自客戶端的輪詢請求。激進的輪詢策略能讓 APP 的消息保持最新,但也會導致伺服器資源耗盡。任何輪詢過程中的 bug 都可能頻繁導致後台負載顯著加劇,甚至崩潰。隨著需要動態實時數據的功能的增加,這個方法變得不再可行。
輪詢會導致更快的電池消耗、應用程序延遲和網路級擁塞。這在城市中使用 2G/3G 網路或網路不穩定的地方尤其明顯。在這些地方,應用程序每次嘗試拉取信息時,都會重試多次。
隨著功能增加,開發者們嘗試重載輪詢 API 或重建一個新的 API。在高峰期,APP 同時向多個 API 發送輪詢請求。每個 API 負載數個功能。這些輪詢 API 本質上成為一組分片負載 API。但是,在 API 級別上保持一致性和邏輯分離仍然是一個越來越大的挑戰。
冷啟動問題是其中最具挑戰性的問題之一。每當 APP 啟動,所有功能都希望從後台獲取最新狀態,以渲染用戶界面。這導致多個 API 並發競爭,APP 不能成功渲染出正常界面,直到關鍵組件的消息被返回。在沒有優先順序的情況下,因為所有的 API 都有一些關鍵信息,所以應用載入時間會持續增加。糟糕的網路條件會進一步惡化冷啟動問題。
很明顯,我們需要一個徹頭徹尾的、對消息同步機制的改變。我們開啟了建立一個全新的實時推送平台的旅程。在這個平台上,伺服器可以根據需要向應用程序發送數據。當我們採用這種新架構時,我們發現效率有顯著的改進,同時也解決了不同的問題和挑戰。
接下來,來看看我們對推送平台的幾代改進以及該平台是如何演變的。
雖然使用消息推送是取代輪詢的自然選擇,但在如何構建推送機制上有很多需要考慮的問題。四個主要設計原則如下:
1)從輪詢到推送的簡單遷移
目前存在大量端設備在進行輪詢。新系統必須利用現有的、分配給輪詢 API 的負載和邏輯,而不是完全推倒重來。
2)簡易開發
與開發輪詢 API 相比,開發人員在推送數據方面不應該做截然不同的事情。
3)可靠性
所有消息應該通過網路可靠地發送到客戶的 APP 上,並在發送失敗時重試。
4)高效率
隨著 Uber 在發展中國家的迅速發展,數據使用成本對我們的用戶來說是一個挑戰,對於每天要在 Uber 平台上呆上幾個小時的司機來說尤其如此。新協議必須最小化伺服器和移動應用程序之間的數據傳輸量。
我們將這個消息推送系統命名為 RAMEN (Realtime Asynchronous MEssaging Network,實時非同步消息網路)。
任何時候,實時信息都在變化。消息的生命周期開始於決定生成一條信息的那一刻。微服務 Fireball 用於決定何時推送消息。很大部分決策都由配置文件決定。Fireball 在系統間監聽多種類型的事件,並決定是否推送給該消息涉及的客戶。
例如,當一個司機加單,司機和行程的狀態都會改變,並觸發 Fireball。之後,根據配置文件的內容,Fireball 決定何類消息應該推送給客戶。通常,一個觸發器會向多個用戶發送多個消息。
任何事件都可能被觸發器捕獲,例如一些客戶行為(如發出打車請求、打開 APP)、定時器到期、消息匯流排上的後端業務事件或是地理上的駛出 / 駛入事件。所有這些觸發器都被過濾並轉換為對各種後台 API 的調用。這些 API 需要客戶的上下文信息,如設備定位、設備的操作系統以及 APP 的版本號,來生成一個響應。Fireball 獲取設備上下文 RAMEN 伺服器,並在調用 API 時將它們添加到頭部。
所有來自 Uber APP 的伺服器調用都由我們的 API 網關提供。推送有效負載以同樣的方式生成。一旦 Fireball 決定了推送消息的對象和時間,API 網關就負責決定推送什麼。網關會調用各類域服務來生成正確的推送負載。
網關中的所有 API 在如何生成有效負載方面是相似的。這些 API 分為拉取式和推送式兩種。。拉取式 API 由移動設備調用來執行任何 HTTP 操作。推送 API 由 Fireball 調用,它有一個額外的 「推送」 中間件,可以攔截拉取式 API 的響應,並將其轉發給推送消息系統。
將 API 網關介乎於二者之間有以下好處:
l 拉式和推式 API 共享端設備上的大部分業務邏輯。一個給定的負載可以從拉式 API 無縫切換到推式 API。例如,無論你的 APP 是通過拉式 API 調用拉出一個客戶對象,還是 Fireball 通過推式 API 調用發送一個客戶對象,他們都使用相同的邏輯。
l 網關負責處理大量業務邏輯,如推送消息的速率、路由和消息驗證。
在適當的時候,Fireball 和網關一起生成發送給客戶的推送消息。負責將這些信息傳遞到移動設備的是 「推送消息傳遞系統」。
每條消息推送會根據不同的配置執行,這些配置項包括:
1)優先順序
由於為不同的用例生成了數百個不同的消息負載,因此需要對發送到 APP 的內容進行優先排序。我們將在下一節中看到,我們採用的協議限制在單個連接上發送多個並發負載。此外,接收設備的帶寬是有限的。為了給人一種相對優先順序的感覺,我們將信息大致分為三個不同的優先順序:
l 高優先順序:核心功能數據
l 中優先順序:其他有助於提升客戶體驗的功能數據
l 低優先順序:需要發送的數據規模大且使用頻率不高
優先順序配置用於管理平台的多種行為。例如,連接建立後,消息按照優先順序降序排列在套接字(socket)中。在 RPC 失敗的情況下,通過伺服器端重試,高優先順序消息變得更加可靠,並且支持跨區域復制。
2)存活時間
推送消息是為了改善實時體驗。因此,每個消息都有一個預先定義的生存時間,從幾秒到半個小時不等。消息傳遞系統將消息持久化並在發生錯誤時重試傳遞消息,直到有效值過期為止。
3)去重復
當通過觸發器機制或重傳機制多次生成相同的消息時,此配置項確定是否應該刪除重復的消息推送。對於我們的大多數用例,發送給定類型的最新推送消息足以滿足用戶體驗,這允許我們降低總體數據傳輸速率。
消息推送系統的最後一個組件是實際的有效負載交付服務。該服務維持著與世界各地數百萬 APP 程序的活躍連接,並在它們到達時將有效信息同步。世界各地的移動網路提供了不同級別的可靠性,因此傳輸系統需要足夠魯棒以適應故障。我們的系統保證 「至少一次」 交貨。
為了保證可靠傳輸,我們必須基於 TCP 協議,建立從應用程序到數據中心的持久連接。對於 2015 年的一個應用協議,我們的選擇是使用帶有長輪詢、網路套接字或最終伺服器發送事件 (SSE) 的 HTTP/1.1。
基於各種考慮,如安全性、移動 SDK 的支持和數據大小的影響,我們決定使用 SSE。Uber 已經支持了 HTTP + JSON API 棧,它的簡單性和可操作性使它成為我們當時的選擇。
然而,SSE 是一種單向協議,即數據只能從伺服器發送到應用程序。為了提供之前提到的 「至少一次」 的保障,需要確認和重傳機制以構建到應用程序協議之上的交付協議中。在 SSE 的基礎上,我們定義了一個非常優雅和簡單的協議方案。
客戶端開始接收第一個 HTTP 請求的消息 /ramen/receive?seq=0,在任何新會話開始時序列號為 0。伺服器以 HTTP 200 和 「Content-Type: text/event-stream」 響應客戶端以維護 SSE 連接。接下來,伺服器將按照優先順序降序發送所有掛起的消息並依次遞增序列號。由於底層傳輸協議是 TCP 協議,如果沒有交付帶有 seq#3 的消息,那麼該連接應該已斷開、超時或失敗。
客戶端期望在下一個看到的帶有最大序列號重新連接 (在本例中 seq=2)。這就告訴了伺服器,即使編號 3 寫到了套接字上,它也沒有被正常傳遞。然後伺服器將重新發送相同的消息或以 seq=3 開始的任何更高優先順序的消息。該協議構建了流連接所需的可恢復性,伺服器負責大部分的存儲工作,在客戶端實現起來非常簡單。
為了獲知鏈接是否存活,伺服器每 4 秒會發送一個心跳包,這類數據包大小隻有一個比特。如果超過 7 秒沒有收到來自伺服器的消息或心跳,客戶端會認定服務終端並重新發起鏈接。
在上面的協議中,每當客戶端重新以一個更高的序列號發起連接時,它就充當伺服器刷新舊消息的確認機制。在一個環境良好的網路中,用戶可能會保持連接數分鍾,從而導致伺服器不斷積累舊消息。為了緩解這個問題,應用程序會每 30 秒一次調用 /ramen/ack?seq=N,不管連接質量如何。協議的簡單性允許用許多不同的語言和平台非常快速地編寫客戶端。
在設備上下文存儲上,RAMEN 伺服器在每次建立連接時存儲設備上下文,並將此上下文暴露給 Fireball。每個設備上下文的 id 是用戶及其設備參數對應的唯一哈希值。這允許隔離推送消息,即使用戶在不同的設置下同時使用多個設備或應用程序。
第一代 RAMEN 伺服器使用 Node.js 編寫,並使用 Uber 內部的一致性哈西 / 分片框架 Ringpop。Ringpop 是一個去中心化的分片系統。所有連接都使用用戶的 UUID 進行分片,並使用 Redis 作為持久性數據存儲。
在接下來的一年半時間里,消息推送平台在整個公司得到了廣泛的應用。高峰期時,RAMEN 系統通過維持高達 60 萬個並發數據流連接,每秒向三種不同類型的應用程序推送超過 70000 個 QPS 消息。該系統很快成為伺服器 - 客戶端 API 基礎結構中最重要的部分。
隨著通信量和持久連接的快速增加,我們的技術選擇也需要擴展。基於 Ringpop 的分布式分片是一個非常簡單的架構,不會隨著 ring 中的節點數量的增加而動態擴展。Ringpop 庫使用一種 gossip 協議來評估成員資格。gossip 協議的收斂時間也隨著環的大小增加而增加。
此外,Node.js 是單線程的,並且會有更高級別的事件循環延遲,從而進一步延遲成員信息的收斂。這些問題可能引發拓撲信息不一致,進而導致消息丟失、超時和錯誤。
2017 年初,我們決定重新啟動 RAMEN 協議的伺服器實現,以繼續擴大應用規模。在這次迭代中,我們使用了以下技術:Netty、Apache Zookeeper、Apache Helix、Redis 和 Apache Cassandra。
1)Netty: Netty 是一個用於構建網路伺服器和客戶端的高性能庫。Netty 的 bytebuf 允許零拷貝緩沖區,這使得系統非常高效。
2)Apache ZooKeeper: Apache ZooKeeper 對網路連接進行一致性哈希,可以直接傳輸數據,不需要任何存儲層。但是與分散的拓撲管理不同,我們選擇了 ZooKeeper 的集中共享。ZooKeeper 是一個非常強大的分布式同步和配置管理系統,可以快速檢測連接節點的故障。
3)Apache Helix: Helix 是一個健壯的集群管理框架,運行在 ZooKeeper 之上,允許定義自定義拓撲和重新平衡演算法。它還很好地從核心業務邏輯中抽象出拓撲邏輯。它使用 ZooKeeper 來監控已連接的工作者,並傳播分片狀態信息的變化。它還允許我們編寫一個自定義的 Leader-Follower 拓撲和自定義的漸進再平衡演算法。
4)Redis 和 Apache Cassandra: 當我們為多區域雲架構做准備時,有必要對消息進行正確的復制和存儲。Cassandra 是一個持久的跨區域復制存儲。Redis 被用作 Cassandra 之上的容量緩存,以避免分片系統在部署或故障轉移事件中常見的群發問題。
5)Streamgate: 這個服務在 Netty 上實現了 RAMEN 協議,並擁有所有與處理連接、消息和存儲相關的邏輯。該服務還實現了一個 Apache Helix 參與者來建立與 ZooKeeper 的連接並維護心跳。
6)StreamgateFE (Streamgate Front End): 該服務充當 Apache Helix 的旁觀者,從 ZooKeeper 上偵聽拓撲變化。它實現了反向代理。來自客戶機 (火球、網關或移動應用程序) 的每個請求都使用拓撲信息進行分片,並路由到正確的 Streamgate 工作程序。
7)Helix Controllers: 顧名思義,這是一個 5 節點的獨立服務,單獨負責運行 Apache Helix Controller 進程,是拓撲管理的大腦。無論何時任何 Streamgate 節點啟動或停止,它都會檢測到更改並重新分配分片分區。
在過去的幾年中,我們一直在使用這種架構,並且實現了 99.99% 的伺服器端可靠性。我們推動基礎設施的使用持續增長,支持 iOS、Android 和 Web 平台上的十多種不同類型的應用程序。我們已經使用超過 1.5M 的並發連接來操作這個系統,並且每秒推送超過 250,000 條消息。
伺服器端基礎設施一直保持穩定運行。隨著我們為更多新城市提供各種各樣的網路服務和應用程序,我們的重點將是繼續提高向移動設備消息推送機制的長尾可靠性。我們一直在試驗新協議、開發新方法,以彌合和現實需求的差距。在檢查以往的不足時,我們發現以下方面是導致可靠性下降的原因。
1)缺乏認證
RAMEN 協議在減少數據傳輸進行了優化,僅在每 30 秒或客戶端重新連接時才發送確認消息。這將導致延遲確認,在某些情況下無法確認消息達到,因此很難區分是真正的消息丟失還是確認失敗。
2)連接不穩定
維持客戶端和伺服器的正常連接至關重要。跨不同平台的客戶端實現方式在處理錯誤、超時、後退或應用生命周期事件 (打開或關閉)、網路狀態更改、主機名和數據中心故障轉移等方面有許多細微差別。這導致了不同版本間的性能差異。
3)傳輸限制
由於該協議在 SSE 協議基礎上實現,因此數據傳輸是單向的。但是,許多新的應用程序要求我們啟用雙向消息傳輸機制。沒有實時的往返行程時間測量,確定網路狀況、傳輸速度、緩解線路阻塞都是不可能的。SSE 也是一個基於文本的協議,它限制了我們傳輸二進制有效負載的能力,不需要使用像 base64 這樣的文本編碼,從而獲得更大的有效負載。
2019 年底,我們開始開發下一代 RAMEN 協議以解決上述缺點。經過大量考量,我們選擇在 gRPC 的基礎上進行構建。gRPC 是一個被廣泛採用的 RPC 棧,具有跨多種語言的客戶端和伺服器的標准化實現,對許多不同的 RPC 方法提供了一流的支持,並具有與 QUIC 傳輸層協議的互操作性。
新的、基於 gRPC 的 RAMEN 協議擴展了以前基於 SSE 的協議,有幾個關鍵的區別:
l 確認消息立即通過反向流發送,提高了確認的可靠性,而數據傳輸量幾乎沒有增加。
l 實時確認機制允許我們測量 RTT,了解實時的網路狀況。我們可以區分真正的消息損失和網路損失。
l 在協議之上提供了抽象層,以支持流多路傳輸等功能。它還允許我們試驗應用級網路優先順序和流控制演算法,從而在數據使用和通信延遲方面帶來更高的效率。
l 協議對消息有效負載進行抽象,以支持不同類型的序列化。將來,我們會探索其他序列化方法,但要將 gRPC 保留在傳輸層。
l 不同語言的客戶端實現也讓我們能夠快速支持不同類型的應用程序和設備。
目前,這項開發工作處於 beta 版階段,很快就能上線。
消息推送平台是 Uber 出行體驗的組成部分之一。今天有數百種功能建立在該平台的基礎服務之上。我們總結了消息推送平台在 Uber 出行生態中取得巨大成功的幾個關鍵原因。
1)職能分離
消息觸發、創建和傳遞系統之間明確的職責分離允許我們在業務需求發生變化時將注意力轉移到平台的不同部分。通過將交付組件分離到 Apache Helix 中,數據流的拓撲邏輯和核心業務邏輯被很好的區分開,這允許在完全相同的架構上使用不同的有線協議支持 gRPC。
2)行業標准技術
構建在行業標准技術之上使我們的實現更加魯棒且低成本。上述系統的維護開銷非常小。我們能夠以一個非常高效的團隊規模來傳遞平台的價值。根據我們的經驗,Helix 和 Zookeeper 非常穩定。
我們可以在不同的網路條件下擴展到數百萬用戶的規模,支持數百個功能和幾十個應用程序。該協議的簡單性使其易於擴展和快速迭代。
原文:
https://eng.uber.com/real-time-push-platform/