帶你認識一下“京東到家-網關係統”

京東到家三週年活動已然結束,在這2年裏,我們的網關係統經歷過了618,1020,雙11,雙12,415等多個非常有意義的考試,回顧起來依舊讓人覺得很刺激,每次考前我們和市場部都做了大量的效果預估、壓測&擴容,但是活動當日依舊是驚心動魄,瞬時數以100倍的流量涌入(有成千上萬薅羊毛黨的入侵,有技術黑客的攪局,有友商的友情壓力測試,有通過全站push帶來的用戶同一時間瞬時訪問),網關作爲後臺服務器的第一道牆,如何站好這第一班崗呢?接下來帶你一起認識一下“京東到家-網關係統”

網關係統是什麼

京東到家提供給App端的HTTP接口有上千個,涉及到的系統也有上百個,大家都知道公網HTTP接口面臨着諸多的挑戰,我舉幾個例子:

  • 異常處理-已經剛剛發版的app中寫錯了一個後端的url,致使某項功能不能使用;
  • 版本控制-歷史上發佈的版本不再維護了需要強制下線或者強制升級; 流量控制-異常流量的識別與限流;
  • 登陸驗證-網關做統一的登陸與校驗;
  • 數據安全-接口數據交互時需要加密驗籤,保障用戶數據安全;
  • 流量控制-必要的時候進行限流對後端系統進行保護

上述功能如果每個系統都各自實現一套來說,時間人力成本都是不值當的,實現方式的差異性也會造成聯調時出現的種種奇葩問題,基於這樣的前提,京東到家孵化出了這個基礎平臺-網關係統應運而生,所有系統均需要做的基礎工作交由網關來處理,業務系統只關心自身業務邏輯就可以了。

網關一定需要麼

這是一個比較有爭議的話題,不過業界有一個共識,當系統達到一定量級時有一個基礎網關統一處理異常處理、數據安全、流量控制、版本控制會比較好,後端的業務系統只用關心自身業務邏輯就好了。網關其實就是業務系統的一個前置層,把一些業務系統需要處理的通用邏輯前置到網關,避免業務系統的重複開發,提高開發效率。

網關係統的架構

本文討論的環節爲圖中的物理網關,整體架構如下
物理網關架構圖

數據處理流程如下
數據處理流程

京東到家的物理網關獨立部署,其最核心功能是請求的轉發,每一個請求進入到網關後都會經歷上面的處理流程。首先進行必要的參數校驗,校驗通過後,進行封版和參數防篡改驗證,上述校驗通過後,網關會通過傳過來的參數去配置中心獲取到後端的跳轉地址,如果能取到對應的轉發url,下一步網關做轉發前的最後校驗,包括登陸驗證,封流量校驗,防刷校驗,全部通過後,網關對進入的請求按照請求方式做POST或GET轉發。

訪問示例
http://gw.o2o.jd.com/client?functionId=productsearch/searchKey&body={%22key%22:%22asdf%22,%22pageSize%22:20}&appName=paidaojia&appVersion=1.3.0&channel=AppStore&deviceId=79516EBF-4DE6-4478-9521-F06B405A6F6E&deviceModel=iPhone&deviceToken=79516EBF-4DE6-4478-9521-F06B405A6F6E&networkType=wifi&partner=AppStore&platCode=IOS&platVersion=8.4&screen=1242*2208&signKey=7e995f08f403fa84c3e0b6c7c6e13631

必傳參數解釋說明
body={},app請求後端系統的業務參數,網關不解析,不更改。
deviceId=,設備id,標示設備的唯一標識。
functionId=爲方法ID,網關會通過配置系統配置這個functionID指向到後端set化的集羣域名
signKey=7e995f08f403fa84c3e0b6c7c6e13631,是防篡改簽名,網關會對其做校驗,每個app對應的Md5key值是不一樣的。
appName=pdj,有了appName參數,這樣一套網關就可以支持多個app了
appVersion=4.2,必傳,代表應用的版本號。
deviceToken=**,必傳,作爲發送消息的唯一標識。
platCode=ios,標示是ios還是安卓 。
channel=AppStore
deviceModel=iphone
networkType=wifi,代表網絡類型。
partner=AppStore,推廣渠道。
screen=尺寸。

