京東手機商品詳情頁技術解密

京東手機商品詳情頁技術解密

做者:陳保安,2011年加入京東,目前主要負責手機京東核心業務(搜索、商品、購物車、結算、收銀臺、個人京東)的後端研發工做。帶領團隊在一線奮戰多年,積累了很是豐富的大促備戰經驗,也見證了核心系統從一分鐘幾千單到幾十萬單的質的蛻變。前端

 

京東手機單品頁在每次大促時承載全部流量的入口,它被自然賦予的一個標籤就是抗壓,對系統的穩定性、性能方面要求極其苛刻,另外單品頁自己業務複雜度較高,單品頁有幾十種垂直流程業務,而且展現上都要求個性化的單品頁,加上依賴有50+的基礎服務,稍有抖動,對總體服務質量都會有比較大的影響,所以以前大促也出現過各類問題,不斷打磨,持續優化升級,當前系統架構可支撐接近百萬的QPS瞬時訪問,而且今年雙11表現很是平穩,藉此機會一塊和你們作一次分享。java

 

1、先聊聊APP接口開發的特色nginx

一、  手機網絡、流量受限web

  • 手機單品頁提供給APP的API受限於運營商的網絡,手機的信號時有時無、時好時壞極其不穩定,爲了減小客戶端和後端建連握手的過程,所以接口下發內容大而全,涵蓋了頁面上的全部內容,沒辦法像瀏覽器BS的結構能夠有大量的ajax請求;ajax

  • API接口依賴了幾十個基礎服務,任何接口的抖動對總體接口性能影響很大,所以必須是併發請求依賴,減小接口抖動疊加的影響;redis

  • 單品頁有大量的圖片信息,商品主圖、插圖、推薦商品、手機配件商品、排行榜等等圖片信息量比較大,單個圖片的大小對手機流量影響較大,全部下發的圖片採用是webp格式,極大減小網絡傳輸流量。算法

二、  手機不一樣分辨率、網絡環境、系統版本的適配後端

  • 不一樣環境下用戶的體驗存在差別,好比在弱網、低版本、分辨率差的手機會保持最基本的購物車流程,會減小一些增值的體驗;瀏覽器

  • 圖片的展現尺寸也會根據網絡環境、分辨率大小進行適配。緩存

三、  APP版本兼容

  • 新業務需求變動儘量兼容老版本,但有些業務很難兼容老版本,所以系統裏面存在不少版本適配的邏輯,增長了系統的複雜度;

  • 客戶端若是出現重大bug而且沒辦法進行hotfix的狀況下,須要服務端針對特定版本進行打補丁,也增長代碼複雜度以及後期的維護成本。

 

所以APP的接口開發邏輯複雜度和後續的維護成本被放大不少。

 

2、單品頁業務系統架構

這是當前單品頁系統的總體架構圖,其餘的核心交易流程,好比購物車、下單等也都基本相似,單品頁系統主要有三個進程:OpenResty、Tracer-Collect、Tomcat,以及包含幾個旁路系統。OpenResty是nginx層的web容器,主要職責是作靜態化和限流防刷,只有通過清洗過的流量纔會流轉到tomcat的java進程真正的業務處理,Tracer-Collect進程是經過旁路的方式異步埋點到統一的監控平臺,進行實時的數據分析。

 

3、核心技術點

一、  OpenResty

這個是在今年618以前架構上作的一個變化,主要有如下幾點考慮:

  • 業務須要,業務流量到必定程度,須要把靜態化數據以及限流策略前置,更多把流量擋在前端,減小業務系統壓力;

  • ngx_openresty模塊有效地把Nginx 服務器轉變爲一個強大的 Web 應用服務器,在其餘0級系統中已經很好驗證了帶來的高可用、高併發的能力。

 

使用規範上

  • Lua屬於腳本語言,開發相對java語言比較開放,好比方法能夠返回多對象,這對長期java開發人員就有不少不適應,在灰度過程當中及時發現並進行修復,所以利用lua來知足特殊需求外,不會進行過多業務邏輯處理;

  • 任何技術上的變更都要極度謹慎,不斷的進行灰度測試,咱們是從一臺機器逐步灰度到一個set,再擴散到一個渠道,最後全量,而且具有實時的異常數據埋點能力,及時發現灰度過程當中問題,一旦發現問題要有開關能實時降級。

 

Lua語言對於不少團隊都使用過程當中都遇到各類問題,今年雙11的總結會上也有團隊分享大促期間lua死鎖問題,咱們這裏遇到的一個場景是zk的配置數據同步到lua時必定機率出現死鎖。

 

緣由:lua運行在nginx主線程中,但zk在nginx主線程外啓動新的線程watch,當zk更新時經過這個新線程通知數據更新,這時咱們在這個新的線程中直接調用lua代碼,會有機率產生死鎖。

