一探B站后臺(tái)架構(gòu), 他山之石, 何以攻玉? -- 僅從一個(gè)一線Golang開(kāi)發(fā)者的角度談B站4.22代碼

4月22日, B站部分后臺(tái)源代碼因?yàn)槟硲嵟膯T工, 被上傳至Github. 本文我們不討論安全, 法律 (根據(jù)代碼漏洞, 去惡意攻擊或者獲利是違法的! 我們工作時(shí)也要注意代碼安全), 我僅從開(kāi)發(fā)者的角度談?wù)? 這份代碼我們能學(xué)到什么? B站Golang生態(tài)建設(shè), 代碼規(guī)范, 工具建設(shè), 技術(shù)棧選擇, 對(duì)于Go在部門(mén)或公司的推廣又有哪些值得借鑒?

首先必須得說(shuō), B站這份代碼整體還是不錯(cuò)的, 不是說(shuō)組件或者基礎(chǔ)庫(kù)多么的厲害, 而是從整體目錄分布, 業(yè)務(wù)代碼分布, API易用性, 業(yè)務(wù)代碼風(fēng)格, 工具的統(tǒng)一, 上手難度上來(lái)評(píng)價(jià).
這里是一個(gè)小小的總結(jié).

  1. 約329個(gè)Go服務(wù), 歷史約170人左右貢獻(xiàn)過(guò)Go代碼.
  2. 代碼和目錄規(guī)范性比較好, 代碼生成工具建設(shè)比較好, 大家可以借鑒一下.
  3. 對(duì)于一個(gè)Golang開(kāi)發(fā)者來(lái)說(shuō), 入職B站, 我覺(jué)得大概2-3天就可以copy&&paste開(kāi)始貢獻(xiàn)業(yè)務(wù)代碼了. 其他語(yǔ)言開(kāi)發(fā)者, 3-4天吧, 因?yàn)閷W(xué)習(xí)Golang花一天.
  4. B站Go不依賴CGO, 業(yè)務(wù)代碼可以在windows編譯通過(guò)! 啟動(dòng)!
  5. 組件基本是基于開(kāi)源組件封裝.
  6. RPC基于grpc封裝, 協(xié)議編碼為proto, 沒(méi)有我們通常那樣的包頭.
  7. 服務(wù)注冊(cè)與發(fā)現(xiàn)已經(jīng)包裝在RPC中. 注冊(cè)使用自研的discovery, 基于類似url的方式去注冊(cè)和尋址.
  8. 數(shù)據(jù)存儲(chǔ)多使用memcache, redis和DB.
  9. hbase也使用比較多. 用于鑒權(quán), 用戶數(shù)據(jù)存儲(chǔ). 對(duì)于一些kv數(shù)據(jù), 外部沒(méi)有支持冷熱分離的kv存儲(chǔ), hbase是一個(gè)非常好的選擇: 基于HDFS, 熱數(shù)據(jù)加載到內(nèi)存, 列式存儲(chǔ), 強(qiáng)一致, 可配置副本數(shù).
  10. 消息隊(duì)列為使用基于kakfa, 實(shí)現(xiàn)了redis協(xié)議的databus.
  11. 小文件存儲(chǔ): B站自己實(shí)現(xiàn)的bfs
  12. 監(jiān)控上報(bào)使用的是prometheus, 對(duì)于中小公司, 沒(méi)法建設(shè)自己的監(jiān)控組件, prometheus是很不錯(cuò)的選擇.
  13. 簡(jiǎn)單瀏覽了下, 這份代碼在SQL上沒(méi)有注入風(fēng)險(xiǎn). 生產(chǎn)環(huán)境的配置并沒(méi)有在這份代碼中. 一個(gè)合格的開(kāi)發(fā)者, 即使所有源碼流出去, 也不會(huì)對(duì)系統(tǒng)造成任何危害.
  14. 不過(guò)B站的代碼似乎打點(diǎn)監(jiān)控做的不是很多(可能沒(méi)有太多的去強(qiáng)調(diào)?)

可以看出B站有一定的技術(shù)建設(shè)能力, 能夠基于開(kāi)源技術(shù)棧做封裝和改進(jìn), 所選技術(shù)棧適合中小型公司業(yè)務(wù). 技術(shù)總監(jiān)毛劍水平的確挺不錯(cuò), 下面會(huì)給出兩篇B站在Gopher China上的分享.
詳細(xì)請(qǐng)看下文

PS: 學(xué)習(xí)完代碼已刪除, 不要問(wèn)我要代碼哈.

[TOC]

嗶哩嗶哩的Go微服務(wù)實(shí)戰(zhàn)
文章上: https://mp.weixin.qq.com/s/bPFUGQDZCnt2aeIf7JI2cQ (主要講B站從PHP, Java轉(zhuǎn)為Go微服務(wù)之路)
文章下: https://mp.weixin.qq.com/s/4uA6iE7HC_SAfdIATAdrrA (主要講B站中間件建設(shè)情況)
視頻: https://www.bilibili.com/video/av29079011