值得一提的設計細節
1) 錯誤碼定義
爲什麼特別強調一下這個問題呢,現在都是SOA架構,系統與系統間的關係愈來愈複雜,用戶看到的一個頁面可能由後端10個或者更多的系統支撐着,任何一個系統出現問題,都會影響到用戶頁面的展示,那麼如何保障出現問題時,快速定位是哪個系統哪個接口的問題呢,錯誤碼格式:系統代號+接口代號+錯誤情況代號

錯誤碼示例
APP提示語(用戶看到的) 真實的錯誤原因
網絡繁忙,請稍後再試[000000] httpstatus非302,404,500,502
網絡繁忙,請稍後再試[000011] 請求後端服務超5s read time out
網絡繁忙,請稍後再試[000044] 請求後端返回httpstatus:404
網絡繁忙,請稍後再試[000050] 請求後端返回httpstatus:500
網絡繁忙,請稍後再試[000052] 請求後端返回httpstatus:502
網絡繁忙,請稍後再試[000090] 加密驗證未通過
網絡繁忙,請稍後再試[000091] 請求方式不對
網絡繁忙,請稍後再試[000092] 未配置functionId
網絡繁忙,請稍後再試[000093] functionId當前版本沒有配置url

2) 網關與配置中心的交互
網關functionId與後端系統url的對應關係全部存儲在配置中心(也是一個應用,獨立部署),爲了最大限度提高配置中心的可用性和訪問速度問題,配置中心的配置信息在網關機器啓動時就會全量加載到網關jvm內存中,之後如果配置中心的配置新增或者修改,我們採用zookeeper的通知機制來更新jvm內存中的配置信息。

3) 日誌查詢
日誌對於一個系統來說,重要性不容忽視,線上的突發問題定位、日常的問題排查、責任定位都需要用到,但作爲日PV過億的系統,很多系統都會因性能考慮不提供日誌,其實我不是太贊成這一思路的,首先性能的問題應該是想辦法解決性能,不能因爲採集了日誌,結果影響了性能,基於這樣的大前提,我們的日誌採用了Log4j2(官方號稱比Log4j性能提升了10倍),配合動態開關來控制打印日誌的級別,可以在一些特殊情況下控制日誌的輸出。
另外一個知識點就是現在我們的應用服務器通常有幾個或者幾十個,日誌的集中化管理與關鍵字檢索查詢也顯得非常麻煩,目前京東到家使用了業界比較成熟的ELK技術(ELK由ElasticSearch、Logstash和Kiabana三個開源工具組成)

4) 高可用保證
京東到家網關係統的日常現狀(其中X>1,Y>1)
PV:X億/日
峯值:Y十萬/分鐘
作爲一個億級PV的系統,每秒鐘都會有上千次的訪問,保證系統的高可用呢?比如說可能會遇到網絡、硬件、軟件的故障,或者程序自身的升級,如何最小化的降低對用戶的感知呢
網絡故障,京東到家所有公網域名都是分運營商(移動、聯通、電信、香港)進行設置DNS的,任何一家運營商的網絡出現問題都可以快速切換到其它運營商
硬件故障,首先我們服務器通過前置HAProxy+Nginx雙層架構,網關服務器水平擴容便無後顧之憂,另外採用同機房多服務器+擴機房混合部署,防止服務器或者機房故障
程序升級,程序升級有多方面的原因,比如新功能上線或者修復bug,我們如何避免由於程序升級過程中造成的訪問波動呢,這個也是SoEasy的,前面提到HAProxy,這裏會維護一個VIP與後端服務器的映射關係,每次上線前可以通過VIP控制檯進行摘掉一部分機器待無流量後再進行上線升級操作,待這部分正常啓動後重新再掛到VIP上,並對外提供服務,依次完成剩餘的一部分機器即可,當然了,由於需要修改系統參數、程序參數造成的程序重啓也可以腫採取該策略。

截流

限流

