本文由百度技術團隊分享,引用自百度Geek說,原題“千萬級高性能長連接Go服務架構實踐”,為了閱讀便利,本文進行了排版優化等。
1、引言
移動互聯網時代,長連接服務成為了提升應用實時性和互動性的基礎服務。
本文將介紹百度基于golang實現的統一長連接服務,從統一長連接功能實現和性能優化等角度,描述了其在設計、開發和維護過程中面臨的問題和挑戰,并重點介紹了解決相關問題和挑戰的方案和實踐經驗。
* 關聯文章:《百度統一socket長連接組件從0到1的技術實踐》、《淘寶移動端統一網絡庫的架構演進和弱網優化技術實踐》,建議可一并閱讀。
2、專題目錄
本文是專題系列文章的第10篇,總目錄如下:
- 《長連接網關技術專題(一):京東京麥的生產級TCP網關技術實踐總結》
- 《長連接網關技術專題(二):知乎千萬級并發的高性能長連接網關技術實踐》
- 《長連接網關技術專題(三):手淘億級移動端接入層網關的技術演進之路》
- 《長連接網關技術專題(四):愛奇藝WebSocket實時推送網關技術實踐》
- 《長連接網關技術專題(五):喜馬拉雅自研億級API網關技術實踐》
- 《長連接網關技術專題(六):石墨文檔單機50萬WebSocket長連接架構實踐》
- 《長連接網關技術專題(七):小米小愛單機120萬長連接接入層的架構演進》
- 《長連接網關技術專題(八):B站基于微服務的API網關從0到1的演進之路》
- 《長連接網關技術專題(九):去哪兒網酒店高性能業務網關技術實踐》
- 《長連接網關技術專題(十):百度基于Go的千萬級統一長連接服務架構實踐》(* 本文)
3、內容概述
移動互聯網時代,用戶對服務的實時性、互動性有了更高的要求,因此能夠極大提升服務實時性、互動性的長連接服務,成為了移動互聯網應用的剛需。
長連接,顧名思義,是應用存活期間和服務端一直保持的網絡數據通道,能夠支持全雙工上下行數據傳輸。其和請求響應模式的短連接服務最大的差異,在于它可以提供服務端主動給用戶實時推送數據的能力。
不過:長連接作為基礎服務,要做到低延時、高并發、高穩定性,對服務的開發和維護有較高的要求。
如果每個業務都維護自身的長連接服務,一方面有較大的重復開發和維護成本,另一方面長連接服務功能迭代、服務穩定性、專業性很難跟上業務訴求。
因此:統一長連接項目通過打造完整的端到服務端的長連接服務系統,給業務提供一套安全、高并發、低延遲、易接入、低成本的長連接服務能力。
4、需要什么樣的統一長連接服務
統一長連接服務主要目的是給業務提供一套安全、高并發、低延遲、易接入、低成本的長連接服務系統。
主要愿景包括:
- 1)滿足百度體系內APP主要場景如直播、消息、PUSH、云控等業務對長連接能力的訴求,提供安全構建、維護長連接和數據上下行能力;
- 2)保障服務的高并發、高穩定性、低延遲,保障長連接服務的專業性和先進性;
- 3)支持長連接多業務長連接復用,減少APP建立和維護長連接的成本和壓力;
- 4)支持業務快速接入長連接,提供給業務簡單清晰的接入流程和對外接口。
5、問題和挑戰1:功能實現
統一長連接服務與接入業務的邊界關系是長連接業務架構設計的首要問題。
與業務專用的長連接服務不同,統一長連接服務要實現的目標是多業務方共用一條長連接。因此在設計時既要考慮到不同業務方、不同業務場景對長連接服務的訴求,同時,也要明確長連接服務的服務邊界,避免過多介入業務邏輯,限制后續長連接服務的迭代和發展。
通常,業務對長連接服務的主要訴求包括三個方面:
- 1)連接建立、維護、管理;
- 2)上行請求轉發;
- 3)下行數據推送。
數據上下行過程中,需要能夠支持不同業務數據協議上的差異。
此外,根據不同的業務類型,對下行數據推送模式、推送量級有著不同的要求。
以長連接服務常見的消息、直播、PUSH業務方為例:
- 1)消息場景:主要是私信和有人數限制(500-1000)的群聊,推送通知的模式主要是單播和批量單播,推送頻率和并發度,依賴于私信和群里消息的發送頻率;
- 2)直播消息場景:直播消息是一個組播場景,組播成員數和直播間在線人數相關,峰值百萬甚至千萬,推送消息頻率高;
- 3)PUSH場景:PUSH 場景是對一個固定人群下發消息,推送模式是批量單播,推送頻率相對而言比較低。