以上兩篇(上面后兩篇)是B站公開(kāi)分享的Go微服務(wù)實(shí)戰(zhàn), 上文講B站的微服務(wù)演進(jìn), 下文講B站的中間件建設(shè).
本文中很多情況的確和本文中一致. 詳細(xì)可參考這兩篇文章.

目錄結(jié)構(gòu)及整體情況

通過(guò)main.go啟動(dòng)文件統(tǒng)計(jì), 整體約329個(gè)Go服務(wù). 有170人左右貢獻(xiàn)過(guò)Go代碼.

整體目錄結(jié)構(gòu)

admin是管理后臺(tái)的服務(wù), service是提供RPC內(nèi)部服務(wù), job是處理消息隊(duì)列的服務(wù), interface目錄是對(duì)外http的服務(wù).
其中admin目錄下54個(gè), infra目錄下5個(gè)基礎(chǔ)組件服務(wù), interface下77個(gè), job目錄下80個(gè), service目錄下113個(gè).


整理目錄結(jié)構(gòu)

可以看出來(lái)B站Go后臺(tái)代碼管理使用的是一個(gè)大倉(cāng)庫(kù)的方式(從源碼目錄整齊度以及大倉(cāng)庫(kù)的README來(lái)看, 應(yīng)該是這樣的, 當(dāng)然還有個(gè)東西叫g(shù)it submodule). 這種方式有好處也有壞處.

  1. 上手很快, 所有的庫(kù), 依賴, 業(yè)務(wù)都在一個(gè)倉(cāng)庫(kù)中, 下載了就有提示, 馬上開(kāi)始擼代碼.
  2. 后期版本管理變得很混亂. 分支開(kāi)發(fā)也很重.

我在前公司也有這種情況, 前人把大概某20個(gè)服務(wù)放在一個(gè)倉(cāng)庫(kù)中, 后續(xù)的git log簡(jiǎn)直沒(méi)法看. 幸好后面大家沒(méi)這么做了.

服務(wù)目錄結(jié)構(gòu)

服務(wù)目錄結(jié)構(gòu)
cmd: 放main.go和配置文件, 作為啟動(dòng)入口
conf: 放配置文件對(duì)應(yīng)的golang struct, 使用的是toml
model: 放結(jié)構(gòu)體, 比如Http參數(shù)轉(zhuǎn)換用的struct, DB存儲(chǔ)對(duì)應(yīng)的struct, 各層之間傳遞用的struct
dao: data access object, 數(shù)據(jù)庫(kù)訪問(wèn)方法, redis, memcache訪問(wèn)方法, 還有一些RPC調(diào)用也放在這里面
http: 提供http服務(wù), 主要是提供協(xié)議轉(zhuǎn)換, 聚合. 邏輯還是再service層做.
service: 對(duì)于后端服務(wù)來(lái)說(shuō), 該目錄提供服務(wù)的實(shí)現(xiàn), 對(duì)于http服務(wù), 該目錄提供http服務(wù)的實(shí)現(xiàn).

目錄規(guī)范性

所有的服務(wù)均遵守該目錄結(jié)構(gòu). model層放VO, DO等, dao層用于數(shù)據(jù)層封裝, 隔離本服務(wù)的領(lǐng)域邏輯與外部數(shù)據(jù). http層提供協(xié)議轉(zhuǎn)換. service實(shí)現(xiàn)具體邏輯.
比較像Java開(kāi)發(fā)的模式, 可能在公司很多人不是很喜歡這樣復(fù)雜的目錄, 喜歡什么都放在一個(gè)目錄下.
不過(guò)這樣的分目錄是一種比較好的實(shí)踐. 各層分的清清楚楚, 一個(gè)服務(wù)從1個(gè)接口到10個(gè)接口, 都比較清晰. 對(duì)于服務(wù)改動(dòng)來(lái)說(shuō),也比較好聚焦于某一層.

生成工具的重要性

目錄做到規(guī)范性, 服務(wù)維護(hù), 其他人接手也容易多了. 然而大家都是有各自習(xí)慣, 每個(gè)人都喜歡偷懶, 靠規(guī)范, 靠說(shuō)教來(lái)使得程序員保持目錄規(guī)范, 實(shí)踐證明是不可能的. 所以得靠生成工具.你給程序員生成好的代碼目錄和模式, 99%的人是不會(huì)去改的...能把業(yè)務(wù)邏輯實(shí)現(xiàn)了, 還管其他的干啥?

此份代碼的300多個(gè)服務(wù), 目錄都是一致的, 不管是http服務(wù), 還是接收消息隊(duì)列的服務(wù), 還是后臺(tái)service. 同時(shí)service包下, http包下的代碼流程都基本一致, rpc調(diào)用方式一致, 都是靠生成工具來(lái)實(shí)現(xiàn).

B站Golang技術(shù)棧分析

