好的架構不是設計出來的,而是演進出來的

来源:http://www.cnblogs.com/seexmq/archive/2017/09/18/7545944.html
-Advertisement-
Play Games

對很多創業公司而言,很難在初期就預估到流量十倍、百倍以及千倍以後網站架構會是什麼樣的一個狀況。同時,如果系統初期就設計一個千萬級併發的流量架構,很難有公司可以支撐這個成本。 因此,這裡主要會關註架構的眼花。在每個階段,找到對應該階段網站架構所面臨的問題,然後在不斷解決這些問題,在這個過程中整個架構會 ...


對很多創業公司而言,很難在初期就預估到流量十倍、百倍以及千倍以後網站架構會是什麼樣的一個狀況。同時,如果系統初期就設計一個千萬級併發的流量架構,很難有公司可以支撐這個成本。

因此,這裡主要會關註架構的眼花。在每個階段,找到對應該階段網站架構所面臨的問題,然後在不斷解決這些問題,在這個過程中整個架構會一直演進。

在58同城建立之初,站點的流量非常小,可能也就是十萬級別,這也就意味著,平均每秒鐘也就是幾次的訪問,此時網站架構的特點是:請求量比較低,數據量比較小,代碼量也比較小。這個時候的站點可以被幾個工程師輕易搞定,因此根本沒什麼“架構”可言。

其實這也是很多創業公司初期面臨的問題,最開始58同城的站點架構用一個詞概括就是“ALL IN ONE”,如下圖所示:

就像一個單機系統,所有的東西都部署在一臺機器上,包括站點、資料庫、文件等等。而工程師每天的核心工作就是CURD,前端傳過來一些數據,然後業務邏輯層拼裝成一些CURD訪問資料庫,資料庫返回數據,數據拼裝成頁面,最終返回到瀏覽器。相信很多創業團隊初期都面臨一個與之類似的情況,每天寫代碼,寫SQL、介面參數、訪問數據等等。

這裡需要說明一個問題,大家都知道最初58同城使用的是Windows、iis、SQL-Sever、C#這條路。現在很多創業公司可能就不會這麼做。

如果可以重來?那麼會選擇LAMP

很多創業的同學可能會想,初期什麼樣的一個架構合適? 如果重來,站在現在這個角度上58會選擇LAMP,為什麼?首先是無須編譯,而且快速發佈功能強大,從前端到後端、資料庫訪問、業務邏輯處理等等全部可以搞定,最重要都是成熟的開源產品,完全免費的。如果使用LAMP搭建一個論壇,兩天的時間就足夠了。所以,如果在創業初期,就儘量不要再使用Windows。

在這個階段58同城面臨的主要問題是什麼?其實就是招人,最初工程師寫CURD都容易出錯。當時引進了DAO和ORM,從而避免直接面對CURD語句,而是面對工程師比較擅長的是面向對象,能夠極大的提高工作效率,降低出錯率。

中等規模:流量跨過十萬的階段,資料庫成為瓶頸

隨著58同城的高速增長,系統很快跨越了十萬流量階段。主要需求是什麼?網站能夠正常訪問,當然速度更快點就好了。而此時系統面臨的問題有:在流量峰值期容易宕機,因為大量的請求會壓到資料庫上,所以資料庫成為新的瓶頸,從而,人越多訪問越慢。而在這個時候,機器數量也從一臺變成了多台,所以很自然的行程了分散式架構,如下圖所示:

首先,使用了一些非常常見的技術,一方面是動靜分離,動態的頁面通過Web-Servre訪問,靜態的像圖片等就單獨放到了一些伺服器上。另外一點就是讀寫分離。其實,對58同城或者說絕大部分的站點而言,一般來說都是讀多寫少。對58同城來說,絕大部分用戶是訪問信息,只有很少的用戶過來發貼。那麼如何擴展整個站點架構的讀請求呢?常用的是主從同步,讀寫分離。同時原來只有一個資料庫,現在使用多個不同的資料庫提供服務,這樣的話,就擴展了讀寫,很快就解決了中等規模下數據訪問的問題。

在這個階段,系統的主要矛盾就是“站點耦合+讀寫延時”,58同城是如何進行解耦,如何緩解延時呢?

對58同城而言,典型業務場景是主頁,發佈信息有發佈頁,信息聚合、標題聚合有列表頁,點開一個標題有詳細頁,而這些站點都是耦合在一個程式中的,或者說耦合在一個站點中的,當一個站點出現問題,整個站點就會因為耦合一起出問題。

第二個問題,大家都知道做資料庫讀請求和寫請求,分佈在不同的資料庫上,這個時候如果再讀取可能讀到的是舊數據,因為讀寫有一個延時。如果有用戶發帖子,馬上去找的話肯定找不到,很可能帶來的後果就是陸續在發佈兩條信息,這就是一個很大的問題。尤其是在請求量越來越大的時候,這個問題就更加突出。