綜上,統一長連接服務,要實現的服務能力如下:
- 1)連接建立、維護、管理;
- 2)上、下行數據轉發,區分不同業務、兼容不同業務消息協議;
- 3)下行推送上,支持單播、批量單播、廣播。
6、問題和挑戰2:性能優化
統一長連接服務因為要給百度體系APP提供長連接能力的服務,要做到高并發、高可用、高穩定性。具體到長連接服務本身,其主要包括以下幾個方面。
1 )建聯qps、延時、成功率、連接維持:
長連接在app打開同時需要完成建立、并在app存活期間保持連接存活。
因此,長連接服務要支持萬級別的建聯qps和千萬級別在在線連接維持,并支持橫向擴容。
此外,連接建立作為長連接服務的基礎,建聯的成功率和延時重中之重。
2) 上行請求qps、延時、成功率:
連接建立完成后,需要將業務請求轉發給業務側,這個依賴于用戶規模和請求頻率,一般至少要支持到幾十乃至百萬級別,并可以支持橫向擴容。
3) 下行請求qps,延時、成功率:
下行請求根據業務場景的不同,分為批量單播和組播,且不同業務對應請求qps要求不一樣,一般批量單播需要支持到百萬級ups,組播要支持到千萬級ups,且支持橫向擴容。
7、整體設計
下面簡單介紹下,為了完成上述目標,統一長連接服務所做的一些方案設計和實踐經驗。
7.1整體架構

統一長連接服務整體架構如上圖所示,整個服務包括四個部分組成:
- 1)統一長連接SDK;
- 2)控制層;
- 3)接入層;
- 4)路由層。
統一長連接SDK歸屬于客戶端,控制層、接入層、路由層歸屬于服務端。每個組成部分在整體系統中的扮演的角色和功能如下。
1)統一長連接SDK:
統一長連接SDK歸屬于客戶端,負責連通業務SDK和長連接服務端。
其主要職責包括:
- 1)請求控制層,獲取能夠標識設備合法身份的token、長連接接入點和長連接接入協議;
- 2)同長連接接入層建立、維護長連接,在連接狀態異常時,主動觸發連接重連,維護端上連接的穩定;
- 3)轉發各業務SDK請求到長連接服務。
- 4)接受長連接下發的數據并將數據轉發給指定的業務SDK。
2)控制層:
長連接建聯之前的一個前置服務,主要用來驗證接入設備的合法性和決定設備的接入策略。
其主要職責包括:
- 1)生成和驗證標識設備合法性的token;
- 2)根據客戶端屬性下發對應的接入點;
- 3)負責小流量控制策略等。
3)接入層:
接入層作為統一長連接核心服務,承擔了連接介入,連接維護、請求轉發、下行推送等主要功能,是長連接核心邏輯和主要壓力的承擔者。
其主要職責包括:
- 1)對端通訊:負責與長連接SDK建立、維護、釋放長連接;
- 2)連接管理:負責連接管理、構建連接ID->連接信息的映射關系;
- 3)組管理:負責連接組的管理,構建組ID-> 連接信息的映射關系;
- 4)上行轉發:接受并轉發業務請求到業務后端,接受業務后端的返回,并寫回給長連接SDK;
- 5)下行推送:接受業務的推送請求,寫到對應的長連接SDK。
4)路由層:
負責構建設備標識和連接標識的映射關系,在業務指定設備標識進行推送的時候,提供設備標識查詢連接標識的能力。
7.2核心流程

