1、需求緣起css
大夥打開微信錢包,會發現58到家入駐了微信錢包的一級入口(以下圖),這個入口流量極大,微信要求被接入的H5必須能抗住n萬的qps(58到家的系統是偏交易的系統,雖然一天100w訂單其實也沒多少請求),這是以前的業務系統沒有遇到過的,要抗住這個n萬的qps的優化思路是怎麼樣的呢?html
這裏作一個思路分享,但願能對業界同仁有啓示做用。mysql
2、業務分析nginx
在微信錢包裏,點擊進入58到家,會發現實際上是一個類別落地頁,根據不一樣城市開通的服務類別,展現不一樣類別的入口(以下圖)。web
很容易想到,整個架構與流程是這樣滴:sql
架構分層:數據庫
(1)微信錢包端,嵌有到家H5頁面apache
(2)web-server層,生成H5頁面緩存
(3)service層,提供「城市開通了哪些核心服務」的接口tomcat
(4)數據庫層,存儲了「城市開通了哪些核心服務」的數據
核心流程:
步驟一:微信端經過native的GPS定位或者微信的js-sdk獲取用戶當前所在城市,並往web-server發送http請求
步驟二:web-server收到http請求,調用service層,獲取當前城市開通了哪些核心服務的數據,以瓶裝返回html
步驟三:service收到RPC請求,調用mysql,獲取真正的數據
步驟四:mysql返回service,service返回web-server,web-server拼裝html,返回微信錢包
潛在的問題:
每秒鐘n萬的qps數據庫扛不住
3、優化分析
看到這裏,不少讀者就笑了,這個場景加個緩存不就搞定了麼,好吧,是能夠,但本文的重點並非加一個緩存,還有其餘的梗等着你。
場景分析:這個「城市開通了哪些核心服務」是一個幾乎只讀的場景,由於城市要開通新的服務是很低頻的,因此一大早就想到了cache的優化(cache要注意高可用),優化後的架構分層以下:
cache存儲城市開通的核心服務列表,key value創建的是一個city-id到list<service-id>的映射關係。
幾乎100%的請求會命中緩存。
潛在的問題:服務與緩存之間的帶寬會不會成爲瓶頸呢?
由於幾乎是只讀的請求,很容易想到將分佈式緩存優化爲服務內存緩存,優化後的架構分層以下:
每個服務內部都有一個map,存儲city-id到list<service-id>的映射關係,而不用經過cache來讀取數據。
還能不能進一步優化,例如進一步下降網絡交互呢?
是能夠的,服務層能夠作數據的緩存map<cityid, list<sid>>,web-server層能夠進一步作頁面緩存優化,架構圖以下:
每個站點層,直接作頁面緩存,上游傳入一個city-id,就直接將提早拼裝好的頁面返回,獲得很高的性能。
有甚者,經過nginx/varnish/squid針對性的作一些「頁面靜態化的優化」,直接每一個city有一個對應的html,能極大的提升吞吐量:
4、頁面靜態化的適用場景
在作站點架構的過程當中,「動靜分離」是一項很常見的優化手段:
(1)對於不變的首頁、js、jpg、css,能夠用專門的file-server來針對性優化(cdn/nginx/varnish/squid)提供高速訪問
(2)對於動態的頁面,有專門的tomcat/apache/iis/lighttpd集羣來提供動態站點生成
通常來講動態站點時延會大大高於靜態站點,應爲每次生成動態站點須要訪問服務(屢次網絡傳輸)、訪問數據庫(可能有很慢的磁盤io),而且還有大量的計算邏輯,而靜態文件則能夠直接返回。
「頁面靜態化」是一種將本來須要動態生成的站點提早生成靜態站點的優化技術,什麼樣的業務場景能夠進行「頁面靜態化」優化呢?
解答:總數據量不大,生成靜態頁面數量很少的業務,很是適合於「頁面靜態化」優化
<廣告>
若是你讀到了這裏,說明對微信平臺仍是有點興趣的,58到家微信平臺團隊目前只有一個女生負責(技術圈混,毫不騙人),奇缺人,歡迎有志之士加入。
一些說明:base北京,核心團隊,技術導向,Java方向,和58沈劍一個團隊
加入方式:(1)直接在文章下面留言(2)在公衆號回覆「招聘」獲取加盟密鑰
</廣告完畢>
例如:到家開通的城市只有幾百個,那隻需提早生成幾百個城市的「靜態化頁面」便可
又例如:一些二手車業務,整個公司可能只有幾萬量二手車庫存,也能夠提早生成這幾萬量二手車的靜態頁面
再例如:像58同城這樣的信息模式業務,又幾十億的帖子量,就不太適合於靜態化
5、總結
「頁面靜態化」是一種將本來須要動態生成的站點提早生成靜態站點的優化技術,總數據量不大,生成靜態頁面數量很少的業務,很是適合於「頁面靜態化」優化
以上內容均來自微信公衆號「架構師之路」胡劍老師的文章,歡迎關注。