在解決這些問題時,最先想到的是針對原來站點的核心業務做切分,然後工程師根據自己的站點和業務場景進行細分。首先,業務拆分是58同城最先嘗試的優化——將業務垂直拆分成了首頁和發佈頁。另外,在資料庫層面,隨之也進行了拆分,將大數據量拆分成一個個小的數據量。這樣,讀寫延時就馬上得到了緩解。尤其是在代碼拆分成了不同的層面之後,站點耦合也得到了緩解,數據載入速度也提升了很多。

當時,還使用了一些技術,前面也提到了對動態資源和靜態資源進行拆分。其中,我們對靜態資源使用了CDN服務,便於數據緩存和就近訪問,訪問速度得到很明顯的提升。除此之外,還使用了MVC模式,擅長前端的去做展示層,擅長協作邏輯的工程師就做Contorller,擅長數據的人就負責數據,效率就會逐步的提高,最後就是負載均衡技術。

大流量:將整個Windows技術體系轉向了Java體系

流量越來越大,當流量超過一千多萬時,58同城面臨的最大問題就是性能和成本。此前曾提到58同城最初的技術選型是Windows,整個網站的性能變得非常之低。即使進行了業務拆分和一些優化,依然解決不了這個問題,所以當時做了一個非常艱難的決定,就是轉型:將整個Windows技術體系轉向了Java體系,這涵蓋了操作系統、資料庫等多個維度。

其實,現在很多大的互聯網公司在流量從小到大的過程中都經歷過轉型,包括京東、淘寶等等。對技術的要求越來越高,任何一個站點都不能掛,對站點的可用性要求也是越來越高。

就在這個時候,58同城業務量也出現一個爆發期。於是招聘了很多工程師,大家一起寫越來越多的站點,但是發現效率很低,經常做一些重覆性的工作,比如參數解析等等。同時,業務之間相互依賴,無論是分類的子系統還是信息的子系統,二手車業務、房產業務都要訪問用戶和信息等一些底層數據,代碼之間頻繁的溝通,效率也不可能很高。

問題隨之而來,站點數越來越多,數據量越來越大,機器數從最開始的幾臺上升到幾百台的級別。那麼如何提供整個架構的可用性呢?首先,在上層進行了一些改進和優化,再做進一步的垂直拆分,同時引入了Cache,如下圖所示:

在架構的改進上,這裡構建了一個相對獨立的服務層,這個服務層做的每個業務線都會寫對應的代碼。如果用戶發出請求,就由這個服務層統一來管理,所有的上游業務線就像調用本地函數一樣,通過IDC的框架來調用這個服務。整個用戶登錄先訪問Cache,如果Cache變動了就直接返回,如果Cache不變動,就會訪問資料庫,這樣把資料庫的數據拿到本地再放回Cache,再打回上一輪。如此一來,業務邏輯全部封裝在這個服務的上游管理,該業務邏輯只有服務層能夠編寫代碼,然後由這個服務層集中管理、集中優化,這樣就提高了效率。

除此之外,為了保證站點的高可用,主要使用了反向代理技術。因為對用戶而言,他主要為了使用58同城的服務,不會關註訪問是58同城或者有十臺首頁的伺服器。58同城通過反向代理技術,通過DNS群,通過LVS技術,來保證接入層的高可用性,同時還保證了服務層、站點層、數據層的高可用。另外,為了保證高可用還使用了冗餘的方法,無論是站點服務和數據服務都可以使用這種方式進行解決,一個站點不可用,就換一個站點,一個資料庫不夠用,就多加幾個。當然,數據冗餘也會帶來一些副作用,如果數據量更新的話,那就需要將所有的“冗餘”都要進行更新。

