架構,剛開始的解釋是我從知乎上看到的。什麼是架構?有人講,說架構並非一個很懸乎的東西,實際上就是一個架子,放一些業務和算法,跟咱們的生活中的晾衣架很像。更抽象一點,說架構實際上是對咱們重複性業務的抽象和咱們將來業務拓展的前瞻,強調過去的經驗和你對整個行業的預見。html
咱們要想作一個架構的話須要哪些能力?我以爲最重要的是架構師一個最重要的能力就是你要有戰略分解能力。 這個怎麼來看呢,第一,你必需要有抽象的能力,抽象的能力最基本就是去重,去重在整個架構中體如今方方面面,從定義一個函數,到定義一個類,到提供的一個服務,以及模板,背後都是要去重提升可複用率。第二,分類能力。 作軟件須要作對象的解耦,要定義對象的屬性和方法,作 分佈式系統的時候要作服務的拆分和模塊化,要定義服務 的接口和規範。 第三,算法(性能),它的價值體如今提高系統的性能,全部性能的提高,最終都會落到CPU、內 存、IO和網絡這4大塊上。前端
這一頁PPT舉了一些例子來更深刻的理解常見技術背後的架構理念。第一個例子,在分佈式系統咱們會作MySQL分庫分表,咱們要從不一樣的庫和表中讀取數據,這樣的抽象最直觀就是使用模板,由於絕大多數SQL語義是相同的,除了路由到哪一個庫哪一個表,若是不使用Proxy中間件,模板就是性價比最高的方法。第二看一下加速網絡的CDN,它是作速度方面的性能提高,剛纔咱們也提到從CPU、內存、IO、 網絡四個方面來考慮,CDN本質上一個是作網絡智能調度優 化,另外一個是多級緩存優化。第三個看一下服務化,剛纔已經提到了,各個大網站轉型過程當中必定會作服務化,其 實它就是作抽象和作服務的拆分。第四個看一下消息隊列,本質上仍是作分類,只不過不是兩個邊際清晰的類,而是把兩個邊際不清晰的子系統經過隊列解構而且異步化。算法
接下咱們看一下微博總體架構,到必定量級的系統整個架構都會變成三層,客戶端包括WEB、安卓和IOS,這裏就不說了。接着還都會有一個接口層,有三個主要做用:數據庫
第一個做用,要作安全隔離,由於前端節點都是直接和用戶交互,須要防範各類惡意攻擊;後端
第二個還充當着一個流量控制的做用,你們知道在2014年春節的時候,微信紅包每分鐘8億屢次的請求,其實真正到它後臺的請求量, 只有十萬左右的數量級(這裏的數據可能不許),剩餘的流量在接口層就被擋住了;瀏覽器
第三,咱們對PC端和移動端的需求不同的,因此咱們能夠進行拆分。接口層以後是後臺,能夠看到微博後臺有三大塊:一個是平臺服務,第二是搜索,第三是大數據。到了後臺的各類服務其實都是處理的數據。 像平臺的業務部門,作的就是數據存儲和讀取,對搜索來講作的是數據的檢索,對大數據來講是作的數據的挖掘。緩存
微博其實和淘寶是很相似的。通常來講,第一代架構, 基本上能支撐到用戶到百萬級別,到第二代架構基本能支 撐到千萬級別都沒什麼問題,當業務規模到億級別時,需 要第三代的架構。安全
從LAMP的架構到面向服務的架構,有幾個地方是非 常難的,首先不可能在第一代基礎上經過簡單的修修補補 知足用戶量快速增加的,同時線上業務又不能停, 這是咱們常說的在飛機上換引擎的問題。前兩天我有一個朋友問 我,說他在內部推行服務化的時候,把一個模塊服務化作完了,其餘部門就是不接。我建議在作服務化的時候,首先更可能是偏向業務的梳理,同時要找準一個很好的切入點, 既有架構和服務化上的提高,業務方也要有收益,好比提 升性能或者下降維護成本同時升級過程要平滑,建議開始 從原子化服務切入,好比基礎的用戶服務, 基礎的短消息服務,基礎的推送服務。 第二,就是能夠作無狀態服務, 後面會詳細講,還有數據量大了後須要作數據Sharding, 後面會將。第三代架構要解決的問題,就是用戶量和業務 趨於穩步增長(相對爆發期的指數級增加),更多考慮技術框架的穩定性, 提高系統總體的性能,下降成本,還有對整個系統監控的完善和升級。服務器
咱們經過經過數據看一下它的挑戰,PV是在10億級別, QPS在百萬,數據量在千億級別。咱們可用性,就是SLA要求4個9,接口響應最多不能超過150毫秒,線上全部的故障必須得在5分鐘內解決完。若是說5分鐘沒處理呢?那會影 響你年終的績效考覈。2015年微博DAU已通過億。咱們系統有上百個微服務,每週會有兩次的常規上線和不限次數的緊急上線。咱們的挑戰都同樣,就是數據量,bigger and bigger,用戶體驗是faster and faster,業務是more and more。互聯網業務更可能是產品體驗驅動,技術在產品體驗 上最有效的貢獻,就是你的性能愈來愈好。每次下降加載一個頁面的時間,均可以間接的下降這個頁面上用戶的流失率。微信
下面看一下第三代的架構圖以及咱們怎麼用正交分 解法闡述。 咱們能夠看到咱們從兩個維度,橫軸和縱軸可 以看到。一個維度是水平的分層拆分,第二從垂直的維 度會作拆分。水平的維度從接口層、到服務層到數據存儲 層。垂直怎麼拆分,會用業務架構、技術架構、監控平臺、 服務治理等等來處理。我相信到第二代的時候不少架構已 經有了業務架構和技術架構的拆分。咱們看一下,接口層 有feed、用戶關係、通信接口;服務層,SOA裏有基層服務、 原子服務和組合服務,在微博咱們只有原子服務和組合服 務。原子服務不依賴於任何其餘服務,組合服務由幾個原 子服務和本身的業務邏輯構建而成 ,資源層負責海量數據 的存儲(後面例子會詳細講)。
技術框架解決獨立於業務的海量高併發場景下的技 術難題,由衆多的技術組件共同構建而成。在接口層, 微博使用JERSY框架,幫助你作參數的解析,參數的驗證, 序列化和反序列化;資源層,主要是緩存、DB相關的各種 組件,好比Cache組件和對象庫組件。
監控平臺和服務治理,完成系統服務的像素級監控, 對分佈式系統作提早診斷、預警以及治理。包含了SLA 規則的制定、服務監控、服務調用鏈監控、流量監控、錯 誤異常監控、線上灰度發佈上線系統、線上擴容縮容調度
系統等。
下面咱們講一下常見的設計原則。
首先是系統架構三個利器:
一個,咱們RPC服務組件(這裏不講了),第二個,咱們消息中間件 。消息中間件起的做用:能夠把兩個 模塊之間的交互異步化,其次能夠把不均勻請求流量輸出 爲勻速的輸出流量,因此說消息中間件異步化解耦和流量 削峯的利器。第三個是配置管理,它是代碼級灰度發佈 以及保障系統降級的利器。
第二個,無狀態,接口層最重要的就是無狀態。咱們在電商網站購物,在這個過程當中不少狀況下是有狀態的, 好比我瀏覽了哪些商品,爲何你們又常說接口層是無狀態的,其實咱們把狀態從接口層剝離到了數據層。像用戶在電商網站購物,選了幾件商品,到了哪一步,接口無狀態後,狀態要麼放在緩存中,要麼放在數據庫中,其實它並非沒有狀態,只是在這個過程當中咱們要把一些有狀態的東西抽離出來到了數據層。
第三個,數據層比服務層更須要設計,這是一條很是重要的經驗。對於服務層來講,能夠拿PHP寫,明天你能夠拿JAVA來寫,可是若是你的數據結構開始設計不合理, 未來數據結構的改變會花費你數倍的代價,老的數據格式向新的數據格式遷移會讓你痛不欲生,既有工做量上的,又有數據遷移跨越的時間週期,有一些甚至須要半年以上。
第四,物理結構與邏輯結構的映射,上一張圖看到兩個維度切成十二個區間,每一個區間表明一個技術領域, 這個能夠看作咱們的邏輯結構。另外,不論後臺仍是應用 層的開發團隊,通常都會分幾個垂直的業務組加上一個基 礎技術架構組,這就是從物理組織架構到邏輯的技術架構 的完美的映射,精細化團隊分工,有利於提升溝通協做的 效率。
第五,www.sanhao.com的訪問過程,咱們這個架構圖裏沒有涉及到的,舉個例子,好比當你在瀏覽器輸入 www.sanhao網址的時候,這個請求在接口層以前發生了什麼?首先會查看你本機DNS以及DNS服務,查找域名對應的IP地址,而後發送HTTP請求過去。這個請求首先會到前端 的VIP地址(公網服務IP地址),VIP以後還要通過負載均 衡器(Nginx服務器),以後纔到你的應用接口層。在接口 層以前發生了這麼多事,可能有用戶報一個問題的時候, 你經過在接口層查日誌根本發現不了問題,緣由就是問題 可能發生在到達接口層以前了。
第六,咱們說分佈式系統,它最終的瓶頸會落在哪裏 呢?前端時間有一個網友跟我討論的時候,說他們的系統遇到了一個瓶頸, 查遍了CPU,內存,網絡,存儲,都沒有問題。我說你再查一遍,由於最終你不論用上千臺服務器仍是上萬臺服務器,最終系統出瓶頸的必定會落在某一 臺機(多是葉子節點也多是核心的節點),必定落在 CPU、內存、存儲和網絡上,最後查出來問題出在一臺服務 器的網卡帶寬上。
接下來咱們看一下微博的Feed多級緩存。咱們作業務的時候,常常不多作業務分析,技術大會上的分享又都偏向技術架構。其實你們更多的平常工做是須要花費更多時間在業務優化上。這張圖是統計微博的信息流前幾頁的訪 問比例,像前三頁佔了97%,在作緩存設計的時候,咱們最 多隻存最近的M條數據。 這裏強調的就是作系統設計要基 於用戶的場景,越細緻越好。舉了一個例子,你們都會 用電商,電商在雙十一會作全國範圍內的活動,他們作設 計的時候也會考慮場景的,一個就是購物車,我曾經跟相 關開發討論過,購物車是在雙十一以前用戶的訪問量很是 大,就是不停地往裏加商品。在真正到雙十一那天他不會 往購物車加東西了,可是他會頻繁的瀏覽購物車。針對這 個場景,活動以前重點設計優化購物車的寫場景, 活動開 始後優化購物車的讀場景。
你看到的微博是由哪些部分聚合而成的呢?最右邊的是Feed,就是微博全部關注的人,他們的微博所組成的。 微博咱們會按照時間順序把全部關注人的順序作一個排序。 隨着業務的發展,除了跟時間序相關的微博還有非時間序的微博,就是會有廣告的要求,增長一些廣告,還有粉絲 頭條,就是拿錢買的,熱門微博,都會插在其中。分發控制,就是說和一些推薦相關的,我推薦一些相關的好友的微博,我推薦一些你可能沒有讀過的微博,我推薦一些其餘類型的微博。 固然對非時序的微博和分發控制微博,實 際會起多個並行的程序來讀取,最後同步作統一的聚合。
這裏稍微分享一下, 從SNS社交領域來看,國內如今作的比較好的三個信息流:
微博是基於弱關係的媒體信息流;
朋友圈是基於強關係的信息流;
另一個 作的比較好的就是今日頭條,它並非基於關係來構 建信息流,而是基於興趣和相關性的個性化推薦信息流。
信息流的聚合,體如今不少不少的產品之中,除了SNS, 電商裏也有信息流的聚合的影子。好比搜索一個商品後出來的列表頁,它的信息流基本由幾部分組成:第一,打廣 告的;第二個,作一些推薦,熱門的商品,其次,纔是關鍵字相關的搜索結果。信息流開始的時候很簡單,可是到後期會發現,你的這個流如何作控制分發,很是複雜, 微博在最近一兩年一直在作這樣的工做。
剛纔咱們是從業務上分析,那麼技術上怎麼解決高併發,高性能的問題?微博訪問量很大的時候,底層存儲是 用MySQL數據庫,固然也會有其餘的。對於查詢請求量大的時候,你們知道必定有緩存,能夠複用可重用的計算結果。 能夠看到,發一條微博,我有不少粉絲,他們都會來看我
發的內容,因此微博是最適合使用緩存的系統,微博的讀寫比例基本在幾十比一。
微博使用了雙層緩存,上面是L1,每一個L1上都是一組 (包含4-6臺機器),左邊的框至關於一個機房,右邊又是一個機房。在這個系統中L1緩存所起的做用是什麼?首先, L1緩存增長整個系統的QPS,其次以低成本靈活擴容的方式增長系統的帶寬。想象一個極端場景,只有一篇博文, 可是它的訪問量無限增加,其實咱們不須要影響L2緩存, 由於它的內容存儲的量小,但它就是訪問量大。這種場景下,你就須要使用L1來擴容提高QPS和帶寬瓶頸。另一個場景,就是L2級緩存發生做用,好比我有一千萬個用戶, 去訪問的是一百萬個用戶的微博 ,這個時候,他不僅是說 你的吞吐量和訪問帶寬,就是你要緩存的博文的內容也很 多了,這個時候你要考慮緩存的容量,第二級緩存更多的是從容量上來規劃,保證請求以較小的比例穿透到後端的數據庫中,根據你的用戶模型你能夠估出來,到底有百分之多少的請求不能穿透到DB, 評估這個容量以後,才能更好的評估DB須要多少庫,須要承擔多大的訪問的壓力。
另外,咱們看雙機房的話,左邊一個,右邊一個。兩個機房是互爲主備,或者互爲熱備 。若是兩個用戶在不 同地域,他們訪問兩個不一樣機房的時候,假設用戶從IDC1過來,由於就近原理,他會訪問L1,沒有的話纔會跑到 Master,當在IDC1沒找到的時候纔會跑到IDC2來找。同時 有用戶從IDC2訪問,也會有請求從L1和Master返回或者到 IDC1去查找。 IDC1和IDC2,兩個機房都有全量的用戶 數據,同時在線提供服務,可是緩存查詢又遵循最近 訪問原理。
還有哪些多級緩存的例子呢?CDN是典型的多級緩存。 CDN在國內各個地區作了不少節點,好比在杭州市部署一個節點時,在機房裏確定不止一臺機器,那麼對於一個地區 來講,只有幾臺服務器到源站回源,其餘節點都到這幾臺服務器回源便可,這麼看CDN至少也有兩級。
Local Cache+分佈式緩存,這也是常見的一種策略。 有一種場景,分佈式緩存並不適用,好比單點資源的爆發 性峯值流量,這個時候使用Local Cache + 分佈式緩存, Local Cache在應用服務器上用很小的內存資源擋住少許的極端峯值流量,長尾的流量仍然訪問分佈式緩存,這樣的Hybrid緩存架構經過複用衆多的應用服務器節點,下降 了系統的總體成本。
咱們來看一下Feed的存儲架構,微博的博文主要存在 MySQL中。首先來看內容表,這個比較簡單,每條內容一個索引,天天建一張表,其次看索引表,一共建了兩級索引。 首先想象一下用戶場景,大部分用戶刷微博的時候,看的 是他關注全部人的微博,而後按時間來排序。仔細分析發 如今這個場景下, 跟一個用戶的本身的相關性很小了。 因此在一級索引的時候會先根據關注的用戶,取他們的前條微博ID,而後聚合排序。咱們在作哈希(分庫分表)的 時候,同時考慮了按照UID哈希和按照時間維度。很業務和時間相關性很高的,今天的熱點新聞,明天就沒熱度了, 數據的冷熱很是明顯,這種場景就須要按照時間維度作分表,首先冷熱數據作了分離(能夠對冷熱數據採用不一樣的 存儲方案來下降成本),其次, 很容止控制我數據庫表的爆炸。像微博若是隻按照用戶維度區分,那麼這個用戶全部數據都在一張表裏,這張表就是無限增加的,時間長了 查詢會愈來愈慢。二級索引,是咱們裏面一個比較特殊的場景,就是我要快速找到這我的所要發佈的某一時段的微博時,經過二級索引快速定位。
分佈式追蹤服務系統,當系統到千萬級之後的時候, 愈來愈龐雜,所解決的問題更偏向穩定性,性能和監控。 剛纔說用戶只要有一個請求過來,你能夠依賴你的服務 RPC一、RPC2,你會發現RPC2又依賴RPC三、RPC4。分佈式服 務的時候一個痛點,就是說一個請求從用戶過來以後,在 後臺不一樣的機器之間不停的調用並返回。
當你發現一個問題的時候,這些日誌落在不一樣的機器 上,你也不知道問題到底出在哪兒,各個服務之間互相隔 離,互相之間沒有創建關聯。因此致使排查問題基本沒有 任何手段,就是出了問題無法兒解決。
咱們要解決的問題,咱們剛纔說日誌互相隔離,咱們 就要把它創建聯繫。創建聯繫咱們就有一個請求ID,而後結合RPC框架, 服務治理功能。假設請求從客戶端過來, 其中包含一個ID 101,到服務A時仍然帶有ID 101,而後調 用RPC1的時候也會標識這是101 ,因此須要一個惟一的請求ID標識遞歸迭代的傳遞到每個相關節點。第二個, 你作的時候,你不能說每一個地方都加,對業務系統來講需 要一個框架來完成這個工做,這個框架要對業務系統是最低侵入原則,用JAVA的話就能夠用AOP,要作到零侵入的原則,就是對全部相關的中間件打點,從接口層組件 (HTTP Client、HTTP Server)至到服務層組件(RPC Client、RPC Server),還有數據訪問中間件的,這樣業 務系統只須要少許的配置信息就能夠實現全鏈路監控 。爲何要用日誌?服務化之後,每一個服務能夠用不一樣的開發 語言,考慮多種開發語言的兼容性,內部定義標準化的日誌是惟一且有效的辦法。
最後,如何構建基於GPS導航的路況監控?咱們剛纔講分佈式服務追蹤。分佈式服務追蹤能解決的問題,若是單一用戶發現問題後,能夠經過請求ID快速找到發生問 題的節點在什麼,可是並無解決如何發現問題。咱們看 現實中比較容易理解的道路監控,每輛車有GPS定位,我想 看北京哪兒擁堵的時候,怎麼作? 第一個,你確定要知 道每一個車在什麼位置,它走到哪兒了。其實能夠說每一個車 上只要有一個標識,加上每一次流動的信息,就能夠看到 每一個車流的位置和方向。其次如何作監控和報警,咱們怎 麼能瞭解道路的流量情況和負載,並及時報警。咱們要定 義這條街道多寬多高,單位時間能夠通行多少輛車,這就 是道路的容量。有了道路容量,再有道路的實時流量,我 們就能夠基於實習路況作預警?
對應於分佈式系統的話如何構建? 第一,你要定 義每一個服務節點它的SLA是多少?SLA能夠從系統的CPU佔 用率、內存佔用率、磁盤佔用率、QPS請求數等來定義,相 當於定義系統的容量。 第二個,統計線上動態的流量, 你要知道服務的平均QPS、最低QPS和最大QPS,有了流量和 容量,就能夠對系統作全面的監控和報警。
剛纔講的是理論,實際狀況確定比這個複雜。微博在 春節的時候作許多活動,必須保障系統穩定,理論上你只要定義容量和流量就能夠。但實際遠遠不行,爲何?有 技術的因素,有人爲的因素,由於不一樣的開發定義的流量 和容量指標有主觀性,很難全局量化標準,因此真正流量 來了之後,你預先評估的系統瓶頸每每不正確。實際中我 們在春節前主要採起了三個措施:
第一,最簡單的就是有 降級的預案,流量超過系統容量後,先把哪些功能砍掉, 須要有明確的優先級 。
第二個,線上全鏈路壓測,就是把 如今的流量放大到咱們日常流量的五倍甚至十倍(好比下 線一半的服務器,縮容而不是擴容),看看系統瓶頸最早 發生在哪裏。咱們以前有一些例子,推測系統數據庫會先 出現瓶頸,可是實測發現是前端的程序先遇到瓶頸。
第三, 搭建在線Docker集羣, 全部業務共享備用的Docker 集羣資源,這樣能夠極大的避免每一個業務都預留資源,但 是實際上流量沒有增加形成的浪費。
接下來講的是如何不停的學習和提高,這裏以Java語 言爲例,首先,必定要理解JAVA;第二步,JAVA完了之後, 必定要理解JVM;其次,還要理解操做系統;再次仍是要 瞭解一下Design Pattern,這將告訴你怎麼把過去的經 驗抽象沉澱供未來借鑑;還要學習TCP/IP、分佈式系統、 數據結構和算法。
原文地址:http://sanwen8.cn/p/1f7bzmN.html