長連接生命周期內主要有四個核心流程:
- 1)建立連接;
- 2)維持連接;
- 3)上行請求;
- 4)下行推送。
具體是:
- 1)建立連接:由長連接SDK發起,先通過控制層獲取該設備的合法標識token和接入配置(接入點、接入協議),然后和接入層開始建聯長連接,成功則長連接建立完成;
- 2)維持連接:主要是通過長連接SDK定時發起心跳來保證長連接活躍;
- 3)上行請求:上行請求由業務SDK發起,長連接SDK封裝后發送給接入層,接入層根據請求來源發送給指定的業務Server;
- 4)下行推送:下行推送由業務Server發起,經由路由層根據設備標識確定連接標識,然后將請求轉發到對應的接入層,寫入到設備指定連接上,經由長連接SDK轉發給業務SDK。
8、功能實現
8.1連接狀態

長連接由于連接生命周期較長,在周期內連接可能會因為各種網絡情況、數據傳輸異常導致連接發生狀態變化。同時也為了防止惡意設備模擬正常的客戶端對長連接服務進行攻擊,需要有一套機制能夠讓服務端驗證長連接狀態是合法有效的,同時對于處于異常狀態的連接,能夠觸發其重連并快速恢復。
統一長連接通過引入狀態機的方式構建了該機制。即明確定義長連接在生命周期內可能存在的各種狀態、每種狀態可以觸發的操作,以及狀態間相關轉移的場景等。
比如:
- 1)連接在可以發送數據前,需要通過登錄驗證連接合法有效,認證通過后的連接才能視為有效連接并支持上下行數據傳輸;
- 2)登錄后的連接如果發生異常情況,比如數據格式異常、網絡狀態異常,會觸發連接失效觸發端上重新建聯登錄等等。
引入這種的機制好處是:簡化長連接狀態流轉的開發邏輯,長連接生命周期里面每種狀態以及狀態間轉移關系,觸發的操作都是明確定義的,避免了線上因為各種未知原因導致連接處于不可知狀態,導致長連接異常甚至無法恢復。
8.2多業務支持

統一長連接一個主要愿景是支持多業務復用一條長連接,即同一條連接上,能夠兼容不同業務的數據協議,且在上下行業務數據傳輸時候能夠區分不同業務的請求轉發給指定業務。
這個主要是通過長連接私有數據協議來支持,長連接數據協議是長連接SDK和長連接接入層交互使用的數據協議,采用的二進制私有協議。
協議主要分為三部分:
- 1)協議頭:包括協議標識、協議版本等;
- 2)公參:設備標識、應用標識、業務標識、請求元數據等;
- 3)業務數據:業務自定義數據,用來兼容不同業務的數據協議。
通過解析協議公參里面的業務標識,長連接SDK和長連接接入層能夠確認業務數據對應的業務方,并根據業務標識將請求做對應轉發。業務的請求數據放在業務數據部分,協議有業務側指定,長連接服務只做轉發,不介入業務具體細節。
8.3上行請求轉發

接入層根據業務標識確認業務數據來源后,會通過RPC請求將業務數據轉發給業務server,然后將業務Server的返回寫回給端上。
上行請求轉發除了會轉發業務上行請求數據外,也會講長連接公參數據一并帶給業務Server。
除此外, 如果業務有訴求,在連接狀態發生變化,比如連接斷開等,長連接接入層也可以將該信號實時通知業務Server,以便業務Server 根據狀態信號變化做進一步操作。
8.4單播&多播推送
下行推送,根據業務需要,主要分為兩類,單播推送和組播推送,以下對比了單播推送和組播的差異。