解決方案:在這個新線程中不直接調用lua代碼,而是經過http協議直接進入nginx主線程更新配置數據。

 

二、  數據靜態化

單品頁給APP提供的API重點包含兩個,一個是靜態接口,一個是動態接口數據,這裏提到的靜態化重點是針對靜態接口數據,包含商品圖片、基本信息、店鋪商家信息、顏色尺碼、延保…..等,去年雙11期間,因爲一些熱點商品訪問量過大,對jimdb集羣單個分片的鏈接數和操做數都很是高,服務壓力過大,總體集羣服務性能變差,所以針對此進行了三級熱點的優化:

  •   CDN

    衆所周知,CDN原本就是替業務靜態流量扛熱點數據,可是上邊提到後端有不少的適配工做,包括平臺、網絡環境、分辨率尺寸,要知道Android的分辨率五花八門,因此這種邏輯的話CDN很難發揮做用,所以今年針對這個邏輯作了優化,接口下發給APP的數據都是標準數據格式,同時會下發對應的適配規則給APP,由APP根據規則進行動態適配,極大地提高了緩存命中率,另外別忘了還要加上各類開關控制和數據的埋點監控,這也是APP開發的一個重要特徵,APP發出去的版本若是出現各類未知狀況將會是災難,在618以前版本通過各類灰度最終仍是順利上線,在618期間發揮了重要做用,CDN的命中率達到60%以上,大促的0點開始大部分人仍是集中在少數的爆款商品上。這是第一層的保護。

  •   OpenResty(Nginx+Lua)層靜態化

    上邊提到這一層重點仍是數據靜態化和防刷,您可能有疑問,CDN已經替擋住了大部分流量,爲何還須要這一層?CDN只是擋住了App的最新版本熱點流量,還有M渠道是經過內網網關過來的,不通過CDN,以及App的老版本也是不走CDN,所以這一層主要依賴Nginx的共享緩存,分配100M的共享空間,在大促時命中率也能夠到接近20%。

  •   JVM本地緩存

    JVM的堆內存主要是針對商品的基本信息和特殊屬性信息進行本地緩存,支持動態接口商品熱點數據,依賴Guava組件實現的LRU緩存淘汰算法,大體5000個熱點sku數據,數據量在5M左右,這是第三層的數據保護,大促時命中率在27%左右,另外強調一下,這裏的java對象可動態配置成弱引用或者是軟引用,通常建議採用弱引用,這樣避免內存增加過快,致使頻繁的GC。

     

三、  數據異構,減小強依賴

數據異構帶來的好處是能夠減小一些基礎服務的強依賴,以前老闆提的一個目標就是基礎服務掛了,上層業務還能很好的活着,可是京東這個數據體量來當作本是很是巨大的,所以APP單品頁選擇部分數據異構,減小基礎服務接口的強依賴,主要是商品的基礎數據、擴展屬性信息、商品的詳情數據,全量數據同步一次以後經過中間件JMQ進行增量的數據同步變動,存儲使用的是緩存中間件jimdb(redis緩存)。

 

四、  併發請求異步化

APP單品頁前期屬於野蠻發展,不少RPC的依賴極其不合理,好比依賴關係沒有層次概念,超時時間設置超長、內外網接口同時依賴,形成任何的服務質量變差和網絡抖動對總體API影響很是大,所以進行了一次SOA化改造,主要工做是把單品頁系統從大網關分離出來,而後制定服務接入標準並進行改造,第三方面就是上游基礎服務調用並行化,系統總體併發能力及穩定性獲得了極大的提高。

 

服務依賴的標準

  • 依賴接口必須是內網服務,不容許依賴外網服務;

  • 接口超時時間不超過100ms,而且除了一些核心數據,好比商品、價格、庫存,其餘都不進行重試;

  • 核心接口必須可支持跨機房的雙活容災,client端出現問題必須可切換,而且要有降級方案;

  • RPC調用最好是依賴中間件JSF,這樣是點對點的長鏈接服務,減小每次建連的開銷,HTTP依賴須要通過內網的LB,增長一層代理的開銷,會出現一些不可控的問題。

 

隨着流量不斷增長,並行化遇到了瓶頸,每次請求會建立大量的線程,線程的維護和上下文切換成本自己比較消耗CPU資源,所以基於現有HttpClient和JSF基礎組件的異步化支持,進一步進行異步化的改造,單機壓測效果仍是比較明顯,併發能力提高40%。

 

五、  監控

