從0到100——知乎網站架構變遷史
也許很多人還不知道,知乎在規模上是僅次於百度貼吧和豆瓣的中文網際網路最大的UGC(使用者生成內容)社群。知乎創業三年來,從0開始,到現在已經有了100多臺伺服器。目前知乎的註冊使用者超過了1100萬,每個月有超過8000萬人使用;網站每個月的PV超過2.2億,差不多每秒鐘的動態請求超過2500。
在ArchSummit北京2014大會上,知乎聯合創始人兼 CTO 李申申帶來了知乎創業三年多來的首次全面技術分享(幻燈片下載)。本文系根據演講內容整理而成。
初期架構選型
在2010年10月真正開始動手做知乎這個產品時,包含李申申在內,最初只有兩位工程師;到2010年12月份上線時,工程師是四個。
知乎的主力開發語言是Python。因為Python簡單且強大,能夠快速上手,開發效率高,而且社群活躍,團隊成員也比較喜歡。
知乎使用的是Tornado框架。因為它支援非同步,很適合做實時comet應用,而且簡單輕量,學習成本低,再就是有FriendFeed 的成熟案例,Facebook 的社群支援。知乎的產品有個特性,就是希望跟瀏覽器端建立一個長連線,便於實時推送Feed和通知,所以Tornado比較合適。
最初整個團隊的精力全部放在產品功能的開發上,而其他方面,基本上能節約時間、能省的都用最簡單的方法來解決,當然這在後期也帶來了一些問題。
最初的想法是用雲主機,節省成本。知乎的第一臺伺服器是512MB記憶體的Linode主機。但是網站上線後,內測受歡迎程度超出預期,很多使用者反饋網站很慢。跨國網路延遲比想象的要大,特別是國內的網路不均衡,全國各地使用者訪問的情況都不太一樣。這個問題,再加上當時要做域名備案,知乎又回到了自己買機器找機房的老路上。
買了機器、找了機房之後又遇到了新的問題,服務經常宕掉。當時服務商的機器記憶體總是出問題,動不動就重啟。終於有一次機器宕掉起不來了,這時知乎就做了Web和資料庫的高可用。創業就是這樣一個情況,永遠不知道明早醒來的時候會面臨什麼樣的問題。
這是當時那個階段的架構圖,Web和資料庫都做了主從。當時的圖片服務託管在又拍雲上。 除了主從,為了效能更好還做了讀寫分離。為解決同步問題,又新增了一個伺服器來跑離線指令碼,避免對線上服務造成響應延遲。另外,為改進內網的吞吐量延遲, 還更換了裝置,使整個內網的吞吐量翻了20倍。
在2011年上半年時,知乎對Redis已經很依賴。除了最開始的佇列、搜尋在用,後來像Cache也開始使用,單機儲存成為瓶頸,所以引入了分片,同時做了一致性。
知乎團隊是一個很相信工具的團隊,相信工具可以提升效率。工具其實是一個過程,工具並沒有所謂的最好的工具,只有最適合的工具。而且它是在整個過程中,隨著整個狀態的變化、環境的變化在不斷髮生變化的。知乎自己開發或使用過的工具包括Profiling(函式級追蹤請求,分析調優)、Werkzeug(方便除錯的工具)、Puppet(配置管理)和Shipit(一鍵上線或回滾)等。
日誌系統
知乎最初是邀請制的,2011年下半年,知乎上線了申請註冊,沒有邀請碼的使用者也可以通過填寫一些資料申請註冊知乎。使用者量又上了一個臺階,這時就有了一些發廣告的賬戶,需要掃除廣告。日誌系統的需求提上日程。
這個日誌系統必須支援分散式收集、集中儲存、實時、可訂閱和簡單等特性。當時調研了一些開源系統,比如Scribe總體不錯,但是不支援訂閱。Kafka是Scala開發的,但是團隊在Scala方面積累較少,Flume也是類似,而且比較重。所以開發團隊選擇了自己開發一個日誌系統——Kids(Kids Is Data Stream)。顧名思義,Kids是用來彙集各種資料流的。
Kids參考了Scribe的思路。Kdis在每臺伺服器上可以配置成Agent或 Server。Agent直接接受來自應用的訊息,把訊息彙集之後,可以打給下一個Agent或者直接打給中心Server。訂閱日誌時,可以從 Server上獲取,也可以從中心節點的一些Agent上獲取。
具體細節如下圖所示:
知乎還基於Kids做了一個Web小工具(Kids Explorer),支援實時看線上日誌,現在已經成為除錯線上問題最主要的工具。
Kids已經開源,放到了Github上。
事件驅動的架構
知乎這個產品有一個特點,最早在新增一個答案後,後續的操作其實只有更新通知、更新動 態。但是隨著整個功能的增加,又多出了一些更新索引、更新計數、內容審查等操作,後續操作五花八門。如果按照傳統方式,維護邏輯會越來越龐大,維護性也會 非常差。這種場景很適合事件驅動方式,所以開發團隊對整個架構做了調整,做了事件驅動的架構。
這時首先需要的是一個訊息佇列,它應該可以獲取到各種各樣的事件,而且對一致性有很高的 要求。針對這個需求,知乎開發了一個叫Sink的小工具。它拿到訊息後,先做本地的儲存、持久化,然後再把訊息分發出去。如果那臺機器掛掉了,重啟時可以 完整恢復,確保訊息不會丟失。然後它通過Miller開發框架,把訊息放到任務佇列。Sink更像是序列訊息訂閱服務,但任務需要並行化處理, Beanstalkd就派上了用場,由其對任務進行全週期管理。架構如下圖所示:
舉例而言,如果現在有使用者回答了問題,首先系統會把問題寫到MySQL裡面,把訊息塞到Sink,然後把問題返回給使用者。Sink通過Miller把任務發給 Beanstalkd,Worker自己可以找到任務並處理。
最開始上線時,每秒鐘有10個訊息,然後有70個任務產生。現在每秒鐘有100個事件,有1500個任務產生,就是通過現在的事件驅動架構支撐的。
頁面渲染優化
知乎在2013年時每天有上百萬的PV,頁面渲染其實是計算密集型的,另外因為要獲取資料,所以也有IO密集型的特點。這時開發團隊就對頁面進行了元件化,還升級了資料獲取機制。知乎按照整個頁面元件樹的結構,自上而下分層地獲取資料,當上 層的資料已經獲取了,下層的資料就不需要再下去了,有幾層基本上就有幾次資料獲取。
結合這個思路,知乎自己做了一套模板渲染開發框架——ZhihuNode。
經歷了一系列改進之後,頁面的效能大幅度提升。問題頁面從500ms 減少到150ms,Feed頁面從1s減少到600ms。
面向服務的架構(SOA)
隨著知乎的功能越來越龐雜,整個系統也越來越大。知乎是怎麼做的服務化呢?
首先需要一個最基本的RPC框架,RPC框架也經歷了好幾版演進。
第一版是Wish,它是一個嚴格定義序列化的模型。傳輸層用到了STP,這是自己寫的很 簡單的傳輸協議,跑在TCP上。一開始用的還不錯,因為一開始只寫了一兩個服務。但是隨著服務增多,一些問題開始出現,首先是 ProtocolBuffer會 生成一些描述程式碼,很冗長,放到整個庫裡顯得很醜陋。另外嚴格的定義使其不便使用。這時有位工程師開發了新的RPC框架——Snow。它使用簡單的 JSON做資料序列化。但是鬆散的資料定義面對的問題是,比如說服務要去升級,要改寫資料結構,很難知道有哪幾個服務在使用,也很難通知它們,往往錯誤就 發生了。於是又出了第三個RPC框架,寫RPC框架的工程師,希望結合前面兩個框架的特點,首先保持Snow簡單,其次需要相對嚴格的序列化協議。這一版 本引入了 Apache Avro。同時加入了特別的機制,在傳輸層和序列化協議這一層都做成了可插拔的方式,既可以用JSON,也可以用Avro,傳輸層可以用STP,也可以用 二進位制協議。
再就是搭了一個服務註冊發現,只需要簡單的定義服務的名字就可以找到服務在哪臺機器上。同時,知乎也有相應的調優的工具,基於Zipkin開發了自己的 Tracing系統。
按照呼叫關係,知乎的服務分成了3層:聚合層、內容層和基礎層。按屬性又可以分成3類:資料服務、邏輯服務和通道服務。資料服務主要是一些要做特殊資料型別的儲存,比如圖片服務。邏輯服務更多的是CPU密集、計算密集的操作,比如答案格式的定義、解析等。通道服務的特點是沒有儲存,更多是做一個轉發,比如說Sink。
這是引入服務化之後整體的架構。
演講中還介紹了基於AngularJS開發知乎專欄的新實踐。後續我們將在網站上釋出演講視訊,敬請期待。
相關文章
- 從0到100——知乎架構變遷史架構
- 從100PV到1億級PV網站架構演變網站架構
- [轉載]從100PV到1億級PV網站架構演變網站架構
- 銀行IT架構變遷史(金融IT基礎架構)架構
- 大型網站應用中MySQL的架構演變史網站MySql架構
- 網站架構及架構演變網站架構
- 從零到百億網際網路金融架構發展史架構
- [轉載]大型網站應用中 MySQL 的架構演變史網站MySql架構
- mysql8.0 主從架構模式【0到1架構系列】MySql架構模式
- 【網站架構13/100】一步步帶你,如何網站架構網站架構
- 如何從 0 到 1 設計、構建移動分析架構架構
- 知乎容器化構建系統:從0到1支撐日近萬次構建部署
- 個人網站遷移之旅:從部落格到知識庫,從 Hexo 到 Docusaurus網站Hexo
- 大型網站架構體系的演變網站架構
- 網易馬進:DDB從分散式資料庫到結構化資料中心的架構變遷分散式資料庫架構
- 我也要談談大型網站架構之系列(1)——縱觀歷史演變(上)網站架構
- 我也要談談大型網站架構之系列(2)——縱觀歷史演變(下)網站架構
- 系統從初期到支撐億級流量,都經歷了哪些架構的變遷?架構
- 如何遷移 Hibernate架構到 spring架構?架構Spring
- <<從0到1學C++>> 第3篇 從結構到類的演變C++
- 大型網站架構系列:電商網站架構案例(1)網站架構
- 大型網站架構系列:電商網站架構案例(2)網站架構
- 大型網站架構系列:電商網站架構案例(3)網站架構
- 從 0 開始學架構架構
- 探索從 MVC 到 MVVM + Flux 架構模式的轉變MVCMVVMUX架構模式
- 淺談Web網站架構演變過程Web網站架構
- 大型網站技術架構——2. 網站架構模式網站架構模式
- 大型網站技術架構(二)--大型網站架構演化網站架構
- 大型網站技術架構(五)--網站高可用架構網站架構
- 大型網站技術架構(一)--大型網站架構演化網站架構
- 馬蜂窩 IM 移動端架構的從 0 到 1架構
- 大型網站架構網站架構
- 大型網站架構演變過程、大併發伺服器架構網站架構伺服器
- MySQL在大型網站的應用架構演變MySql網站應用架構
- 大型網站架構演變和知識體系網站架構
- 大型網站技術架構(八)--網站的安全架構網站架構
- Linux架構26 playbook實戰, 安裝資料庫, 網站遷移, ansible變數Linux架構資料庫網站變數
- 《架構基礎 從需求到架構》讀書架構