1)單播推送:
服務端主動推送時候,比如一個業務要給某個設備推消息,由于接入層是多實例部署的,首先需要知道這個設備與哪個長連接實例相連。其次需要知道這個設備與這個實例內哪條長連接相關聯,那么這個實例地址和對應的長連接一期就構成了這個設備當時的連接信息,給某個用戶推消息。本質上就是通過用戶設備找到這個設備對應的連接信息的過程,也就是設備ID -> 連接信息(實例ip+連接ID)映射關系的過程,路由層負責構建和維護設備和連接信息的一個模塊。
這個對業務的主要成本是確定需要推送用戶的設備ID:
- 1)對于一些業務本身的業務場景是設備維度的,那就可以直接通過接口進行推送;
- 2)對于一些業務本身的業務場景是用戶維度的,一個用戶可以有多個設備,那么業務側需要做一個用戶->設備的映射關系,給用戶推消息,需要做用戶->設備,然后設備->連接信息的兩層轉換。
2)組播推送:
此外,由于下行推送的時候,在某些場景下,會存在需要給大批量用戶推送相同消息的場景,比如直播(聊天室)。
路由層會維護一個連接組信息,連接組ID->組內連接信息的映射。連接組的創建、連接加入和退出連接組,主要由對應的業務場景來控制,路由層只提供對應的接口能力,在連接組建立好后,向對應的連接組推消息,長連接服務會自動將消息拆分發給組內每一條連接。
使用連接組,業務需要做的事情:
- 1)連接組創建;
- 2)客戶端主動加入和退出連接組;
- 3)根據連接ID,推送消息。
9、性能優化
9.1多協議支持
一方面,不同的場景,可能會使用到不同的通訊協議,比如NA端一般傾向于tcp和tls,小程序和web端傾向于websocket。一方面,現有協議的迭代和新協議的出現,也會給長連接的性能和通道質量帶來優化。因此,為了適配不同場景下的通訊協議,同時也為了能夠快速探索通訊協議迭代對長連接服務質量的提升。統一長連接做了對不同通訊協議的兼容。
即為了支持多種通訊協議,接入層對連接概念做了劃分,將連接分為了兩層,connection 和 session。
1)connection層: 和具體的通訊層協議交互,封裝不同通訊協議的接口和邏輯差異,比如tls、websocket、quic 等等。同時給上層session 層提供統一的數據接口,包括連接建立、數據讀取、寫入、連接信息獲取等。新協議的接入,只需要在connection做相應適配,不影響session層的長連接業務邏輯。
2)session層:長連接業務級別連接概念,維護長連接業務連接狀態,維護連接狀態機,支持請求轉發、下行推送等業務邏輯,本身依賴connection層提供的數據接口和實際的通訊協議進行交互。但是不感知具體的通訊協議差異。
同時,端上在建聯時,控制層會根據客戶端當前的情況,比如端類型(NA、小程序、Web)、當前的網絡類型(4G、5G)、設備質量情況等,下發不同的建聯協議和對應的接入點,端上根據下發的建議協議和接入點,結合端上自身情況,選用合適的接入協議和接入點進行建聯。
這樣設計的主要優勢在于:
- 1)長連接業務邏輯和通訊協議做了隔離,通訊協議的更新和新增,不影響長連接狀態機、請求轉發、下行推送等業務邏輯,簡化了兼容多通訊協議的實現難度,實現一套架構支持多通訊協議接入。
- 2)客戶端可以根據實際情況,采用不同的通訊協議接入,通訊協議帶來的通道質量優勢能夠很好的體現在長連接服務質量上。
9.2請求轉發組&下行任務組
連接建立完成后,接入層主要面臨著三個壓力來源:
按照單個實例需要支持百萬連接來考慮:
- 1)假定單個連接心跳為1分鐘1次,則連接維持需要支持1.6w qps心跳請求;
- 2)請求轉發依賴于業務請求頻率,通常百萬在線至少需要支持1-2w qps 上行請求;
- 3)下行推送,根據推送場景的不同,通常組播場景下需要支持5-10w ups下行。
綜上:單個實例如果要支持百萬連接,通常需要支持3-4w qps 上行,5-10w 的ups下行。
統一長連接層接入層服務是使用golang來實現的,按照golang 常用的網絡模型,一條連接會有對應兩個goroutine,一個用來讀數據和處理數據,一個用來寫數據。
這個模型存在兩個問題:
- 1)統一長連接是多業務復用一個連接,連接上會存在同時有多個請求上行,一個goroutine讀和處理數據,如果一個請求處理比較慢,會導致后續其他請求處理排隊的情況;
- 2)每個連接至少需要2個goroutine,如果單實例需要支持一百萬連接,則單個實例常態下會有200萬goroutine, 而且,長連接服務,連接的建立和釋放非常頻繁,這個會導致goroutine的建聯和釋放也非常頻繁,進而給服務的gc帶來巨大的壓力。
統一長連接通過引入請求轉發組和下行任務組來解決上述兩個問題。
1)請求轉發組:
接入層在實例啟動的時候,會根據支持的業務上行qps,初始化對應的請求轉發組,連接在讀取完請求數據后,會根據請求屬于那個業務將請求轉給對應的請求轉發組,由請求轉發組內的goroutine完成后續請求。
不同業務的請求轉發組是不同的goroutine池,避免業務間相互影響。連接本身的讀goroutine只是負責讀取數據,轉發請求給請求轉發組,避免請求處理存在排隊的情況。
2)下行任務組:
下行數據寫入的時候,會有一個公共的任務組,每個連接在任務組中會有一個固定的處理協程,有數據下行的時候會講寫入數據的任務發到下行任務組。
這個主要目的是,由于單個實例需要維護大量的在線長連接,每個長連接通常需要兩個協程,一個讀協程、一個寫協程,如果單實例支持50w連接,也就會單實例存在百萬協程,這個對服務gc和資源都會造成一定的壓力。
同時,一個實例維持的所有連接通常不會同時都下行寫消息,因而,可以通過維護一個下行任務組,任務組里面維護動態數量的協程數,每個連接綁定任務組里面一個協程,有下行任務時將任務發送到任務組里面,有任務組里面的協程負責將任務下行,減少實例服務壓力。
9.3服務部署

