做者:呂丹(凝睇),2011 年加入支付寶,前後負責了支付寶 Wap、alipass 卡券、SYNC 數據同步等項目,並參與了屢次雙11、雙12、春節紅包大促活動,在客戶端基礎服務方面有必定的項目實踐經驗與積累。目前負責螞蟻金服移動開發平臺 mPaaS 服務端組件體系優化與架構設計。
5 月 6 日,InfoQ 主辦的 QCon 2019 全球軟件開發大會在北京舉行。螞蟻金服技術專家呂丹(凝睇)在大會上作了《螞蟻金服面對億級併發場景的組件體系設計》的分享,咱們根據演講整理以下:mysql
今天,我主要想和你們分享一下移動領域基礎組件體系,內容大體能夠分爲四大塊,第一塊是標準移動研發所需的基礎服務體系,第二塊是支撐億級併發的核心組件「移動接入」的架構演進過程,第三塊是雙11、雙12、新春紅包這種大促活動的的應付方法,最後一塊是目前已經對外輸出的基礎服務產品。算法
首先介紹一下支付寶客戶端的演進過程。以前,支付寶客戶端的主要功能是轉帳、訂單支付、交易查詢等等,更像是一個工具類的 APP,在須要付錢的時候纔會掏出來,用完了就放回去了。2013 年,螞蟻金服 all in 無線以後,加入了不少服務,例如餘額寶、卡券、探索發現等,基本是把支付寶網站上的功能都儘可能遷移到客戶端,支付寶也逐漸演化成一個平臺級別的客戶端。以後,隨着移動互聯網的快速發展,公司內部孵化出了更多的 APP,其餘行業也在移動互聯網圈內鋪開了大量的業務,爲了提高用戶量、用戶粘性,APP 之間也開始進行了大量的業務融合,超級 APP 也所以而誕生,APP 開始朝着生態化的模式發展。sql
截止到目前爲止,支付寶客戶端的年活躍用戶數超過 8 億,在大促場景下,同時在線量超過 3 億,併發請求超過 1 億,同時上線的用戶數超過百萬每秒。數據庫
而在這些數據的背後必定須要一套龐大、複雜、完整的支撐體系來支持支付寶的運做,移動研發基礎服務體系就是其中的重要組成部分。小程序
按照研發過程,咱們把移動研發基礎服務體系分紅四大塊:APP 研發階段,主要包括 App 框架、基礎組件、雲端服務和研發工具;App 測試階段 ,主要包括研發協做平臺和真機測試平臺,其中研發協做平臺包含版本管理、迭代管理、安裝包編譯、構建和打包的能力,而真機測試主要是代替人工服務,減小人工消耗,提高測試效率; App 運維階段 ,主要包括智能發佈、日誌回溯、應急管理和動態配置;App 運營階段,主要包括輿情反饋、實時分析、離線計算和智能營銷。後端
今天的主題爲支撐億級併發下的基礎服務,而在億級併發下移動接入又是最核心、最重要的一個環節。移動接入並非單個系統,而是一整套組件的總稱,包括:Spanner+ 鏈接管理、API 網關、PUSH 通知和 SYNC 數據同步,它是全部移動業務的流量入口,須要維持客戶端的狀態,支持進行統一的管控,同時還須要進行部分的業務數據處理。緩存
其實,一開始並無移動接入這個說法,與支付寶客戶端的演進過程相似,後端移動接入也是逐步迭代演進的。最開始,各個業務服務都是本身提供 API 或者直接暴露能力給客戶端,沒有統一的架構,沒有統一的模型,也沒有統一的管控。安全
爲了解決這個問題,在 all in 階段咱們引伸出了一個 API 網關,由它來作集中式管理,同時添加了 PUSH 推送的能力。由於公司內部有不少 APP,咱們但願這些能力可以複用,因此在架構上,咱們支持多 APP 同構,客戶端會提供多個 SDK,能夠隨時進行集成。性能優化
上圖是一個移動 API 網關的架構,從圖中能夠看到,咱們把 API 生命週期定義爲如下幾個階段:API 定義、API 研發、API 發佈、API 配置、API 上線、API 運營和 API 下線。而移動網關又把 API 生命週期切分紅三大塊,分別是研發支撐階段、運行時階段和服務治理階段。服務器
研發支撐階段主要有四個能力,分別爲 Code-Gen、API-MAN、API-Test 和 API-Mock。爲了提升 API 數據在網絡上的傳輸效率,目前螞蟻的 API 模型所有都採用了 protobuf 進行序列化,所以,爲了方便業務開發,API 網關提供了統一的基於 proto 文件的代碼生成工具,而且爲了減小客戶端的文件大小和方法數限制,咱們修改了官方提供的生成代碼,有效減小了冗餘的方法並大大減少了客戶端文件大小。
在運行時階段,核心的功能包括 API 流量管控、數據驗籤、用戶鑑權以及接口系統路由等。
API 平常的運維由服務治理體系來搞定,主要的能力爲 API 監控,並根據實時數據進行 API 質量模型評估,同時提供了一些應急的管理措施。
API 網關最爲核心的架構設計是 Pipeline,正如你們所知,網關看起來只是一個簡單的 API 管控和路由,但其中涉及的節點卻很是多,而每一個節點的功能又相互獨立,而且隨着業務的發展,功能節點會逐漸增長,在某些場景下,還須要作不一樣的節點組合。若是採用傳統的鏈式調用,代碼執行串會很是的長,同時擴展和維護起來都很是的困難。所以咱們參考了 netty 的 Pipeline 設計,完成了本身的 Pipeline 鏈路。Pipeline 中的各個 handler 保持相互獨立,同時能夠根據須要、根據配置自由捆綁,也爲後續的功能延伸提供了良好的架構支撐;
從代碼來看,咱們能夠明確的感覺到以前的調用過程是一個遠程調用,須要感知路徑、參數等,而在統一了整個數據的交互以後,對於業務系統來講,這個調用過程更像是本地調用,直接調用函數,封裝模型。經過這種方式,業務類研發同窗可以更關注於本身業務系統的代碼邏輯編寫,徹底不用關注底層通信的實現,較大的提高了研發效率。
移動網絡跟有線網絡是有很大區別的。移動網絡比較複雜,用戶狀態也比較複雜,有多是在地下室、電梯或者其它弱網環境中,而且用戶在移動場景下對於體驗的要求很是高,例如在支付時,用戶須要立馬拿到支付結果。以前,咱們主要是作了服務端的改進,針對客戶端並無作改進。爲了解決用戶問題、性能問題、提高用戶體驗,咱們在進行了一次升級,作了一個統一接入網關,並把它架在基礎組件之上,同時研發了性能數據同步、加強了 IP 調度等能力。
【統一接入網關】
統一接入網關(ACCGW),能夠理解成一個前置的 Nginx,是螞蟻基於 Nginx 二次開發的一套組件,在內部咱們叫作 Spanner,它在接入架構中主要負責非業務的那一部分邏輯處理,主要包括 SSL 的卸載,MMTP 的協議解析,數據的壓縮、解壓縮,客戶端 TCP 長鏈接的維持,接入流量的總控,數據包的路由以及客戶端日誌的接入。API 網關、PUSH 推送、數據同步等組件,都在它的庇廕之下。
【網絡協議優化】
MMTP 協議的全稱是螞蟻移動傳輸協議,基於 TLV 的數據結構,這種數據結構的好處是分包解包的效率很是高,且它是基於二進制的,存儲成本相對較低。同時還知足了客戶端多個組件的鏈路複用,固然 MMTP 配合客戶端也有本身的一些特性,同時咱們也加入了不少新特性,例如智能鏈接策略。由於移動環境下用戶的網絡狀態不是很可靠,若是是傳統的鏈接方式,不必定能知足全部 RPC 請求,因此咱們作了策略改進。在可以使用長鏈接的狀況下儘可能使用長鏈接,若是出現長鏈接連不上或者閃斷的狀況,咱們就嘗試使用短鏈接的方式,短鏈接能夠知足當時緊急的 RPC 發數據。同時咱們也會用一些併發建連的策略,運營商網絡一般是先連上哪一個就使用哪一個鏈接,鏈接以後咱們會使用智能心跳策略,用以捕捉不一樣運營商、不一樣地區,對於維持鏈接的心跳時間的差別。
在併發建連的過程當中常常會出現客戶端同時存在多端長鏈接的現象,數據包可能會在中間作傳輸,若是立馬斷掉的話,數據包就丟了,極可能對業務產生影響,所以咱們加入了柔性斷連,以確保可能在傳輸過程當中的數據包能被安全送達。另外,多個鏈接建完以後,客戶端可能出現情況,服務端沒有及時感知到,沒法獲知這個鏈接是好是壞。所以,咱們加入了假鏈接監測,數據包派發的時候攜帶一個序列號,客戶端回報以後,若是序列號返回了,就證實這個鏈接是可用的,反之,咱們就認爲這個鏈接是假死狀態,能夠在合適的時間點斷掉該鏈接。
MTLS 是螞蟻移動安全傳輸協議,基於 TLS1.3。咱們在作的時候,TLS1.3 尚未正式發佈,可是咱們瞭解到一些它的特性,並將某些特性加入到了設計中。好比採用了 1RTT ECDHE 的握手方式。1RTT ECDHE 是基於 ECC 加密套件,ECC 的最大特色是密鑰串比較小,更小的數據在移動方面有很是大的優點,例如提高傳輸效率,節省存儲成本。在存儲或傳輸過程當中,數據包大小是移動領域特別關注的點。也由於如此,咱們選擇了 ZSTD 壓縮算法,ZSTD 有很是大的壓縮比,且在該壓縮比之下,壓縮和解壓縮的效率都不錯。另外,在某些可支持重放的業務場景中,咱們還加入了 0RTT 策略,第一時間把數據從客戶端發送到服務端。經過上述優化,RPC 的平均響應效率提高了 5~6 倍。
【SYNC 數據同步】
SYNC 數據同步聽起來有點陌生,其實能夠理解成是 PUSH 的演進版本。它是基於 TCP、雙向傳輸的。雖然傳統的 RPC 可以解決絕大多數的問題,可是在某些場景下,它是有缺陷的。例如,客戶端啓動以後,須要經過 RPC 請求去判斷服務端是否是有數據。其實 90% 的狀況是查詢接口沒有任何的變化或者返回的數據客戶端已經存在了,因此這個過程很是冗餘。除了數據冗餘之外,請求也冗餘,由於沒有發生變化,調用在原則上是能夠省下來的。
當初,在 all in 以後,咱們作了一些體驗上的優化,如預加載能力,當客戶端啓動以後,觸發數據預加載,雖然沒有進入到模塊,但爲了提高用戶體驗,客戶端發送不少 RPC 請求,也所以形成了大量的冗餘併發請求。
另外一個不足是客戶端沒辦法主動感知到服務端的數據變化,好比在聊天場景中,用戶是等着交互的,若是使用 RCP 定時拉取的方式,客戶端和服務端的成本會很是高,總體響應時間也比較慢。而經過 SYNC 的推送模式,能夠在服務端產生數據的時候,基於 TCP 方式把數據推送到客戶端,客戶端能夠在第一時間拿到數據作業務渲染,好比支付寶的掃碼支付、當面付都是經過 SYNC 服務來同步的結果數據。
SYNC 的基礎核心是——oplog,它相似於 mysql 的 binlog,是每一條增量數據的快照。SYNC 會爲每一條 oplog 生成一個惟一的、遞增的版本號,而後經過記錄客戶端當前數據版本號的方式來計算兩端之間的差量,並僅同步差量數據。由於 SYNC 是基於 TCP,可雙向主動傳輸,從而達到實時、有序、可靠、增量的數據傳輸效果。同時,SYNC 在客戶端觸發場景中,並不是基於業務場景,而是基於事件,如建聯、登陸、從後臺到前臺等動做,所以,能夠達到單次事件觸發多業務的增量計算,而當無增量數據時客戶端也不須要進行任何的其餘 RPC 請求,從而極大的減小了客戶的請求數和冗餘數據傳輸,不但提升了效率、實時性,還間接的下降了系統壓力。
【移動調度中心】
對於客戶端請求來講最重要的是在第一時間內找到正確的 IP 並把請求發出去。以前這些工做通常是由傳統 DNS 來作,但傳統 DNS 會有一些問題,例如 DNS 劫持、DNS 解析失敗、不一樣運營商 DNS 解析效率不一樣等等,解析 DNS 須要消耗額外的 RTT。
針對這些狀況,咱們設立了移動調度中心,它是基於 HTTPDNS,並在此基礎上加入了用戶分區信息。什麼叫用戶分區呢?面對億級併發,服務端確定不會在一個機房裏,多是在多個機房中,且機房內部還有邏輯分區。用戶屬於哪一個邏輯區只有服務端知道,客戶端自己是感知不到的。當某個分區的用戶接入進來後,若是沒有在正確的分區內,且又須要轉到其它分區作業務處理時,若是是採用傳統 DNS 是沒法實現的,由於沒法解析出用戶屬於哪一個 IP 列表。而 HTTPDNS+ 分區數據的模型,可讓客戶端快速拿到最準確的 IP 地址,同時客戶端還能夠針對這個 IP 地址作質量檢測和有效性檢測,在請求以前就肯定最優的 IP 地址。另外,HTTPDNS 還能夠支持海外節點的部署。HTTPDNS 必定不會比 DNS 的效果差,由於它還有 DNS 來兜底,一旦 HTTPDNS 出現問題,那麼就會切換到 DNS 去作解析。
以上的演進過程知足了絕大多很多天常的需求,可是支付寶有不少大促場景,每次大促的玩法都不一樣,且峯值集中在一剎那。針對這個場景,咱們又孵化出了新的模式,一是 API 網關的去中心化,二是 SYNC-PULL 機制,三是 SYNC-Bucket 計算模式。
【網關去中心化】
網關去中心化解決的一個核心問題就是成本。大促場景下,業務量不停上升,峯值可能很是高。但峯值只有一剎那,其餘時間內機器都是處於空閒狀態,這是很是大的資源浪費。而爲了保證大促時不崩潰,機器又不能減小,因此對應用的壓力是很是大的。
若是都是作單點,那麼還會存在穩定性的問題。若是網關在發佈時出現了某些差錯,那麼有可能影響全部業務流程的處理。另外,若是單個接口出現問題,客戶端出現死循環等問題,也會影響到其餘系統業務的流程。面對以上狀況,咱們把網關去中心化就能夠抵消這些風險,若是隻是單個系統出問題,那麼不會由於網絡的問題致使其餘業務發生問題。
【SYNC-PULL 讀擴散】
爲何會有 SYNC-PULL 讀擴散的需求呢?由於支付寶內部有很是多大 V 商戶,每一個商戶有很是多的關注用戶,它須要按期或不按期的作一些運營消息投放。若是按照 SYNC 的場景,經過寫擴散的方式給每一個關注投放一條數據,不只浪費存儲,並且效率很低下。假設某個商戶有 5 億關注用戶,5 億數據所有入庫最快也要幾十分鐘。另外,因爲咱們商戶的數量不少,你們都爭搶這個資源,可能會出現排隊的狀況。對於商戶來講,沒法立馬將活動觸達到用戶端,對於服務端來講,消息多是如出一轍的,形成了存儲浪費。即便是使用了緩存,整個索引也須要給每一個用戶去存一遍,這對數據的 TPS 依然要求很是高。
爲了解決以上問題,咱們升級成了讀擴散的模式,把它抽象成關注關係,每一個商戶抽象成 Topic,而後把全部數據放在 Topic 下面。由於用戶關注的大 V 相對比較少,且大 V 生產數據的頻率並不高,有效的數據集不是特別多,因此能夠把超級大 V 的數據先放在緩存裏面,而後經過二叉索引快速尋址用戶下的關注關係,並經過原有的 SYNC 機制把增量數據推到客戶端。這樣,原來億級的存儲就變成了一條存儲,原來幾十分鐘的響應時間變成了秒級,效率和體驗都有了極大的提高。
早先,咱們作 SYNC 的時候是想讓每一個業務都相對獨立、相對隔離,計算也獨立進行。當時的業務場景很少,可是後來接入的業務愈來愈多,將近有 80 個業務場景,且每一個業務都是獨立計算。客戶端是基於事件的,建連以後,須要進行 80 次業務獨立計算,在大促一百萬每秒的發送量的狀況下,很容易就達到億級,這對數據庫、應用程序、緩存等的壓力都是很是大的,同時這種方式也無法知足將來的持續發展。
爲了解決這些問題,咱們針對原來的計算特性抽象出了幾個分類。例如,基於用戶維度、基於設備維度、基於一次性、基於多端同步、基於全局用戶配置的幾個大類數據,抽象成幾個抽象模型。咱們姑且認爲是有 5 個 bucket,全部的計算都基於 bucket 方式來作,若是有新的業務加入,那就根據它的特性把它歸到某個 bucket 中。
另外,大促場景下會有高優先級的業務,因此須要作一些特定的限流策略。針對這種狀況,bucket 能夠動態的增減,業務進出 bucket 也能夠隨時切換。bucket 上線以後,當時咱們的計算量降低超過了 80%,在後面的 二、3 年中,業務從 80 個增長到 300 個,服務器也沒有增長。總體來講,對性能的提高仍是很是明顯的。
前面的內容主要是移動接入方面的組件設計如何支撐億級場景,下面咱們聊一下,如何切實的應對大促活動。
【大促活動場景應對之道:步法】
經過幾年的大促經驗,咱們在技術上提煉出了應對大促的幾個步法:首先業務同窗設定業務目標,肯定業務玩法;技術同窗在收到大促介紹以後,開始分解技術指標,並根據各自系統的能力、流程和特性肯定相應的技術方案,肯定技術方案的步驟則主要爲:鏈路分析、容量評估、性能優化、流控方案、預案策略以及肯定彈性流量規則。在肯定完成技術應對方案後,最重要的是進行全鏈路的壓測,經過影子用戶,影子表進行生產環境的全鏈路壓測,每一個系統壓測週期短則幾天,長則須要數月。在不斷的壓測中發現問題,發現瓶頸,優化後再次進行壓測,直到完成技術目標;在全鏈路完成壓測指標後,進行多輪活動的演練,以模擬真實業務場景,並驗證技術方案的準確性;此後,根據實際須要,擇時進入大促階段。在這個階段,研發同窗主要工做是配合運維進行預案的執行、觀察大促期間各類指標的變化,並根據監控確認是否須要應急。固然,應急方案在以前的演練中也須要進行驗證。隨後大促活動結束後,須要進行預案 & 應急策略的回滾和驗證,這樣大促活動纔算真正結束。同時,更重要的是,咱們須要對每一年的大促進行復盤 review,以便發現不足,在後續的活動中加以改進。
【大促活動場景應對之道——流控】
在大促執行過程當中,最爲關鍵的是流控。對技術同窗來講,讓系統在活動中活下來是對大促最給力的支持,流控是系統最有力的屏障。因爲各系統在大促活動中發揮的做用、業務的緊急程度、集羣的規模各不相同,所以大促中通常會犧牲一些特性來爲主要鏈路騰出性能空間,好比流水日誌、壓縮閾值、消息順序性等等。
流量的管控也會分多級,在最上層 LVS 會在 VIP 上進行數十億級別的控制,到接入網關層則根據建連量、包數進行億級流控,而 API 網關層則進行千萬級別的控制。在這幾層上,通常簡單計數便可知足。而到業務層,特別是中低流量的業務層,通常採起的是令牌桶和分佈式限流方式。而後,在 API 網關上,也能夠作一些自定義的腳本,mock 返回結果來爲業務系統抵擋住一部分請求。
【自動化真機測試】
除了核心鏈路以外,咱們也須要一些後勤服務。例如在測試過程當中,須要自動化,特別是真機模擬測試來抵消部分的人力勞動。咱們的機房中部署了上千臺手機,一般都會進行一些自動化的運維檢測,包括安裝包的安裝卸載、性能損耗、功能測試等。除了自動化測試,它還扮演着自動審批和服務巡檢的角色,分別用來檢測小程序和及時發現問題。經過自動測試平臺能夠節省 60% 以上的重複體力勞動消耗。
【客戶端智能發佈——確保客戶端萬無一失】
若是要確保客戶端萬無一失,那麼最核心的就是灰度流程,灰度流程結束以後,咱們才能發佈到生產環境中。
智能發佈主要支持客戶端各類的發佈包,包括安裝包、離線包、小程序包等。經過多年的發佈,咱們也沉澱了一些模板,例如灰度用戶、灰度覆蓋率等等。灰度時咱們能夠選擇必定的模板,按照既定邏輯,使用自動化流程代替人工處理。
【輿情分析——及時獲取用戶反饋】
客戶端發佈以後,業務同窗必定很是關心用戶心聲和市場反應,技術同窗則但願第一時間收集到用戶的真實反饋。輿情分析系統就用來知足這些需求,輿情繫統能夠分爲 4 大塊:數據採集,主要採集渠道爲各大媒體中心、應用市場評論、開會的反饋功能和客戶滿意中心的數據;數據內容則能夠包含各類熱點話題、熱點事件和主要生產問題;數據存儲,目前主要由 4 大塊來支撐:元數據通常能夠採用關係型數據庫,文檔數據使用的是 MongoDB,爬蟲採集的條目經過 MQ 來傳輸,全部數據最終會落至 ES 中,用來作檢索和基礎分析;數據計算更多的是經過文件算法來對 ES 中的數據進行分析,最終產出各類趨勢和各類事件、話題排行,同時針對每個用戶反饋又能夠實時通知到相關的負責人。
在這裏咱們說的移動分析主要是基於客戶端日誌埋點的數據分析能力。客戶端須要有標準的埋點 SDK 來採集 Native、H五、小程序的各類框架 & 容器埋點,也須要支持業務自定義的業務埋點。同時,爲了在大促場景能有效的提高服務端性能,埋點的寫入與上報也須要有一些措施來進行動態的控制,埋點在客戶端完成後,在合適的時機就會上報給服務端的移動日誌網關,(移動日誌網關目前也已經逐步被歸入到移動接入中進來)。當客戶端日誌上報到服務端以後,便可由日誌網關輸出到服務端日誌文件或投遞至消息組件,供其餘的平臺進行消費計算,這包括如 Jstorm、kepler、Flink 這樣實時計算平臺,也能夠投遞到 Spark、odps 等離線大數據計算平臺來進行進一步分析。做爲基礎組件,移動分析除了日誌採集和同步以外,也進行了一些框架輸出日誌的基本數據分析,行爲分析(像日活、新增、流存在)、頁面分析(停留時長,參與度)、閃退分析、卡頓分析,並提供了日誌回溯和日誌拉取等能力供研發同窗進行問題排查和分析。固然,這些數據能夠用於各類業務分析,分析的形式徹底取決於業務方想如何使用。
【技術組件產品服務輸出:成熟一個,開放一個】
咱們的基礎能力通過這幾年的努力,也沉澱了很多技術產品能夠輸出出來。這些技術產品覆蓋了從 APP 研發到測試到運維到運營的各個階段,有客戶端框架、客戶端基礎組件,有云端基礎服務(像 API 網關、SYNC 數據同步、PUSH 通知這些),有開放工具,有插件,有伴隨研發測試的研發協做平臺來進行迭代管理、編譯、構建、打包,真機測試平臺,也有 APP 運維階段所需的智能發佈、日誌管理、應急管理,還有用於 APP 運營的,各類數據分析和營銷投放產品。這些能力目前已經輸出到了螞蟻國際(印度 paytm、馬來西亞、印度尼西亞、菲律賓等)的多個合做夥伴 APP,公有云的上百個企業級 APP,以及私有云的數十家金融 APP。
咱們的宗旨是,成熟一個、開放一個,來與合做夥伴共建移動互聯網的生態。
【一站式研發平臺——mPaaS】
爲了可以幫助合做夥伴快速、有效的建設本身的 APP,咱們也推出了一站式的移動研發平臺——mPaaS。mPaaS 囊括了前面說到的各項基礎能力,同時,支持公有云和私有云,mPaaS 不只僅是技術的輸出,也是生產經驗和運營理念的輸出。
本文爲雲棲社區原創內容,未經容許不得轉載。