網關係統,我們正在做?
持續優化,優化每個請求在網關的耗時,在網關轉發請求到後端時,需要做比較多的校驗,且需要和外部的會話中心和防刷系統等交互,後續優化儘量降低對外部系統的強依賴,能異步化的異步化。也可適當優化tomcat參數(IO->NIO->AIO),提高響應速度。
風控對接,單純從技術手段有些攻擊手段是無法徹底解決的,頂多是可以增加攻擊的成本的複雜度,比如暴力破解、社會工程學等,我們目前逐步與風控系統數據對接,風控系統有一套非常強大的用戶識別體系,集合了用戶,設備,瀏覽,訂單,優惠,支付等環節的數據,對風險用戶進行星級打分,最終實現網關與風控的數據共享利用。
優化日誌,方便問題查找,統一日誌的輸出格式,增加類似traceId的字段,通過這一字段可以看到每一個請求在網關的完整的調用日誌鏈,方便問題定位與查找。
完善監控,增加依賴的核心繫統的監控,及網關機器性能的監控,防止網絡或者機器的原因導致網關可用率降低

截流限流的思路
2. 多個賬號,一次性發送多個請求
很多公司的賬號註冊功能,在發展早期幾乎是沒有限制的,很容易就可以註冊很多個賬號。因此,也導致了出現了一些特殊的工作室,通過編寫自動註冊腳本,積累了一大批“殭屍賬號”,數量龐大,幾萬甚至幾十萬的賬號不等,專門做各種刷的行爲(這就是微博中的“殭屍粉“的來源)。舉個例子,例如微博中有轉發抽獎的活動,如果我們使用幾萬個“殭屍號”去混進去轉發,這樣就可以大大提升我們中獎的概率。
這種賬號,使用在秒殺和搶購裏,也是同一個道理。例如,iPhone官網的搶購,火車票黃牛黨。

應對方案:
這種場景,可以通過檢測指定機器IP請求頻率就可以解決,如果發現某個IP請求頻率很高,可以給它彈出一個驗證碼或者直接禁止它的請求:
1. 彈出驗證碼,最核心的追求,就是分辨出真實用戶。因此,大家可能經常發現,網站彈出的驗證碼,有些是“鬼神亂舞”的樣子,有時讓我們根本無法看清。他們這樣做的原因,其實也是爲了讓驗證碼的圖片不被輕易識別,因爲強大的“自動腳本”可以通過圖片識別裏面的字符,然後讓腳本自動填寫驗證碼。實際上,有一些非常創新的驗證碼,效果會比較好,例如給你一個簡單問題讓你回答,或者讓你完成某些簡單操作(例如百度貼吧的驗證碼)。
2. 直接禁止IP,實際上是有些粗暴的,因爲有些真實用戶的網絡場景恰好是同一出口IP的,可能會有“誤傷“。但是這一個做法簡單高效,根據實際場景使用可以獲得很好的效果。
3. 多個賬號,不同IP發送不同請求
所謂道高一尺,魔高一丈。有進攻,就會有防守,永不休止。這些“工作室”,發現你對單機IP請求頻率有控制之後,他們也針對這種場景,想出了他們的“新進攻方案”,就是不斷改變IP。

有同學會好奇,這些隨機IP服務怎麼來的。有一些是某些機構自己佔據一批獨立IP,然後做成一個隨機代理IP的服務,有償提供給這些“工作室”使用。還有一些更爲黑暗一點的,就是通過木馬黑掉普通用戶的電腦,這個木馬也不破壞用戶電腦的正常運作,只做一件事情,就是轉發IP包,普通用戶的電腦被變成了IP代理出口。通過這種做法,黑客就拿到了大量的獨立IP,然後搭建爲隨機IP服務,就是爲了掙錢。
應對方案:
說實話,這種場景下的請求,和真實用戶的行爲,已經基本相同了,想做分辨很困難。再做進一步的限制很容易“誤傷“真實用戶,這個時候,通常只能通過設置業務門檻高來限制這種請求了,或者通過賬號行爲的”數據挖掘“來提前清理掉它們。
殭屍賬號也還是有一些共同特徵的,例如賬號很可能屬於同一個號碼段甚至是連號的,活躍度不高,等級低,資料不全等等。根據這些特點,適當設置參與門檻,例如限制參與秒殺的賬號等級。通過這些業務手段,也是可以過濾掉一些殭屍號。

心靈寄語:唯有認真對待每一次考試,方能臨陣不亂

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章