Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 499, comments - 13, trackbacks - 0, articles - 1

          本文由B站微服務技術團隊資深開發(fā)工程師周佳輝原創(chuàng)分享。

          1、引言

          如果你在 2015 年就使用 B 站,那么你一定不會忘記那一年 B 站工作日選擇性崩潰,周末必然性崩潰的一段時間。

          也是那一年 B 站投稿量激增,訪問量隨之成倍上升,而過去的 PHP 全家桶也開始逐漸展露出頹勢,運維難、監(jiān)控難、排查故障難、調用路徑深不見底。

          也就是在這一年,B 站開始正式用 Go 重構 B 站,從此B站的API網關技術子開始了從0到1的持續(xù)演進。。。

          * 補充說明:本次 API 網關演進也以開源形式進行了開發(fā),源碼詳見本文“12、本文源碼”。

          PS:本文分享的API網關涉及到的主要是HTTP短連接,雖然跟長連接技術有些差異,但從架構設計思路和實踐上是一脈相承的,所以也就收錄到了本《長連接網關技術專題》系列文章中。

          學習交流:

          本文已同步發(fā)布于:http://www.52im.net/thread-3941-1-1.html

          2、關于作者

          周佳輝:嗶哩嗶哩資深開發(fā)工程師。始終以簡單為核心的技術設計理念,追求極致簡單有效的后端架構。

          2017 年加入 B 站,先后從事賬號、網關、基礎庫等開發(fā)工作。編碼 C/V 技能傳授者,技術文檔背誦者。開源社區(qū)愛好者,安全技術愛好者,云計算行業(yè)活躍用戶,網絡工程熟練工。史詩級 bug 生產者,熟練掌握 bug 產生的各類場景。

          3、專題目錄

          本文是專題系列文章的第8篇,總目錄如下:

          4、正式用Go重構B站

          鑒于引言中所列舉的各種技術問題,也是在2015年,財隊開始正式用 Go 重構 B 站。

          B站第一個 Go 項目——bilizone,由冠冠老師(郝冠偉)花了一個周末時間編碼完成。

          commit 4ccb1497ca6d94cec0ea1b2555dd1859e6f4f223

          Author: felixhao <g******[url=mailto:1@gmail.com]1@gmail.com[/url]>

          Date:   Wed Jul 1 18:55:00 2015 +0800

              project init

          commit 6e338bc0ee638621e01918adb183747cf2a9e567

          Author: 郝冠偉 <h*******@bilibili.com>

          Date:   Wed Jul 1 11:21:18 2015 +0800

              readme

          ▲ 郝冠偉:嗶哩嗶哩主站技術中心架構師

          bilizone 其實還是一個大而全的應用,bilizone 在當時重構的主要意義是將誰也理不清的 PHP 邏輯梳理成了一個比較標準的 Go 應用。

          bilizone 在當時最大的意義就是為用戶終端提供了基本穩(wěn)定的數據結構、相對可靠的接口和比較有效的監(jiān)控。

          但因 bilizone 依舊是一個單體應用,所以它依舊繼承了單體應用所具有的缺點:

          • 1)代碼復雜度高:方法被濫用、超時設置混亂、牽一發(fā)而動全身;
          • 2)一掛全掛:最常見的比如,超時設置不合理、goroutine 大量堆積、雪崩;
          • 3)測試及維護成本高:小改動都需要測試所有 case,運維發(fā)布膽戰(zhàn)心驚。

          所以此時B站的崩潰頻率雖然已經有所降低,但一炸全炸的問題依舊是一個心腹大患。

          5、基于微服務的B站架構初具雛形

          鑒于bilizone所面臨的單體應用技術缺點,接下來的一次重構,讓B站基于微服務的全局架構面貌就將初具雛形。

          為了實現(xiàn)微服務模式下的 bilibili,我們將一個 bilizone 應用拆分成多個獨立業(yè)務應用,如賬號、稿件、廣告等等,這些業(yè)務通過 SLB 直接對外提供 API。

          當時的調用模式如下圖所示:

          但是隨著功能拆分后,我們對外暴露了一批微服務,但是因為缺乏統(tǒng)一的出口而面臨了不少困難。

          這些困難主要是:

          • 1)客戶端與微服務直接通信,強耦合;
          • 2)需要多次請求,客戶端聚合數據,工作量巨大,延遲高;
          • 3)協(xié)議不利于統(tǒng)一,各個部門間有差異,反而需要通過客戶端來兼容;
          • 4)面向“端”的 API 適配,耦合到了內部服務;
          • 5)多終端兼容邏輯復雜,每個服務都需要處理;
          • 6)統(tǒng)一邏輯無法收斂,比如安全認證、限流。

          6、基于BFF模式的微服務架構

          基于上節(jié)的初階微服務架構帶來的技術問題,以及我們想要將對端的處理進行內聚的想法,我們自然的而然的就想到在客戶端與后端服務之間加一個 app-interface 的組件,這就是接下來的 BFF(Backend for Frontend)模式。

          app-interface 的工作模式如下圖所示:

          有了這個 BFF 之后,我們可以在該服務內進行大量的數據聚合,按照業(yè)務場景來設計粗粒度的 API。

          這樣,后續(xù)服務的演進也帶來了很多優(yōu)勢:

          • 1)輕量交互:協(xié)議精簡、聚合;
          • 2)差異服務:數據裁剪以及聚合、針對終端定制化 API;
          • 3)動態(tài)升級:原有系統(tǒng)兼容升級,更新服務而非協(xié)議;
          • 4)溝通效率提升:協(xié)作模式演進為移動業(yè)務和網關小組。

          BFF 可以認為是一種適配服務,將后端的微服務為客戶端的需要進行適配(主要包括聚合裁剪和格式適配等邏輯),向終端設備暴露友好和統(tǒng)一的 API,方便無線設備接入訪問后端服務,在其中可能還伴隨有埋點、日志、統(tǒng)計等需求。

          然而,這個時期的 BFF 還有一個致命的一個問題是——整個 app-interface 屬于 single point of failure,嚴重代碼缺陷或者流量洪峰可能引發(fā)集群宕機所有接口不可用。

          7、基于多套BFF模式的微服務架構

          針對上節(jié)中BFF模式下架構的技術問題,于是我們在上述基礎上進一步迭代,將 app-interface 進行業(yè)務拆分。

          進而多套 BFF 的模式橫空出世:

          由此模式開始,基本確定了 B 站微服務接口的對接模式,這套模式也隨之在全公司內推廣開來。

          8、垂直BFF模式時代(2016年至2019年)

          接上節(jié),當 B 站網關的架構發(fā)展為多套垂直 BFF 之后,開發(fā)團隊圍繞該模式平穩(wěn)迭代了相當長的一段時間。

          而后隨著B站業(yè)務的發(fā)展,團隊人員的擴充和幾次組織架構調整,此時開始出現(xiàn)直播、電商等獨立業(yè)務,這些業(yè)務的發(fā)展我們之后再細說。

          而在這些調整之后,有一個團隊的職責越來越清晰:主站網關組。

          主站網關組的主要職責就是維護上述各類功能的 BFF 網關,此時 bilibili 的主要流量入口為粉板 App。這里可以簡單細說一下粉板 App 上的所有業(yè)務組成。

          主站業(yè)務:

          • 1)網關組維護的 BFF,如推薦、稿件播放頁等;
          • 2)業(yè)務層自行維護的 BFF,如評論、彈幕、賬號等。

          獨立業(yè)務:

          • 1)電商服務;
          • 2)直播服務;
          • 3)動態(tài)服務。

          主站業(yè)務的 BFF 其實被分為兩類:

          • 1)一類是由網關組負責的 BFF;
          • 2)另一類是業(yè)務自行維護的 BFF。

          而這兩類 BFF 的技術棧其實基本一致,基本功能職責也相差不多。如此劃分的原因是讓網關組可以更專注于迭代客戶端特性功能,免去理解部分獨立業(yè)務場景的接口,如登陸頁應該讓對安全更專業(yè)賬號的同學自行維護。

          在這里我們也可以簡述一下,一個新需求應該如何決定參與的 BFF :

          • 1)如果這個功能能由業(yè)務層的業(yè)務 BFF 獨立完成,則網關組不需介入;
          • 2)如果該功能是一個客戶端特性需求,如推薦流等復合型業(yè)務,需要對接公司大量部門時,則由網關同學參與開發(fā) BFF。

          當時主站技術部的后端同學遵循以上兩個規(guī)則,基本能夠滿足業(yè)務的快速開發(fā)和迭代。

          我把這段時間稱為垂直 BFF 時代,因為基本主站每個業(yè)務或多或少都有各種形式的網關存在,大家通過這個網關向外提供接口,該網關和 SLB 進行直接交互。

          9、基于業(yè)務的統(tǒng)一API網關架構

          接上節(jié),我們再來談一談幾項重要的業(yè)務:電商、直播和動態(tài)。

          電商和直播其實并不是同一時期衍生的,直播在主站 PHP 時期就誕生了,而電商相對更晚一些。

          當時直播的技術棧組成有 C++、PHP、Go,其中早期大部分業(yè)務邏輯由 PHP 和 C++ 實現(xiàn),稍晚一些也開始逐步試用主站的 Go 實現(xiàn)部分業(yè)務邏輯。其中 PHP 負責對終端提供接口,C++ 主要實現(xiàn)核心業(yè)務功能。因此我們可以簡單理解為直播使用由 PHP 編寫的 BFF 網關。

          動態(tài)團隊其實派生自直播團隊,因此技術棧和直播當時基本一致,這里可以簡單省略。

          而眾所周知,大部分電商團隊的技術棧都是 Java 和 Spring 或 Dubbo。

          因這幾個業(yè)務實現(xiàn)上幾乎沒有相似的地方,且大家對 gRPC 協(xié)議逐漸地認同,因此技術棧上大家基本沒有大一統(tǒng)的想法,互相能調通即可。

          而隨著 B 站團隊進一步的壯大、流量持續(xù)的增長,進而經歷了諸多線上故障、事故分析之后,大家慢慢發(fā)現(xiàn)了這套架構下的各種問題。

          這些問題主要是:

          • 1)單個復雜模塊也會導致后續(xù)業(yè)務集成的高難度,根據康威法則,復雜聚合型 BFF 和多團隊之間就出現(xiàn)不匹配問題,團隊之間溝通協(xié)調成本高,交付效率低下;
          • 2)很多跨橫切面邏輯,比如安全認證,日志監(jiān)控,限流熔斷等。隨著時間的推移,功能的迭代,代碼變得越來越復雜,技術債越堆越多。

          此時:我們可能還需要一個能協(xié)調橫跨切面的組件,將路由、認證、限流、安全等組件全部上提,能夠統(tǒng)一更新發(fā)布,把業(yè)務集成度高的 BFF 層和通用功能服務層進行分層,進而大家開始引入基于業(yè)務的“統(tǒng)一API網關”架構(如下圖所示)。

          在新的架構中:統(tǒng)一網關承擔了重要的角色,它是解耦拆分和后續(xù)升級遷移的利器。

          在統(tǒng)一網關的配合下:單塊 BFF 實現(xiàn)了解耦拆分,各業(yè)務線團隊可以獨立開發(fā)和交付各自的微服務,研發(fā)效率大大提升。

          另外:把跨橫切面邏輯從 BFF 剝離到網關上去以后,BFF 的開發(fā)人員可以更加專注業(yè)務邏輯交付,實現(xiàn)了架構上的關注分離(Separation of Concerns)。

          10、從基于業(yè)務的多網關到全局統(tǒng)一網關(2022年至今)

          在這兩三年的時間里,各個業(yè)務團隊或多或少都有自己業(yè)務網關組建獨立的維護團隊,也為網關的功能作出過相當多的投入。

          但隨著 B 站業(yè)務的發(fā)展,公司級中間件功能的不斷更替演進,如果將對接各個中間件的工作在每個網關上都實現(xiàn)一次的話帶來的人力投入和溝通成本會相當巨大,且實現(xiàn)標準不統(tǒng)一、運營方式不統(tǒng)一無法起到 API 網關所帶來的最佳收益。

          因此微服務團隊開發(fā)了一款 B 站內部意義上的標準 API 網關(全局統(tǒng)一API網關),該 API 網關匯集以往各型網關中流量治理的優(yōu)秀經驗,對相關功能做出完善設計改進。

          該 API 網關的目前的主要功能除了常規(guī)的限流、熔斷、降級、染色外,還會基于這些基礎功能和公司各類中間件的基礎上,提供各種額外能力。

          這些額外進階型AP 質量治理的相關功能主要是:

          • 1)全鏈路灰度;
          • 2)流量采樣分析、回放;
          • 3)流量安全控制;
          • ...

          業(yè)務團隊在接入 API 網關后都可以一并獲得這些功能,為業(yè)務的迅速迭代做出力所能及的保障。

          11、不僅僅是 API 網關

          在開發(fā) API 網關的同時,我們也會更進一步關注業(yè)務團隊開發(fā)、對接 API 時的體驗,我們將以網關作為統(tǒng)一標準 API 規(guī)范的起點,為業(yè)務團隊提供更有效的 API 開發(fā)生態(tài)。

          這些API 開發(fā)生態(tài)可能是:

          • 1)規(guī)劃 API 業(yè)務域,簡化 SRE 運維;
          • 2)標準 API 元信息平臺;
          • 3)精確的 API 文檔和調試工具;
          • 4)類型安全的 API 集成 SDK;
          • 5)API 兼容性保障服務。

          API 網關是我們 API 治理生態(tài)中的一個標志性里程碑,我們希望在 API 網關的開發(fā)中能夠多多傾聽大家的意見,希望能有更多的聲音來幫助我們理清思路。

          本次 API 網關演進也以開源形式進行了開發(fā),在這里歡迎大家指導(本次源碼詳見本文“12、本文源碼)。

          12、本文源碼

          主地址:https://github.com/go-kratos/gateway

          備地址:https://github.com/52im/gateway

          或從原文鏈接中下載附件:http://www.52im.net/thread-3941-1-1.html

          13、參考資料

          [1] 喜馬拉雅自研億級API網關技術實踐

          [2] 手淘億級移動端接入層網關的技術演進之路

          [3] 從100到1000萬高并發(fā)的架構演進之路

          [4] 一文讀懂大型分布式系統(tǒng)設計的方方面面

          [5] 零基礎理解大型分布式架構的演進歷史、技術原理、最佳實踐

          本文已同步發(fā)布于:http://www.52im.net/thread-3941-1-1.html



          作者:Jack Jiang (點擊作者姓名進入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時通訊開發(fā)交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。


          只有注冊用戶登錄后才能發(fā)表評論。


          網站導航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 且末县| 临泽县| 承德市| 禹城市| 乌审旗| 成安县| 思南县| 长子县| 宝山区| 漳浦县| 南城县| 蒙城县| 郑州市| 成武县| 齐河县| 临沂市| 清丰县| 泰州市| 保德县| 和田市| 丘北县| 郧西县| 壶关县| 亚东县| 漳州市| 玛多县| 岚皋县| 简阳市| 利川市| 琼中| 马山县| 定兴县| 乐平市| 察雅县| 广平县| 营口市| 即墨市| 清远市| 梁河县| 永善县| 合阳县|