統一長連接服務部署上,主要做了以下幾點。
1)長連接在國內三大運營商的華東、華北、華南地域均部署了接入點;部分業務需要支持海外業務,增加了香港機房的獨立接入點入口。
2)根據業務量級和重要性,分大小集群部署,每個集群對應不同的域名,不同業務通過控制層下發域名分流到對應集群。主要目的針對于重點業務,提供獨立部署的能力;對于次級業務,提供混部服務,降低成本和提高資源利用率。
3)針對接入層每個實例,將實例的配置和能夠支持的連接數,控制在10w-20w量級,避免單個實例支持連接數過多,實例發生服務抖動時,對整個集群服務產生較大影響;單個實例支持的連接數有限制,減少實例內常態維護的goroutine數,減輕gc壓力。
10、業務接入
業務接入統一長連接通常涉及以下幾個步驟:
- 1)評估需要接入的能力:評估需要接入的長連接能力,比如下行推送中,是要接批量單播還是組播;是否要支持上行請求等,根據接入能力不同,需要對接不同的接口;
- 2)評估用戶量級:用戶量級涉及到資源評估以及是否需要單獨進行集群部署等等;
- 3)端上接入長連接SDK:客戶端需要接入長連接SDK,接入上下行收發消息接口;
- 4)服務端接入上下行接口:服務端需要根據接入能力,適配不同的服務端接口;
- 5)申請資源服務上線。
11、本文小結
目前統一長連接已支持了千萬級長連接并發在線,支持過百萬級ups 批量單播和組播消息下行,擁有實時橫向擴容能力。
服務第一次完成上線至今,長連接服務穩定,經歷過多次重大活動高并發推送的考驗,沒有出現過任何影響其他業務服務質量的case。
總的來說,統一長連接項目從立項、開發到最后上線運維,服務質量整體上是符合預期的。
從統一長連接項目整個項目流程,主要總結有以下三點經驗:
- 1)需求:分析需求時候,要明確需求和業務的邊界,也就是明確什么應該長連接的能力,什么是業務邏輯,堅持長連接服務不深入介入業務邏輯這個原則,保證長連接服務與業務的邏輯解耦,確保長連接服務結構的穩定;
- 2)設計:需求明確的情況下,技術的方案的選擇以簡單滿足要求為優先,長連接服務本身邏輯并不復雜,其主要在于服務的穩定性和高性能,巧妙而復雜的方案在長連接的場景下,并不一定能夠適用;
- 3)運維:追求單實例性能的同時,也要在性能和運維之間做取舍,單實例性能再強,能夠支持的連接數再多,通常也比不上分拆多個小實例,帶來的穩定性和資源利用率的提升大。
12、未來規劃
統一長連接服務經歷數次迭代后,目前基本功能已經趨于穩定,將進一步對長連接服務進行改善和優化。
主要集中在以下幾個方向:
- 1)精細化:進一步完善長連接全鏈路網絡質量數據統計和分析能力的建設;
- 2)智能化:端上建聯、接入點接入、心跳頻率等能夠根據實際環境進行自動調整;
- 3)場景拓展:探索長連接支持更多的業務場景。
13、相關文章
[1] 百度統一socket長連接組件從0到1的技術實踐
[2] 淘寶移動端統一網絡庫的架構演進和弱網優化技術實踐
[3] 直播系統聊天技術(二):阿里電商IM消息平臺,在群聊、直播場景下的技術實踐
[4] 長連接網關技術專題(二):知乎千萬級并發的高性能長連接網關技術實踐
[5] 長連接網關技術專題(三):手淘億級移動端接入層網關的技術演進之路
[6] 長連接網關技術專題(六):石墨文檔單機50萬WebSocket長連接架構實踐
[7] 長連接網關技術專題(七):小米小愛單機120萬長連接接入層的架構演進
[8] 不為人知的網絡編程(十五):深入操作系統,一文搞懂Socket到底是什么
[9] 零基礎IM開發入門(一):什么是IM系統?
[10] WebSocket從入門到精通,半小時就夠!
[11] 網絡編程懶人入門(十):一泡尿的時間,快速讀懂QUIC協議
14、百度分享的其它技術文章
《百度APP移動端網絡深度優化實踐分享(一):DNS優化篇》
《百度APP移動端網絡深度優化實踐分享(二):網絡連接優化篇》
《百度APP移動端網絡深度優化實踐分享(三):移動端弱網優化篇》
《全面了解移動端DNS域名劫持等雜癥:原理、根源、HttpDNS解決方案等》
《深入了解百度開源的分布式RPC框架brpc的方方面面》
《直播系統聊天技術(四):百度直播的海量用戶實時消息系統架構演進實踐》
《IM消息ID技術專題(五):開源分布式ID生成器UidGenerator的技術實現》
《百度統一socket長連接組件從0到1的技術實踐》
《百度網盤千萬節點的P2P架構設計(PPT) [附件下載]》
《即時通訊音視頻開發(二十):一文讀懂視頻的顏色模型轉換和色域轉換》
《揭秘百度IM消息中臺的全量用戶消息推送技術改造實踐》
《百度基于金融場景構建高實時、高可用的分布式數據傳輸系統的技術實踐》
(本文已同步發布于:http://www.52im.net/thread-4623-1-1.html)