系統流量到必定程度,系統的各維度監控尤其重要,能夠幫助咱們縮短排查、定位問題的時間,甚至能夠幫助預警風險,當前APP業務從用戶到後端整個服務鏈條的監控都已經很是完善,包括各運營商入口流量的監控、內外部網絡質量、負載均衡、以及網關流量的監控之外,我重點介紹下單品頁業務層的監控,下邊是業務監控系統數據異步埋點的架構,主要分爲兩類數據,第一業務指標數據好比單品頁各渠道訪問數據,經過UDP協議實時埋點到Kafka,而後storm實時在線分析造成最終須要的數據落地,另外一類是大流量數據,好比系統異常信息落到磁盤日誌中,而後經過logCollector異步發送到Kafka中,這類數據對磁盤IO、網卡IO的流量佔比大,針對磁盤IO,會按照文件大小100M滾動生成日誌文件,數據搬走以後進行刪除操做,網卡IO在數據傳輸過程當中進行了限速,按照1m/s的速度進行傳輸,可進行動態調整,基本對業務不產生任何影響,大促峯值期間會針對必定比例降級。

 

業務系統除了基本的服務器各項指標CPU、MEM監控,服務的性能、可用率監控之外,介紹幾個比較實用的業務能力監控:

  • 方法tree監控,一次請求在單品頁SOA系統內部所通過的每個類的方法做爲結點造成這麼一顆樹,這棵樹很是直觀看到系統內部的依賴結構關係和任何一個節點的請求量的大小,若是性能、可用率、異常量、訪問量出現異常可第一時間標紅報警,出現任何故障可第一時間聚焦到具體某一個點上,極大提高了定位和處理故障的時間;

  • 異常監控,系統依賴的外部服務以及系統內部拋出的任何一條異常的堆棧信息都被異步埋點記錄下來,進行實時的統計和報警,對系統健康度的把控起到相當重要的做用;




  • 用戶行爲的跟蹤,詳細記錄用戶在什麼時間作了什麼事情以及當時的網絡狀況,方便用戶出現問題時回放出問題時的現場,快速幫助用戶解決問題。



監控細節還有不少,以上幾個監控手段對當前業務系統幫助很是大也是很是實用的一些能力,如今業務系統已經作到很是透明,任何人均可以清晰看到系統的健康度,而且部分服務具有經過故障自動容錯的能力,對系統總體的穩定性提供了很是大的保障。

 

六、  限流手段

京東APP上全部商品價格庫存都是分區域的,所以不少刷子以及爬蟲不斷的來爬京東各區域的價格、庫存和促銷信息等,有一個很明顯的特徵就是大量刷子刷時用戶登陸態的佔比會明顯降低,所以單品頁針對用戶的行爲實時行爲數據進行分析和控制:

  • 流量清洗能力,根據用戶的pin、IP的實時分析和清洗,並能夠根據已登陸和未登陸作不一樣策略;

  • 系統過載保護能力,任什麼時候候不能讓系統掛掉,把明顯的惡意流量清洗以後進行按必定策略進行排隊,保障流量不超過系統極限負載,同時給用戶比較友好的一些交互體驗。

 

七、  壓測

單品頁壓測比較麻煩,一方面壓測的流量大,對線上可能會形成不少不可預知的問題,另外一方面涉及的基礎服務比較多,牽涉的人就多,每次壓測要協調上下游幾十號人支持,協調成本比較高,第三方面壓測的商品數量都在上百萬的商品,每次壓測的SKU會變動,腳本變動比較大,第四每次壓測完成以後須要人工造成壓測報告並分析其中的薄弱環節問題,所以APP端產出了一個本身的壓測平臺,經過流程方面來協助解決以上幾個問題:

  • 啓動壓測任務可自動收集壓測數據併產出須要的壓測腳本;

  • 線上流量的隔離;

  • 通知相關方,確認壓測時間和壓測方案;

  • 按照壓測腳本逐步進行壓測任務執行;

  • 造成壓測報告,並分析壓測過程當中問題點。

 

壓測數據準備方面:

  • 線上流量日誌進行回放,而且按照壓測目標放大到必定倍數來回放;

  • 按照各品類的流量佔比選出一部分商品做爲熱點數據來進行壓測,檢驗各環節對熱點數據的處理是否合理;

  • 針對一些埋點以及統計要能清洗掉這部分數據,目前主要是根據請求的一些固定特徵,好比設備號和特殊標識來進行區分,而且上下游都要能作到一致的數據清洗規則。

 

4、將來方向

單品頁還有很大的一些優化空間,好比爲適應快速的業務迭代進行系統重構、jvm垃圾收回策略和堆內存分配大小的調整、異步化的改造等等優化正在進行,將來單品頁最重要的幾個方向:

  • 動態配置化:不一樣品類商品可根據單品頁元素動態造成一個個性化的單品頁,作到徹底樓層可配置化;

  • 精細化:流控、自動化降級等方面可以根據用戶特徵,好比用戶級別、地域等可執行不一樣策略;

  • 智能化:根據用戶畫像數據展現更多個性化推薦的數據,千人千面,給用戶提供更有價值的信息。

相關文章
相關標籤/搜索