58同城也做了一個圖片存儲系統,開始都是存儲在操作系統之上,隨著新增站點、新增服務,壓力就變得越來越大。於是,58同城就自建了站點框架和服務框架,現在這兩個框架也已經開源(如何降低站點開發成本?https://github.com/58code/Argo 如何降低服務開發成本? https://github.com/58code/Gaea )只需要修改一些基本的配置就可以使用了。

當架構變成“蜘蛛網”,人肉已很難搞定!

隨著用戶量、數據量併發量進一步的增長,58同城也拓展了很多的新業務,那麼對產品迭代速度要求就非常高,整體的架構對自動化的要求越來越高。

為了支撐業務的發展,技術團隊對架構做了進一步的解耦,另外就是引入了配置中心,如果要訪問任何一個服務,不會直接在本地的配置中留下一個服務,配置中心告訴這個服務的特點,如果擴展的話,配置中心自動下達消息,如果有機器要下線的話,配置中心會反向通過發郵件的方式進行通知。

而柔性服務是指當流量增加的時候,自動的新增服務。可以看到進一步解耦之後,有垂直業務、無線業務、集成業務等等,這些子系統之間都是通過配置中心相應之間發生關係的。

另一點就是關於資料庫,當某一點成為一個業務線重點的時候,就會集中解決這個點的問題。最初期的時候每個業務線都要訪問資料庫,訪問緩存,訪問用戶數據,於是把代碼集中的放到了服務層。現在數據量越來越大,大家都要做數據切分,每個業務線都做切分,這個時候58同城的每個頁面都面對這樣的痛點,於是把這個痛點拿到集中的層面來解決。

最後一點就是效率矛盾,此時有很多問題,靠“人肉”已經很難進行搞定了。這就需要自動化,包括回歸、測試、運維、監控等等都要回歸到自動化。

這裡需要補充一點,就是在產品層面引入了智能化,比如說智能推薦,主動推薦一些相關的話題;智能廣告,通過一些智能的策略,讓用戶對廣告的點擊更多,增加對58同城的收錄;智能搜索,在搜索的過程中加入一些搜索的策略,可以提高搜索的權重,也可以增加58同城的PV。當然,所有的自動化的產品背後都是由技術在驅動。

未來的挑戰

現在,58同城的流量已經突破了10億量級,那麼架構上未來面臨哪些挑戰呢?一方面是無線化、移動化。另一方面就是需求的變化,必須加快迭代一些東西。如果擁有10億的流量,卻跑在一億的架構上肯定是不行的。未來,還會使用更多的並行計算、實時計算,如果能做到實時推薦,效果肯定非常好,這也是挑戰之一。最後一點,58同城現在的伺服器大概在3000台左右,未來將拓展到10000台,這就是運維的挑戰了。



 

總結

最後做一個小的總結,網站在不同的階段遇到的問題不一樣,而解決這些問題使用的技術也不一樣,流量小的時候,主要目的是提高開發效率,在早期要引入ORM,DAO這些技術。隨著流量變大,使用動靜分離、讀寫分離、主從同步、垂直拆分、CDN、MVC等方式不斷地提升網站穩定性。面對更大的流量時,通過垂直拆分、服務化、反向代理、開發框架(站點/服務)等等,不斷提升高可用。在面對上億級的更大流量時,通過中心化、柔性服務、消息匯流排、自動化(回歸,測試,運維,監控)來迎接新的挑戰。未來的就是繼續實現.

作者:58沈劍



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目描述 形如2P-1的素數稱為麥森數,這時P一定也是個素數。但反過來不一定,即如果P是個素數,2P-1不一定也是素數。到1998年底,人們已找到了37個麥森數。最大的一個是P=3021377,它有909526位。麥森數有許多重要應用,它與完全數密切相關。 任務:從文件中輸入P(1000<P<310 ...
  • 上次我們講了Java中的一些基本的語法;今天我們就講一點內容,來說說Java中的方法和方法重載以及需要註意的一些地方; 方法: Java的方法類似與其他語言的函數,是一段用來完成特定功能的代碼片段, 聲明格式: [修飾符1 修飾符2 ....] ,返回值類型 方法名 (形式參數列表) { Java語 ...
  • 要理解select.select模塊其實主要就是要理解它的參數, 以及其三個返回值。select()方法接收並監控3個通信列表, 第一個是所有的輸入的data,就是指外部發過來的數據,第2個是監控和接收所有要發出去的data(outgoing data),第3個監控錯誤信息在網上一直在找這個sele ...
  • 由於最近新上的項目很多模塊沒有做數據緩存,大量的請求都會到資料庫去查詢,為了減輕資料庫的壓力以及提高網站響應速度,所以在這裡採用了spring 提供的註解+redis實現對數據的緩存,主要針對非熱點數據,例如 省市,銀行卡列表等做緩存,在這裡主要是查詢做一個緩存實例。 pom.xml (加入spri ...
  • 序 好久沒寫設計模式了,自從寫了兩篇之後,就放棄治療了,主要還是工作太忙了啊(藉口,都是藉口),過完年以後一直填坑,填了好幾個月,總算是穩定下來了,可以打打醬油了。 為什麼又重新開始寫設計模式呢?學習使我快樂啊(我裝逼起來我自己都害怕),其實主要是最近填坑的時候看源代碼有點暈,很多代碼不知道他們為什 ...
  • 單例,故名思議,一個只能創建一個實例的類。 單例被廣泛應用於Spring的bean(預設)、線程池、資料庫連接池、緩存,還有其他一些無狀態的類如servlet。 一個沒必要多例的類實現了單例可以節約空間(顯而易見),節省資源(線程、資料庫連接)。 單例模式有這麼多好處,那我們來實現它吧,首先想到的是 ...
  • 報錯 原因 action與result-type順序搞錯了 package里元素必須按照一定的順序排列: result-types interceptors default-interceptor-ref default-action-ref default-class-ref global-res ...
  • 【一朝,王母娘娘設宴,大開寶閣,瑤池中做蟠桃勝會】 有一天,王母娘娘要在瑤池辦party,就需要準備大量的食材。要知道,天上的神仙也分三六九等,九曜星、五方將、二十八宿、四大天王、十二元辰、五方五老、普天星相、河漢群神等等,不同等級的神仙在宴會中吃的東西也不一樣。 為了方便管理,我們把神仙分為低級神 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...