此文是開濤在【三體高可用架構(gòu)群】之分享內(nèi)容,,“三體”是為了紀(jì)念三體一書對(duì)技術(shù)人的偉大影響而冠名,。
京東618的硝煙雖已散去,,可開發(fā)和備戰(zhàn)618期間總結(jié)過的一些設(shè)計(jì)原則和遇到的一些坑還歷歷在目,。伴隨著網(wǎng)站業(yè)務(wù)發(fā)展,需求日趨復(fù)雜多樣并隨時(shí)變化,;傳統(tǒng)靜態(tài)化方案會(huì)遇到業(yè)務(wù)瓶頸,,不能滿足瞬變的需求。因此,,需要一種能高性能實(shí)時(shí)渲染的動(dòng)態(tài)化模板技術(shù)來解決這些問題,。 今夜(編者:指8/27),我們將進(jìn)行服裝品類的垂直詳情頁的AB測(cè)試和切新庫存服務(wù)的1/n流量,。就此機(jī)會(huì),,和大家分享一下最近一年做的京東商品詳情頁的架構(gòu)升級(jí)的心路歷程。 商品詳情頁是什么商品詳情頁是展示商品詳細(xì)信息的一個(gè)頁面,,承載在網(wǎng)站的大部分流量和訂單的入口,。京東商城目前有通用版、全球購,、閃購,、易車、惠買車,、服裝,、拼購,、今日抄底等許多套詳情頁模板,通過一些特殊屬性,、商家類型和打標(biāo)來區(qū)分,,每套模板數(shù)據(jù)是一樣的,核心邏輯基本一樣,,但是一些前端邏輯是有差別的,。 目前商品詳情頁個(gè)性化需求非常多,數(shù)據(jù)來源也是非常多的(目前統(tǒng)計(jì)后端有差不多數(shù)十個(gè)依賴服務(wù)),,而且許多基礎(chǔ)服務(wù)做不了的不想做的或者說需要緊急處理的都放我們這處理,,比如一些屏蔽商品需求等。因此我們需要一種架構(gòu)能快速響應(yīng)和優(yōu)雅的解決這些需求問題,,來了問題能在5~10分鐘內(nèi)搞定,。我們這邊經(jīng)還常收到一些緊急需求,比如工商的一些投訴等需要及時(shí)響應(yīng),。之前架構(gòu)是靜態(tài)化的,,肯定無法滿足這種日趨復(fù)雜和未知的需求。靜態(tài)化時(shí)做屏蔽都是通過js,,所以我們重新設(shè)計(jì)了商品詳情頁的架構(gòu),。 它主要包括以下三部分: 商品詳情頁系統(tǒng) 商品詳情頁動(dòng)態(tài)服務(wù)系統(tǒng)和商品詳情頁統(tǒng)一服務(wù)系統(tǒng) 鍵值結(jié)構(gòu)的異構(gòu)數(shù)據(jù)集群 商品主數(shù)據(jù)因?yàn)槭谴鎯?chǔ)在DB中,,對(duì)于一些聚合數(shù)據(jù)需要聯(lián)合查詢非常多,,會(huì)導(dǎo)致查詢性能差的問題,因此對(duì)于鍵值類型的查詢,,我們這套異構(gòu)數(shù)據(jù)非常有用,。我們這次架構(gòu)的調(diào)整的主要目的是滿足日趨復(fù)雜的業(yè)務(wù)需求,能及時(shí)開發(fā)業(yè)務(wù)方的需求,。我們的系統(tǒng)主要處理鍵值數(shù)據(jù)的邏輯,,關(guān)系查詢我們有另一套異構(gòu)系統(tǒng)。 下圖是我們的模板頁,,核心數(shù)據(jù)都是一樣的,,只是展示方式和一些前端邏輯不太一樣。 我們?cè)斍轫摰那岸苏故局饕譃檫@么幾個(gè)維度:
另外還有一些實(shí)時(shí)性要求比較高的如實(shí)時(shí)價(jià)格、實(shí)時(shí)促銷,、廣告詞,、配送至、預(yù)售等是通過異步加載,。 我們目前把數(shù)據(jù)按維度化存儲(chǔ),,比如一些維度直接redis存,性能好,。 京東商城還有一些特殊維度數(shù)據(jù):比如套裝,、手機(jī)合約機(jī)等,這些數(shù)據(jù)是主商品數(shù)據(jù)外掛的,,通過異步加載來實(shí)現(xiàn)的邏輯。還有一些與第三方合作的,,如易車,,很多數(shù)據(jù)都是無法異構(gòu)的,都是直接異步加載的,。目前有易車,、途牛等一些公司有這種合作。 我們618當(dāng)天PV數(shù)億,,服務(wù)器端TOP99響應(yīng)時(shí)間低于38ms(此處是第1000次中第99次排名的時(shí)間,,PV具體數(shù)據(jù)不便公開,但TOP99基本在40ms之內(nèi)),。 上圖是我們的一個(gè)監(jiān)控圖,。我們?cè)斍轫摿髁刻攸c(diǎn)是離散數(shù)據(jù),熱點(diǎn)少,,各種爬蟲,、比價(jià)軟件抓取,;所以如果直接查庫,,防刷沒做好,很容易被刷掛,。 商品詳情頁發(fā)展史
架構(gòu)1.0
這種方式經(jīng)常受到依賴的服務(wù)不穩(wěn)定而導(dǎo)致的性能抖動(dòng)?;景l(fā)展初期都是這個(gè)樣子的,,扛不住加層緩存。因此我們?cè)O(shè)計(jì)了架構(gòu)2.0,。 架構(gòu)2.0
主要思路:
主要缺點(diǎn):
之前需求沒那么多,,因此頁面變更不是很頻繁,基本沒什么問題,。但是隨著商品數(shù)量的增加這種架構(gòu)的存儲(chǔ)容量到達(dá)了瓶頸,,而且按照商品維度生成整個(gè)頁面會(huì)存在如分類維度變更就要全部刷一遍這個(gè)分類下所有信息的問題,因此我們又改造了一版按照尾號(hào)路由到多臺(tái)機(jī)器,。這種生成整個(gè)頁面的方案會(huì)存在比如只有分類信息變了,,也需要把這個(gè)分類下的商品重新刷一遍。 架構(gòu)2.1
這種方式通過尾號(hào)路由的方式分散到多臺(tái)機(jī)器擴(kuò)容,,然后生成HTML片段,按需靜態(tài)化,;當(dāng)時(shí)我們做閃購的時(shí)候,,需要加頁頭,都是通過js搞定的,。但對(duì)于大的頁面結(jié)構(gòu)變更,,需要全量生成。尤其像面包屑不一樣的話會(huì)很麻煩,,需要生成多個(gè)版本,。 主要缺點(diǎn):
當(dāng)時(shí)我記得印象最深的就是碎片文件太多,我們的inode不夠了,,經(jīng)常要半夜去公司刪文件,。因?yàn)榇嬖趧h除問題,每臺(tái)服務(wù)器并不是全量,,所以我們需要一個(gè)動(dòng)態(tài)生成的服務(wù),,當(dāng)靜態(tài)化不存在的時(shí)候還原到動(dòng)態(tài)服務(wù);但這樣雙十一時(shí)壓力非常大,,我們依賴的系統(tǒng)隨時(shí)都給我們降級(jí),。 架構(gòu)3.0我們的痛點(diǎn):
其實(shí)最痛快的是業(yè)務(wù)來說我們要搞垂直,我們要模塊化,,我們要個(gè)性化,;這些統(tǒng)統(tǒng)不好搞,因此我們就考慮做一版全動(dòng)態(tài)的,。其實(shí)思路和靜態(tài)化差不多,, 數(shù)據(jù)靜態(tài)化聚合、頁面模板化,。 我們要考慮和要解決的問題:
主要思路:
思路差不多: MQ得到變更通知,Worker刷元數(shù)據(jù)到JIMDB,,前端展示系統(tǒng)取數(shù)據(jù)渲染模板,。另外我們當(dāng)時(shí)架構(gòu)的目標(biāo)是詳情頁上有的數(shù)據(jù),我們都可以提供服務(wù)出去,,主要提供單個(gè)商品的查詢服務(wù),,所以我們把這個(gè)系統(tǒng)叫做動(dòng)態(tài)服務(wù)系統(tǒng)。 目前每天為列表頁提供增量數(shù)據(jù)服務(wù),。微信上京東入口看到的詳情頁 也是我們這個(gè)服務(wù)提供的數(shù)據(jù),。APP的數(shù)據(jù)暫時(shí)沒走我們的系統(tǒng),不過我們目前系統(tǒng)實(shí)現(xiàn)的是平常流量的50倍左右,,性能和流量基本不是問題,。我們?cè)斍轫摷軜?gòu)設(shè)計(jì)的一些原則:
因?yàn)槲覀冞@邊主要是讀服務(wù),因此我們架構(gòu)可能偏讀為主的設(shè)計(jì),;目前我設(shè)計(jì)的幾個(gè)系統(tǒng)都遵循這些原則去設(shè)計(jì): 數(shù)據(jù)閉環(huán): 數(shù)據(jù)異構(gòu),,是數(shù)據(jù)閉環(huán)的第一步,,將各個(gè)依賴系統(tǒng)的數(shù)據(jù)拿過來,按照自己的要求存儲(chǔ)起來,;我們把很多數(shù)據(jù)劃分為三個(gè)主要維度進(jìn)行異構(gòu):商品信息,、商品介紹和其他信息(分類,、商家、店鋪等),。 數(shù)據(jù)原子化處理,,數(shù)據(jù)異構(gòu)的數(shù)據(jù)是原子化數(shù)據(jù),這樣未來我們可以對(duì)這些數(shù)據(jù)再加工再處理而響應(yīng)變化的需求,。我們有了一份原子化異構(gòu)數(shù)據(jù)雖然方便處理新需求,,但恰恰因?yàn)榈谝环輸?shù)據(jù)是原子化的,那么它會(huì)很分散,,前端讀取時(shí)mget的話 性能不是很好,,因此我們又做了數(shù)據(jù)聚合。 數(shù)據(jù)聚合,,是將多個(gè)原子數(shù)據(jù)聚合為一個(gè)大JSON數(shù)據(jù),,這樣前端展示只需要一次get,當(dāng)然要考慮系統(tǒng)架構(gòu),,比如我們使用的Redis改造,,Redis又是單線程系統(tǒng),我們需要部署更多的Redis來支持更高的并發(fā),,另外存儲(chǔ)的值要盡可能的小,。 數(shù)據(jù)存儲(chǔ),,我們使用JIMDB,,Redis加持久化存儲(chǔ)引擎,,可以存儲(chǔ)超過內(nèi)存N倍的數(shù)據(jù)量,,我們目前一些系統(tǒng)是Redis LMDB引擎的存儲(chǔ),,目前是配合SSD進(jìn)行存儲(chǔ),;另外我們使用Hash Tag機(jī)制把相關(guān)的數(shù)據(jù)哈希到同一個(gè)分片,,這樣mget時(shí)不需要跨分片合并,。分片邏輯使用的是Twemproxy,,和應(yīng)用端混合部署在一起,;減少了一層中間層,也節(jié)約一部分機(jī)器,。 我們目前的異構(gòu)數(shù)據(jù)是鍵值結(jié)構(gòu)的,,用于按照商品維度查詢,還有一套異構(gòu)時(shí)關(guān)系結(jié)構(gòu)的用于關(guān)系查詢使用,。 數(shù)據(jù)維度化
這些數(shù)據(jù)很多部門在維護(hù),,只能異步加載,;目前這些服務(wù)比較穩(wěn)定,性能也不錯(cuò),,我們?cè)诎堰@些服務(wù)在服務(wù)端聚合,,然后一次性吐出去?,F(xiàn)在已經(jīng)這么做了幾個(gè),,比如下面這個(gè)就是在服務(wù)端聚合吐出去的情況。 這是我們url的一些規(guī)則,,methods指定聚合的服務(wù),。我們還對(duì)系統(tǒng)按照其作用做了拆分,。 拆分系統(tǒng) 將系統(tǒng)拆分為多個(gè)子系統(tǒng)雖然增加了復(fù)雜性,但是可以得到更多的好處,。比如,,數(shù)據(jù)異構(gòu)系統(tǒng)存儲(chǔ)的數(shù)據(jù)是原子化數(shù)據(jù),這樣可以按照一些維度對(duì)外提供服務(wù),;而數(shù)據(jù)同步系統(tǒng)存儲(chǔ)的是聚合數(shù)據(jù),,可以為前端展示提供高性能的讀取。而前端展示系統(tǒng)分離為商品詳情頁和商品介紹,,可以減少相互影響,;目前商品介紹系統(tǒng)還提供其他的一些服務(wù),比如全站異步頁腳服務(wù),。我們后端還是一個(gè)任務(wù)系統(tǒng),。 Worker無狀態(tài)化 任務(wù)化
異步化 并發(fā)化 我們系統(tǒng)大量使用異步化,,通過異步化機(jī)制提升并發(fā)能力。首先我們使用了消息異步化進(jìn)行系統(tǒng)解耦合,,通過消息通知我變更,,然后我再調(diào)用相應(yīng)接口獲取相關(guān)數(shù)據(jù);之前老系統(tǒng)使用同步推送機(jī)制,,這種方式系統(tǒng)是緊耦合的,,出問題需要聯(lián)系各個(gè)負(fù)責(zé)人重新推送還要考慮失敗重試機(jī)制。數(shù)據(jù)更新異步化,,更新緩存時(shí),,同步調(diào)用服務(wù),然后異步更新緩存,。 可并行任務(wù)并發(fā)化,,商品數(shù)據(jù)系統(tǒng)來源有多處,但是可以并發(fā)調(diào)用聚合,,這樣本來串行需要1s的經(jīng)過這種方式我們提升到300ms之內(nèi),。異步請(qǐng)求合并,異步請(qǐng)求做合并,,然后一次請(qǐng)求調(diào)用就能拿到所有數(shù)據(jù),。前端服務(wù)異步化/聚合,實(shí)時(shí)價(jià)格,、實(shí)時(shí)庫存異步化,,使用如線程或協(xié)程機(jī)制將多個(gè)可并發(fā)的服務(wù)聚合。異步化還一個(gè)好處就是可以對(duì)異步請(qǐng)求做合并,,原來N次調(diào)用可以合并為一次,,還可以做請(qǐng)求的排重。 多級(jí)緩存化 瀏覽器緩存,,當(dāng)頁面之間來回跳轉(zhuǎn)時(shí)走local cache,,或者打開頁面時(shí)拿著Last-Modified去CDN驗(yàn)證是否過期,減少來回傳輸?shù)臄?shù)據(jù)量,; CDN緩存,,用戶去離自己最近的CDN節(jié)點(diǎn)拿數(shù)據(jù),而不是都回源到北京機(jī)房獲取數(shù)據(jù),,提升訪問性能,; 服務(wù)端應(yīng)用本地緩存,我們使用Nginx Lua架構(gòu),使用HttpLuaModule模塊的shared dict做本地緩存( reload不丟失)或內(nèi)存級(jí)Proxy Cache,,從而減少帶寬,。 我們的應(yīng)用就是通過Nginx Lua寫的,,每次重啟共享緩存不丟,,這點(diǎn)我們受益頗多,重啟沒有抖動(dòng),,另外我們還使用使用一致性哈希(如商品編號(hào)/分類)做負(fù)載均衡內(nèi)部對(duì)URL重寫提升命中率,;我們對(duì)mget做了優(yōu)化,如去商品其他維度數(shù)據(jù),,分類,、面包屑、商家等差不多8個(gè)維度數(shù)據(jù),,如果每次mget獲取性能差而且數(shù)據(jù)量很大,,30KB以上;而這些數(shù)據(jù)緩存半小時(shí)也是沒有問題的,,因此我們?cè)O(shè)計(jì)為先讀local cache,,然后把不命中的再回源到remote cache獲取,這個(gè)優(yōu)化減少了一半以上的remote cache流量,;這個(gè)優(yōu)化減少了這個(gè)數(shù)據(jù)獲取的一半流量,; 服務(wù)端分布式緩存,我們使用內(nèi)存 SSD JIMDB持久化存儲(chǔ),。 動(dòng)態(tài)化 模板渲染實(shí)時(shí)化,支持隨時(shí)變更模板需求,;我們目前模板變更非常頻繁,,需求非常多,一個(gè)頁面8個(gè)開發(fā)。 重啟應(yīng)用秒級(jí)化,, 使用Nginx Lua架構(gòu),,重啟速度快,重啟不丟共享字典緩存數(shù)據(jù),;其實(shí)我們有一些是Tomcat應(yīng)用,,我們也在考慮使用如Tomcat Local Redis 或 Tomcat Nginx Local Shared Dict 做一些本地緩存,防止重啟堆緩存失效的問題,。 需求上線速度化,,因?yàn)槲覀兪褂昧薔ginx Lua架構(gòu),可以快速上線和重啟應(yīng)用,,不會(huì)產(chǎn)生抖動(dòng),;另外Lua本身是一種腳本語言,我們也在嘗試把代碼如何版本化存儲(chǔ),,直接內(nèi)部驅(qū)動(dòng)Lua代碼更新上線而不需要重啟Nginx,。 彈性化 降級(jí)開關(guān) 可降級(jí)的多級(jí)讀服務(wù),,前端數(shù)據(jù)集群—->數(shù)據(jù)異構(gòu)集群—->動(dòng)態(tài)服務(wù)(調(diào)用依賴系統(tǒng)),;這樣可以保證服務(wù)質(zhì)量,假設(shè)前端數(shù)據(jù)集群壞了一個(gè)磁盤,,還可以回源到數(shù)據(jù)異構(gòu)集群獲取數(shù)據(jù),;基本不怕磁盤壞或一些機(jī)器故障、或者機(jī)架故障,。 開關(guān)前置化,,如Nginx代替Tomcat,在Nginx上做開關(guān),,請(qǐng)求就到不了后端,,減少后端壓力,;我們目前很多開關(guān)都是在Nginx上。 可降級(jí)的業(yè)務(wù)線程池隔離,,從Servlet3開始支持異步模型,,Tomcat7/Jetty8開始支持,相同的概念是Jetty6的Continuations,。我們可以把處理過程分解為一個(gè)個(gè)的事件,。 通過這種將請(qǐng)求劃分為事件方式我們可以進(jìn)行更多的控制。如,,我們可以為不同的業(yè)務(wù)再建立不同的線程池進(jìn)行控制:即我們只依賴tomcat線程池進(jìn)行請(qǐng)求的解析,,對(duì)于請(qǐng)求的處理我們交給我們自己的線程池去完成,;這樣tomcat線程池就不是我們的瓶頸,,造成現(xiàn)在無法優(yōu)化的狀況。通過使用這種異步化事件模型,,我們可以提高整體的吞吐量,,不讓慢速的A業(yè)務(wù)處理影響到其他業(yè)務(wù)處理。慢的還是慢,,但是不影響其他的業(yè)務(wù),。我們通過這種機(jī)制還可以把tomcat線程池的監(jiān)控拿出來,出問題時(shí)可以直接清空業(yè)務(wù)線程池,,另外還可以自定義任務(wù)隊(duì)列來支持一些特殊的業(yè)務(wù),。 去年使用的是JDK7 Tomcat7 最近一個(gè)月我們升級(jí)到了JDK8 Tomcat8 G1。 多機(jī)房多活 多種壓測(cè)方案 線上壓測(cè),,可以使用Tcpcopy直接把線上流量導(dǎo)入到壓測(cè)服務(wù)器,這種方式可以壓測(cè)出機(jī)器的性能,,而且可以把流量放大,,也可以使用Nginx Lua協(xié)程機(jī)制把流量分發(fā)到多臺(tái)壓測(cè)服務(wù)器,或者直接在頁面埋點(diǎn),,讓用戶壓測(cè),,此種壓測(cè)方式可以不給用戶返回內(nèi)容。服務(wù)剛開始的時(shí)候大量使用tcpcopy做驗(yàn)證,,對(duì)于一些 新服務(wù),,如果無法使用tcpcopy我們就在頁面埋url讓用戶來壓。 另外壓測(cè)時(shí),,要考慮讀,、寫、讀或?qū)懲瑫r(shí)壓,。只壓某一種場(chǎng)景可能都會(huì)不真實(shí),。 遇到的一些問題和解決方案SSD性能差使用SSD做KV存儲(chǔ)時(shí)發(fā)現(xiàn)磁盤IO非常低。配置成RAID10的性能只有36MB/s,;配置成RAID0的性能有130MB/s,,系統(tǒng)中沒有發(fā)現(xiàn)CPU,MEM,,中斷等瓶頸,。一臺(tái)服務(wù)器從RAID1改成RAID0后,性能只有~60MB/s,。這說明我們用的SSD盤性能不穩(wěn)定,。 據(jù)以上現(xiàn)象,初步懷疑以下幾點(diǎn):SSD盤,,線上系統(tǒng)用的三星840Pro是消費(fèi)級(jí)硬盤,;RAID卡設(shè)置,Write back和Write through策略(后來測(cè)試驗(yàn)證,,有影響,,但不是關(guān)鍵);RAID卡類型,,線上系統(tǒng)用的是LSI 2008,,比較陳舊。 下面是使用dd做的簡(jiǎn)單測(cè)試,。 鍵值存儲(chǔ)選型壓測(cè)在系統(tǒng)設(shè)計(jì)初期最頭痛的就是存儲(chǔ)選型,,我們對(duì)于存儲(chǔ)選型時(shí)嘗試過LevelDB、RocksDB,、BeansDB,、LMDB、Riak等,,最終根據(jù)我們的需求選擇了LMDB,。 機(jī)器:2臺(tái) LevelDB壓測(cè)時(shí),,隨機(jī)讀 隨機(jī)寫會(huì)產(chǎn)生抖動(dòng)(我們的數(shù)據(jù)出自自己的監(jiān)控平臺(tái),,分鐘級(jí)采樣)。 數(shù)據(jù)量大時(shí)Jimdb同步不動(dòng)Jimdb數(shù)據(jù)同步時(shí)要dump數(shù)據(jù),,SSD盤容量用了50%以上,,dump到同一塊磁盤容量不足。
切換主從因?yàn)槭腔赗edis的,,目前是先做數(shù)據(jù)RDB dump然后同步,。后續(xù)計(jì)劃改造為直接內(nèi)存復(fù)制,之前存儲(chǔ)架構(gòu)是一主二從(主機(jī)房一主一從,,備機(jī)房一從)切換到備機(jī)房時(shí),,只有一個(gè)主服務(wù),讀寫壓力大時(shí)有抖動(dòng),,因此我們改造為之前架構(gòu)圖中的一主三從,。 分片配置之前的架構(gòu)是存儲(chǔ)集群的分片邏輯分散到多個(gè)子系統(tǒng)的配置文件中,切換時(shí)需要操作很多系統(tǒng),。 解決方案:
我們都是在應(yīng)用本地部署的Twemproxy,,然后通過中間系統(tǒng)對(duì)外提供數(shù)據(jù),。 模板元數(shù)據(jù)存儲(chǔ)HTML我們前端應(yīng)用使用的是Nginx Lua,起初不確定Lua做邏輯和渲染模板性能如何,,就盡量減少for,、if/else之類的邏輯;通過java worker組裝html片段存儲(chǔ)到j(luò)imdb,,html片段會(huì)存儲(chǔ)諸多問題,,假設(shè)未來變了也是需要全量刷出的,因此存儲(chǔ)的內(nèi)容最好就是元數(shù)據(jù),。 因此通過線上不斷壓測(cè),,最終jimdb只存儲(chǔ)元數(shù)據(jù),lua做邏輯和渲染,;邏輯代碼在3000行以上,;模板代碼1500行以上,其中大量for,、if/else,,目前渲染性可以接受,。 線上真實(shí)流量,整體性能從TOP99 53ms降到32ms,。 庫存接口訪問量600W/分鐘商品詳情頁庫存接口2014年被惡意刷,,每分鐘超過600w訪問量,,tomcat機(jī)器只能定時(shí)重啟;因?yàn)槭窃斍轫撜故镜臄?shù)據(jù),,緩存幾秒鐘是可以接受的,,因此開啟nginx proxy cache來解決該問題,開啟后降到正常水平,;我們目前正在使用Nginx Lua架構(gòu)改造服務(wù),,數(shù)據(jù)過濾、URL重寫等在Nginx層完成,,通過URL重寫 一致性哈希負(fù)載均衡,,不怕隨機(jī)URL,一些服務(wù)提升了10% 的緩存命中率,。 目前我們大量使用內(nèi)存級(jí)nginx proxy cache和nginx共享字典做數(shù)據(jù)緩存,。 還有我們會(huì)對(duì)這些前端的url進(jìn)行重寫,所以不管怎么加隨機(jī)數(shù),,都不會(huì)影響我們服務(wù)端的命中率,,我們服務(wù)端做了參數(shù)的重新拼裝和驗(yàn)證。 微信接口調(diào)用量暴增14年的一段時(shí)間微信接口調(diào)用量暴增,,通過訪問日志發(fā)現(xiàn)某IP頻繁抓取,;而且按照商品編號(hào)遍歷,,但是會(huì)有一些不存在的編號(hào)。 解決方案:
開啟Nginx Proxy Cache性能不升反降開啟Nginx Proxy Cache后,性能下降,,而且過一段內(nèi)存使用率到達(dá)98%,。 解決方案:
配送至讀服務(wù)因依賴太多,,響應(yīng)時(shí)間偏慢配送至服務(wù)每天有數(shù)十億調(diào)用量,響應(yīng)時(shí)間偏慢,。
假設(shè)一個(gè)讀服務(wù)是需要如下數(shù)據(jù):
那么如果串行獲取那么需要:60ms;而如果數(shù)據(jù)C依賴數(shù)據(jù)A和數(shù)據(jù)B,、數(shù)據(jù)D誰也不依賴,、數(shù)據(jù)E依賴數(shù)據(jù)C;那么我們可以這樣子來獲取數(shù)據(jù): 那么如果并發(fā)化獲取那么需要:30ms,;能提升一倍的性能,。 假設(shè)數(shù)據(jù)E還依賴數(shù)據(jù)F(5ms),而數(shù)據(jù)F是在數(shù)據(jù)E服務(wù)中獲取的,,此時(shí)就可以考慮在此服務(wù)中在取數(shù)據(jù)A/B/D時(shí)預(yù)取數(shù)據(jù)F,,那么整體性能就變?yōu)榱耍?5ms。 我們目前大量使用并發(fā)獲取和預(yù)取數(shù)據(jù),,通過這種優(yōu)化我們服務(wù)提升了差不多10ms性能,。 而且能顯著減少一些依賴服務(wù)的重復(fù)調(diào)用,給他們減流,。 網(wǎng)絡(luò)抖動(dòng)時(shí),返回502錯(cuò)誤Twemproxy配置的timeout時(shí)間太長,,之前設(shè)置為5s,,而且沒有分別針對(duì)連接、讀,、寫設(shè)置超時(shí),。后來我們減少超時(shí)時(shí)間,內(nèi)網(wǎng)設(shè)置在150ms以內(nèi),,當(dāng)超時(shí)時(shí)訪問動(dòng)態(tài)服務(wù),。對(duì)于讀服務(wù)的話,應(yīng)該設(shè)置合理的超時(shí)時(shí)間,,比如超時(shí)了直接降級(jí),。 機(jī)器流量太大2014年雙11期間,服務(wù)器網(wǎng)卡流量到了400Mbps,,CPU30%左右,。原因是我們所有壓縮都在接入層完成,因此接入層不再傳入相關(guān)請(qǐng)求頭到應(yīng)用,,隨著流量的增大,,接入層壓力過大,因此我們把壓縮下方到各個(gè)業(yè)務(wù)應(yīng)用,,添加了相應(yīng)的請(qǐng)求頭,,Nginx GZIP壓縮級(jí)別在2~4吞吐量最高;應(yīng)用服務(wù)器流量降了差不多5倍,;目前正常情況CPU在4%以下,。 因?yàn)橹皦嚎s都是接入層做的,后來因?yàn)榻尤氲姆?wù)太多,,因此我們決定在各應(yīng)用去做,。 一些總結(jié)
Q&AQ1:對(duì)于依賴服務(wù)的波動(dòng),,導(dǎo)致我們系統(tǒng)的不穩(wěn)定,我們是怎么設(shè)計(jì)的,?
Q2:靜態(tài)化屏蔽通過js是怎么做的,?
Q3:內(nèi)網(wǎng)的服務(wù)通過什么方式提供? Q4:對(duì)于mq 的處理如果出現(xiàn)異常是怎么發(fā)現(xiàn)和處理的,?
Q5:對(duì)于模板這塊,有做預(yù)編譯處理,?或者直接使用Lua寫模板嗎,?
Q6: jimdb能否介紹下,,特性是什么,為什么選用?
Q7:咨詢下對(duì)于價(jià)格這類敏感數(shù)據(jù),前端有緩存么,?還是都靠價(jià)格服務(wù)扛,?
價(jià)格數(shù)據(jù)也是通過MQ得到變更存儲(chǔ)到本地redis的,nginx lua直接讀本機(jī)redis,,性能沒的說,。 Q8:庫存和價(jià)格一樣的模式處理嗎? Q9:github里有一個(gè)開源的基于lmdb的redis 你們用的這個(gè)嗎? Q10:看測(cè)試條件說測(cè)試的是大小5~30KB左右的數(shù)據(jù),有沒有測(cè)試過更大文件lmdb的表現(xiàn),? Q11:關(guān)于redis緩存,是每個(gè)子系統(tǒng)擁有自己的一套緩存,;還是使用統(tǒng)一的緩存服務(wù)?是否有進(jìn)行過對(duì)比測(cè)試?(看到又說使用單機(jī)緩存防止服務(wù)掛掉,,影響整體服務(wù))
Q12: “我們目前一些線上服務(wù)器使用的是LMDB,其他一些正在嘗試公司自主研發(fā)的CycleDB引擎”,。 開始自主研發(fā),,這個(gè)是由于lmdb有坑還是處于別的考慮?
關(guān)于21CTO社區(qū) 21CTO.com是中國互聯(lián)網(wǎng)第一技術(shù)人脈與社交平臺(tái),。我們?yōu)閲鴥?nèi)最優(yōu)秀的開發(fā)者提供社交,、學(xué)習(xí)等產(chǎn)品,幫助企業(yè)快速對(duì)接開發(fā)者,,包括人才招聘,,項(xiàng)目研發(fā),顧問咨詢服務(wù),。 看微信文章不過癮,,請(qǐng)移步到網(wǎng)站,誠摯歡迎您加入社區(qū)作者團(tuán)隊(duì),。 網(wǎng)站地址:www.21cto.com 投稿郵箱:[email protected] QQ群: 79309783 (歡迎掃描下列二維碼關(guān)注本微信號(hào)) |
|