技術(shù)棧 技術(shù)選型 參考鏈接
RPC 基于grpc封裝的warden框架, 已開(kāi)源 https://github.com/bilibili/kratos
HTTP框架 基于gin封裝的blade master框架, 已開(kāi)源 同上
服務(wù)注冊(cè)與發(fā)現(xiàn) 初期為zk, 后面逐步改為參考Spring Cloud體系Eureka自研的discovery 已開(kāi)源 https://github.com/bilibili/discovery
存儲(chǔ) DB, redis, memcache, hbase存儲(chǔ)一些用戶kv信息和歷史流水, 已封裝好庫(kù) library/database/ client庫(kù)已開(kāi)源 https://github.com/bilibili/kratos
搜索 B站視頻, 用戶, 歷史記錄等使用es搜索, 客戶端已封裝在基礎(chǔ)庫(kù)中 library/database/elastic
小文件存儲(chǔ) 毛劍個(gè)人研發(fā)的bfs, 已開(kāi)源. https://www.toutiao.com/i6272104949560115714/ https://github.com/Terry-Mao/bfs
消息隊(duì)列 基于kafka封裝的databus
log 基于uber的zap封裝的日志框架
配置及配置中心 支持從環(huán)境變量讀取配置, 從toml中解析配置, 支持遠(yuǎn)程配置中心(自研, mysql存儲(chǔ), 本地落地,http協(xié)議, long poll, 客戶端有更新事件, 類似于攜程開(kāi)源的Apollo)
監(jiān)控 使用開(kāi)源的prometheus, 框架和庫(kù)(sql, redis, hbase等)中已預(yù)埋計(jì)數(shù)點(diǎn)和時(shí)間統(tǒng)計(jì)點(diǎn), 同時(shí)也可以在業(yè)務(wù)邏輯中打點(diǎn). library/stat/stat.go
trace trace似乎是基于agent的方式, 使用unix domain socket進(jìn)行傳送, 框架和庫(kù)已預(yù)埋點(diǎn). library/net/trace.go
研發(fā)流程管理 TAPD, 哈哈, 有相關(guān)的tapd struct信息

其中RPC, HTTP框架, 數(shù)據(jù)訪問(wèn)的一些庫(kù)封裝, 包括生成工具, 均以kratos項(xiàng)目在github開(kāi)源了(https://github.com/bilibili/kratos Kratos是bilibili開(kāi)源的一套Go微服務(wù)框架镣屹,包含大量微服務(wù)相關(guān)框架及工具)

B站目前使用及封裝的中間件的詳細(xì)介紹在Gopher China 2017 B站的分享有提到原理和使用情況.
https://mp.weixin.qq.com/s/4uA6iE7HC_SAfdIATAdrrA
bfs介紹
http://www.reibang.com/p/923917220d23
B站運(yùn)維體系發(fā)展
https://myslide.cn/slides/3840

總結(jié)

簡(jiǎn)單分析了下B站的代碼風(fēng)格和后臺(tái)架構(gòu), 目錄規(guī)范性, 工具建設(shè)均做的不錯(cuò), 其中代碼生成工具做的很好, http服務(wù), 后臺(tái)grpc服務(wù),均可通過(guò)proto生成(目前now也是這樣做的), 也有使用go ast進(jìn)行生成的工具(大家可以參考一下).
中間件方面, 技術(shù)選型大部分為一些目前業(yè)界比較實(shí)用和流行的開(kāi)源組件, 進(jìn)行了一些封裝, 比較適合員工上手. 同時(shí)像配置中心, 小文件存儲(chǔ), 為自研. 全套解決方案比較關(guān)鍵路徑均開(kāi)源.
可以看出B站有一定的技術(shù)建設(shè)能力. 技術(shù)選型比較符合中小型公司的實(shí)際情況.

對(duì)于我們而言, 可以借鑒一下, 完善生成工具, 提高API的易用性, 降低入門(mén)門(mén)檻, 根據(jù)業(yè)務(wù)選用適合組件.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市价涝,隨后出現(xiàn)的幾起案子女蜈,更是在濱河造成了極大的恐慌,老刑警劉巖色瘩,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伪窖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡居兆,警方通過(guò)查閱死者的電腦和手機(jī)覆山,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泥栖,“玉大人簇宽,你說(shuō)我怎么就攤上這事勋篓。” “怎么了魏割?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵譬嚣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我钞它,道長(zhǎng)拜银,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任须揣,我火速辦了婚禮盐股,結(jié)果婚禮上钱豁,老公的妹妹穿的比我還像新娘耻卡。我一直安慰自己,他們只是感情好牲尺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布卵酪。 她就那樣靜靜地躺著,像睡著了一般谤碳。 火紅的嫁衣襯著肌膚如雪溃卡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天蜒简,我揣著相機(jī)與錄音瘸羡,去河邊找鬼。 笑死搓茬,一個(gè)胖子當(dāng)著我的面吹牛犹赖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卷仑,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼峻村,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了锡凝?” 一聲冷哼從身側(cè)響起粘昨,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窜锯,沒(méi)想到半個(gè)月后张肾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锚扎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年吞瞪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片工秩。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尸饺,死狀恐怖进统,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浪听,我是刑警寧澤螟碎,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站迹栓,受9級(jí)特大地震影響掉分,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜克伊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一酥郭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愿吹,春花似錦不从、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至坷衍,卻和暖如春寝优,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枫耳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工乏矾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迁杨。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓钻心,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親仑最。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扔役,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348