4月22日, B站部分後臺源代碼因為某憤怒的員工, 被上傳至Github. 本文我們不討論安全, 法律 (根據代碼漏洞, 去惡意攻擊或者獲利是違法的! 我們工作時也要注意代碼安全), 我僅從開發者的角度談談, 這份代碼我們能學到什麼? B站Golang生態建設, 代碼規範, 工具建設, 技術棧選擇, 對於Go在部門或公司的推廣又有哪些值得借鑑?
首先必須得說, B站這份代碼整體還是不錯的, 不是說組件或者基礎庫多麼的厲害, 而是從整體目錄分佈, 業務代碼分佈, API易用性, 業務代碼風格, 工具的統一, 上手難度上來評價.
這裡是一個小小的總結.
- 約329個Go服務, 歷史約170人左右貢獻過Go代碼.
- 代碼和目錄規範性比較好, 代碼生成工具建設比較好, 大家可以借鑑一下.
- 對於一個Golang開發者來說, 入職B站, 我覺得大概2-3天就可以copy&&paste開始貢獻業務代碼了. 其他語言開發者, 3-4天吧, 因為學習Golang花一天.
- B站Go不依賴CGO, 業務代碼可以在windows編譯通過! 啟動!
- 組件基本是基於開源組件封裝.
- RPC基於grpc封裝, 協議編碼為proto, 沒有我們通常那樣的包頭.
- 服務註冊與發現已經包裝在RPC中. 註冊使用自研的discovery, 基於類似url的方式去註冊和尋址.
- 數據存儲多使用memcache, redis和DB.
- hbase也使用比較多. 用於鑑權, 用戶數據存儲. 對於一些kv數據, 外部沒有支持冷熱分離的kv存儲, hbase是一個非常好的選擇: 基於HDFS, 熱數據加載到內存, 列式存儲, 強一致, 可配置副本數.
- 消息隊列為使用基於kafka, 實現了redis協議的databus.
- 小文件存儲: B站自己實現的bfs
- 監控上報使用的是prometheus, 對於中小公司, 沒法建設自己的監控組件, prometheus是很不錯的選擇.
- 簡單瀏覽了下, 這份代碼在SQL上沒有注入風險. 生產環境的配置並沒有在這份代碼中. 一個合格的開發者, 即使所有源碼流出去, 也不會對系統造成任何危害.
- 不過B站的代碼似乎打點監控做的不是很多(可能沒有太多的去強調?)
可以看出B站有一定的技術建設能力, 能夠基於開源技術棧做封裝和改進, 所選技術棧適合中小型公司業務. 技術總監毛劍水平的確挺不錯, 下面會給出兩篇B站在Gopher China上的分享.
詳細請看下文
PS: 學習完代碼已刪除, 不要問我要代碼哈.
嗶哩嗶哩的Go微服務實戰
文章上: https://mp.weixin.qq.com/s/bPFUGQDZCnt2aeIf7JI2cQ (主要講B站從PHP, Java轉為Go微服務之路)
文章下: https://mp.weixin.qq.com/s/4uA6iE7HC_SAfdIATAdrrA (主要講B站中間件建設情況)
視頻: https://www.bilibili.com/video/av29079011
以上兩篇(上面後兩篇)是B站公開分享的Go微服務實戰, 上文講B站的微服務演進, 下文講B站的中間件建設.
本文中很多情況的確和本文中一致. 詳細可參考這兩篇文章.
目錄結構及整體情況
通過main.go啟動文件統計, 整體約329個Go服務. 有170人左右貢獻過Go代碼.
整體目錄結構
admin是管理後臺的服務, service是提供RPC內部服務, job是處理消息隊列的服務, interface目錄是對外http的服務.
其中admin目錄下54個, infra目錄下5個基礎組件服務, interface下77個, job目錄下80個, service目錄下113個.
![一探B站後臺架構, 他山之石, 何以攻玉](http://p2.ttnews.xyz/loading.gif)
整理目錄結構
可以看出來B站Go後臺代碼管理使用的是一個大倉庫的方式(從源碼目錄整齊度以及大倉庫的README來看, 應該是這樣的, 當然還有個東西叫git submodule). 這種方式有好處也有壞處.
- 上手很快, 所有的庫, 依賴, 業務都在一個倉庫中, 下載了就有提示, 馬上開始擼代碼.
- 後期版本管理變得很混亂. 分支開發也很重.
我在前公司也有這種情況, 前人把大概某20個服務放在一個倉庫中, 後續的git log簡直沒法看. 幸好後面大家沒這麼做了.
服務目錄結構
![一探B站後臺架構, 他山之石, 何以攻玉](http://p2.ttnews.xyz/loading.gif)
服務目錄結構
cmd: 放main.go和配置文件, 作為啟動入口
conf: 放配置文件對應的golang struct, 使用的是toml
model: 放結構體, 比如Http參數轉換用的struct, DB存儲對應的struct, 各層之間傳遞用的struct
dao: data access object, 數據庫訪問方法, redis, memcache訪問方法, 還有一些RPC調用也放在這裡面
http: 提供http服務, 主要是提供協議轉換, 聚合. 邏輯還是再service層做.
service: 對於後端服務來說, 該目錄提供服務的實現, 對於http服務, 該目錄提供http服務的實現.
目錄規範性
所有的服務均遵守該目錄結構. model層放VO, DO等, dao層用於數據層封裝, 隔離本服務的領域邏輯與外部數據. http層提供協議轉換. service實現具體邏輯.
比較像Java開發的模式, 可能在公司很多人不是很喜歡這樣複雜的目錄, 喜歡什麼都放在一個目錄下.
不過這樣的分目錄是一種比較好的實踐. 各層分的清清楚楚, 一個服務從1個接口到10個接口, 都比較清晰. 對於服務改動來說,也比較好聚焦於某一層.
生成工具的重要性
目錄做到規範性, 服務維護, 其他人接手也容易多了. 然而大家都是有各自習慣, 每個人都喜歡偷懶, 靠規範, 靠說教來使得程序員保持目錄規範, 實踐證明是不可能的. 所以得靠生成工具.你給程序員生成好的代碼目錄和模式, 99%的人是不會去改的...能把業務邏輯實現了, 還管其他的幹啥?
此份代碼的300多個服務, 目錄都是一致的, 不管是http服務, 還是接收消息隊列的服務, 還是後臺service. 同時service包下, http包下的代碼流程都基本一致, rpc調用方式一致, 都是靠生成工具來實現.
B站Golang技術棧分析
技術棧技術選型參考鏈接RPC基於grpc封裝的warden框架, 已開源https://github.com/bilibili/kratosHTTP框架基於gin封裝的blade master框架, 已開源同上服務註冊與發現初期為zk, 後面逐步改為參考Spring Cloud體系Eureka自研的discovery已開源 https://github.com/bilibili/discovery存儲DB, redis, memcache, hbase存儲一些用戶kv信息和歷史流水, 已封裝好庫 library/database/client庫已開源 https://github.com/bilibili/kratos搜索B站視頻, 用戶, 歷史記錄等使用es搜索, 客戶端已封裝在基礎庫中 library/database/elastic小文件存儲毛劍個人研發的bfs, 已開源. https://github.com/Terry-Mao/bfs消息隊列基於kafka封裝的databuslog基於uber的zap封裝的日誌框架配置及配置中心支持從環境變量讀取配置, 從toml中解析配置, 支持遠程配置中心(自研, mysql存儲, 本地落地,http協議, long poll, 客戶端有更新事件, 類似於攜程開源的Apollo)監控使用開源的prometheus, 框架和庫(sql, redis, hbase等)中已預埋計數點和時間統計點, 同時也可以在業務邏輯中打點. library/stat/stat.gotracetrace似乎是基於agent的方式, 使用unix domain socket進行傳送, 框架和庫已預埋點. library/net/trace.go研發流程管理TAPD, 哈哈, 有相關的tapd struct信息
其中RPC, HTTP框架, 數據訪問的一些庫封裝, 包括生成工具, 均以kratos項目在github開源了(https://github.com/bilibili/kratosKratos是bilibili開源的一套Go微服務框架,包含大量微服務相關框架及工具)
B站目前使用及封裝的中間件的詳細介紹在Gopher China 2017 B站的分享有提到原理和使用情況.
https://mp.weixin.qq.com/s/4uA6iE7HC_SAfdIATAdrrA
bfs介紹
https://www.jianshu.com/p/923917220d23
B站運維體系發展
https://myslide.cn/slides/3840
總結
簡單分析了下B站的代碼風格和後臺架構, 目錄規範性, 工具建設均做的不錯, 其中代碼生成工具做的很好, http服務, 後臺grpc服務,均可通過proto生成(目前now也是這樣做的), 也有使用go ast進行生成的工具(大家可以參考一下).
中間件方面, 技術選型大部分為一些目前業界比較實用和流行的開源組件, 進行了一些封裝, 比較適合員工上手. 同時像配置中心, 小文件存儲, 為自研. 全套解決方案比較關鍵路徑均開源.
可以看出B站有一定的技術建設能力. 技術選型比較符合中小型公司的實際情況.
對於我們而言, 可以借鑑一下, 完善生成工具, 提高API的易用性, 降低入門門檻, 根據業務選用適合組件.
閱讀更多 guorenweitianxia 的文章