架構師小組交流會是由國內知名公司技術專家參與的技術交流會,每期選擇一個時下最熱門的技術話題進行實踐經驗分享。
第一期:來自滬江、滴滴、蘑菇街、扇貝架構師的 Docker 實踐分享
第二期:來自滴滴、微博、惟品會、魅族、點評關於高可用架構的實踐分享
第三期:京東、宅急送的微服務實踐分享(上)nginx
第三期小組交流會邀請到了國內電商領頭羊京東、宅急送技術負責人。在上篇京東、宅急送的微服務實踐分享(上)中他們介紹了各自產品的微服務實踐。本次他們就 API 網關的設計、服務的 Docker 化、服務測試、持續集成等詳細話題展開了討論。redis
Q:API 網關是怎麼設計的?算法
京東章耿:咱們有個 HTTP 的網關,但不是一個對外網服務的一個網關。對外的話業務本身都有一些網關,好比無線有本身的網關,站點有本身的網關。而另一個公共的開放的是一個叫京東開放平臺的網關。spring
而後咱們的網關幹嗎用的?主要作的就是一個跨語言支持用的,協議轉發和限流。這個網關存在的意義,主要是爲了讓有的調用端不用傑夫協議,或者不依賴服務端的狀況下。來調服務端的服務。最主要就是剛纔說那個 HTTP 轉成內部協議的一個轉發的功能,其次咱們在上面作了一個接口級隔離,不要一個接口就把網關搞掛。另外一個就是限流,每分鐘調多少次。還有受權,曾經的網關轉發的作法。一般是比方說類似於一個 VIP。而後前面掛個域名。數據庫
而後那個虛 IP 後面掛的服務列表通常都是要手動維護上。而咱們的網購本身主動就掛到這個網關上面,就是一個服務發現,還有就是咱們的結果,統計方面,咱們會統一包裝一下,咱們的網關主要是作這個功能,現在一天應該是幾十億的調用量。九十臺,幾乎相同這些。安全
服務發現是到數據庫裏面去讀服務列表,從註冊中心讀出來之後會推給咱們的網關。網關跟調用者是類似的。restful
它事實上也是一個調用者,僅僅只是它是一個代理的調用者。它的服務列表,也是從咱們的註冊中心訂閱的,不直接連數據庫。可以以爲本身是調用者。網關第一次去註冊中心去讀,後面的話咱們可以推變化的部分。markdown
比方說你原來 1000 臺,你要是加了一臺,按曾經拉的思路你會拉 1001 臺。而後你本身比較一下。多了哪一臺。但咱們現在不是。咱們現在是反向給他推加一臺。網絡
這樣的話。大量的下降那個。還有網絡 IO 的推送。京東章耿:咱們想用 nginx+luaw 作一個 HTTP 轉咱們內部 JSF 協議的,但不是 worker 就是一個進程。會產生很是多長連接。因此咱們後來就放棄了。咱們現在是基於 nitty 作了一個轉發,就是對外是 HTTP,對內就 JSF 協議。也作了一些受權,限流,還有服務之間的線程隔離,服務發現,另外一個是結果的包裝,包裝成標準的 HTTP 的響應。因爲像對外網的那些事實上都是有本身的系統,不管你是無線,仍是 PC 他都有本身的系統,那個不需要咱們作。對第三方的話。它也有當中京東一個開發平臺,還有更嚴格的那個驗證,咱們這個主要仍是作協議轉換的 API 網關。架構
Q:大家怎麼驗證請求的合法性的。大家採用什麼方法?就是就那種效率與安全性的這樣的平衡大家怎麼作的?
京東章耿:咱們是有個受權。就是有個應用 ID,京東是每個啓動的都有個應用 ID,帶着那個應用 ID 過來。咱們也可以支持頭上帶 token。京東開放的那種是對外比較嚴格,咱們這個不需要那麼嚴格,反正就看你對象,就看你的網關給誰用了。
Q:大家現在有兩種類型。一種是內部之間調用的,另一部分是外部調用內部的調用大家系統。
京東章耿:那個是開放服務,有些供應商內部的系統,想要調京東的系統,那種就是京東開放服務,是需要 Oauth 認證。
**京東章耿:**HTTP+keepalive 也挺快的,因爲它無非就是頭上大一點,HTTP 的頭大了一點。但假設後臺是調 redis 那就比較明顯的感受,那假設後臺是一個有個幾百毫秒的,那你感受不到那麼明顯。假設後臺,你這就是讀不取一下。讀一下 redis,你感受比較明顯。咱們這邊是用 netty 作的 HTTP 跟二進制都是在同一個port支持的。
Q:你怎麼劃分,哪些用二進制的。那些用 restful 協議的呢?
京東章耿:那個咱們沒有強制要求,業務它本身想用什麼用什麼。
京東章耿:對咱們來講,它一啓動端線口它就支持這兩種協議。啓動同一個port。兩種協議都支撐的。
Q:大家是怎麼區分一種port種協議的呢?
京東章耿:每個數據包含頭上前兩位不是模數位嗎?它們都有本身的模數位。
而後咱們本身協議有本身的模數位,你 HTTP 就是那幾個打頭的 H。而後咱們的 decode 是本身主動裝載的,它不是說你可以一開始裝載一個什麼那是適配器 decode。
當你請求來的時候。你再本身主動裝載量,因爲咱們是超連接,不管你是 HTTP,咱們通常都默認開啓 keepalive 也是個超連接。
事實上,你可以知道這個長連接相應的是什麼協議。
Q:它通常保持穩定的一個超連接,確定是一種協議持續下去,不可能說動態的變質。
京東章耿:是,看效率要求,事實上 HTTP keepalive 也還可以,性能也還可以,假設不是那種調量特別特別大的話,它效率也仍是可以的。而後 debug 的時候可能可讀性會好一點。
二進制最大問題仍是比較麻煩,特別是,咱們現在用 message pack。而後會生成一堆的代理類。模板類,反正問題也比較麻煩。
宅急送石廷鑫:咱們都用 Spring cloud 的那一套。而後自個改了一部分東西。像 Consul 好像也和 Zookeeper 同樣的問題,因此說後邊都改造數據庫了。
我現在用的是開源的 eureka。僅僅是後邊從屬變了。
眼下來講還沒發現問題,因爲我沒有跨機房的問題。假設是跨機房的話。基本上都是數據庫同步,兩個數據之間同步的問題。
京東章耿:通常咱們是有一個功能服務降級,事實上最主要仍是業務部門本身的代碼實現,那咱們事實上有提供一個 mok 功能,就是那在咱們配置這邊直接配上一個,假設這個接口不可用返回的什麼東西有沒有開關,這也是可以。但是這個用起來比較少,通常他們本身在業務代碼上也是容錯的,就是沒有說從平臺這樣的角度去搞,通常都是本身考慮。而後假設是有一個目視跟蹤系統的話,就通常的也可以跟蹤整個調用鏈,就會看出來這個。
比方說這個接口它依賴其它的接口,而後京東事實上是沒有投資這麼細。因爲眼下咱們分公司跟蹤尚未上。咱們現在主要是依賴咱們內部的一個應用管理系統,咱們叫 JOne,有點像本身主動部署。咱們每個進程啓動的時候都會帶上這個應用 ID,在咱們管理端是能看到這個接口是屬於哪一個應用的,咱們僅僅能看到應用級別的。這個應用調了哪些接口?哪些接口依賴?調的那些接口還被誰調用了?到這個級別。
宅急送石廷鑫:咱們用 Springcloud。熔斷機制的降級處理的話,它有一個統計的接口,基本上按那個規則來作。調用關係的話,一個是咱們作了一個 trace ID,就是 google zipkin,它自己有自帶的工具。
另外一部分就是服務的排層。咱們現在就是用 camel 來作的,把這個業務整個來排層次作,大致是這樣。
眼下來講,大的狀況就是監控時會有一些出經常會出現一些抖動。
就比方說 trace ID 那部分。不能用它自帶的 stream 的模式。
咱們現在仍是用 elk 來作,而後把 trace ID 打出來。而後作了一套簡單的監控,類似於模仿它整個 trace 的路徑。固然不要用 google 自帶的監控,咱們發現機器多了自帶的監控不太可靠。咱們都是作到日誌裏面。而後用 elk 收集起來。提及來自個作一個監控的調用量,這個就是略微有點延遲。
京東章耿:咱們這邊近期正在作,而後咱們的思路是這樣的。有個包放在應用裏面,它會輸出日誌,而後咱們有一個日誌收集,原來就有日誌收集的咱們僅僅是擴展了一下。在每臺機子上把它收到一個 kafka 裏面。而後後面是用一個 storm 去把它讀出來,寫到 H base 裏作分析,而後咱們是有個採樣率的一個概念,比方說一千次。才寫一次,或者是一萬次才寫一次,作個採樣率。
而後終於咱們現在是分兩部分,剛纔說寫 H base 是一個離線數據。事實上咱們另外一些簡單樣例。就是直接作一些統計,實時的,大概延遲在一分鐘左右。
Q:關於服務的 Docker 化有什麼進展?
京東章耿:咱們主要仍是應用級別的 Docker。現在僅僅是說,可能這樣的公佈模式會改一下。現在是基於一個 Docker VM。比方說你起來之後。事實上整個鏡像文件都在那裏。而後你彈的時候事實上仍是比較慢的。比方我要擴的話,得先建立一個 Docker 的 VM。再把那些東西複製進去,才幹有個裝機的過程。
就是比較慢一點。可能得分鐘級別才幹把它給提起來。但是將來咱們但願把它改用鏡像的那種形式,就你上線完畢之後。生成一個鏡像。每次上線。你僅僅需要布一臺機器。後面全是複製的一個過程。將來會改爲這樣。預計今年開發,明年推。現在至關於要布 20 個節點,那至關因而給你 20 個 Docker VM,你上線公佈 20 次,將來是但願給你一個,而後你公佈一次之後。系統本身主動給你複製 19 個。
而且反正後面服務發現什麼這些都是原生的,都是無所謂的。
京東章耿:京東的 Docker 主要解決資源調度的問題。就至關於現在部物理機。你可能本身要需要部署機器 。但 Docker 可以把資源分配均勻一點。用算法給算出來。在分配時不會分到同一個機架上,不會分到同一個主機上,還有不會分到很是繁忙的機器上。這些都會幫你考慮一下。
京東章耿:京東這邊是本身有一套部署系統,儘管他沒有像你說就鏡像這樣公佈,儘管沒這麼快。但對於咱們開發者上線來講。事實上是同樣的,他僅僅需要配一下,而後一點,他 24 臺本身主動就上去了,就是有一套工具,也很是快。僅僅只是,他需要提早建立好,比方說你剛纔說 20 個,你要提早建立 20 個 VM。
就比鏡像的話確定是要慢在這一步。你鏡像的話。你直接拉下來一塊兒,而後可以調度到哪臺機子上到個 Docker API 一調,他直接就提起來了。那也是咱們將來的改變方向。
七牛陳愛珍:咱們的數據處理系統系統上執行的都是 CPU 密集型的計算。獲取一個原文件,進行數據處理算法的執行,比方對一個視頻進行轉碼,而在轉碼的過程當中需要大量的 CPU 資源來進行處理。處理完後就可以得到預設的文件樣式。不一樣的數據處理對資源的需求是不同的,比方獲取一個文件的 hash 值,這個處理邏輯很是easy,也沒有大量的運算,配置的資源就相對小一些,而視頻轉碼則很是的複雜,配置的資源就會相對多一些。現在在咱們的平臺上執行了數千種數據處理應用,每種處理的的請求量不同,比方有些圖片處理每秒可以達到數十萬的請求量。而有一些則多是每秒幾萬的請求量,幾千種數據處理應用的高峯期也不同。有些可能在早上。有些可能在晚上,而且每種處理都會存在突發流量的狀況。比方一些電商型的客戶,在作大促銷時。就會致使圖片處理的請求量突增,而一些音視頻的客戶在會在一些活動時會忽然增加對音視頻的處理。
這個系統的核心問題是怎樣把硬件資源對每一種應用不一樣高峯期的請求量和突發流量作合理的資源分配。不合理的資源分配就可能會形成資源的浪費,或致使負載太重的機器會宕機,不能及時響應用戶的需求。原有的系統架構的資源是靜態規劃的,也就是把指定的資源給指定的應用使用,而這樣的資源的分配每每是依照每個應用的業務高峯進行規劃的,爲了應對突發的流量並會預設必定的冗餘,那麼這樣就會需要準備很是多的資源。後來咱們使用容器,因爲容器可以封裝環境,動態遷移,底層使用 Mesos 作資源的調度,這就可以對整個環境按需動態分配。很是好的攻克了資源利用率的問題。
Q:關於服務測試、持續集成,你們分享一下實踐經驗吧。
京東章耿:持續集成咱們這邊事實上在編譯環節就作了。上線咱們這邊是有一個灰度上線功能。
咱們有一個預公佈環節,它可以直接把它標記爲預發,而後有個測試平臺可以對它進行一個服務的測試。那假設是正式環境的話。那就他就得本身想辦法,因爲咱們現在這個環節是不能隨便測試的。因爲我沒法推斷你這個是讀仍是寫,我不能讓你隨便測。
Q:因爲大家是把一個業務系統拆成了很是多這樣的服務化的服務去跑。那確定是要涉及到這樣的單元測試、集成測試和業務流的這樣的測試,那這樣的測試的話大家都是怎麼作的呢?
京東章耿:這邊都是提早測的。就是你測都沒測。那你根本就提不到上線這一步。
你上線的時候必須有一個測試審批經過,事實上他事實上就是已經在線下就測過了。
七牛陳愛珍:咱們是基於 Jenkins 作的持續集成。把代碼上傳到 Github 後,會作本身主動的代碼靜態檢查和單元測試,再作本身主動的集成測試。這樣的優勢是開發僅僅需要開發代碼,不需要構建環境,都是本身主動完畢的,而且反饋的速度也會很是高速。
宅急送石廷鑫:測試環境是由開發者去部署,線上正式環節,是從這個測試環境把報測試經過去的,直接拷貝過去。我以爲 Docker 是解決整個配置的問題,因爲生產環境測試環境和開發環境不同。
配置環境這個東西很是難很是麻煩作的。儘量就是 UAT 的環境和測試環境,就是用戶測試的環境和線上的環境儘可能是同樣。現在不是有配置管理嗎?這三個環境能來回切換。比方說 spring boot 這樣的,實際上就是一個 Jar 包命令。Jar 包命令惟一不一樣的就是它的配置問題。你僅僅要一上線。那邊一監控就可以看到。因爲你啓動時候他有註冊。註冊基本上他要調哪些東西就能看到他註冊的配置。
京東章耿:京東測試環境,預發。線上都是從源代碼庫裏編譯爲準。主幹編譯爲準,因此說代碼應該是同樣的。線上配置咱們是管理在配置中心。但是眼下咱們測試環境就沒有這個東西。
預發,線上有配置中心,這個配置中心也集成到咱們那個公佈平臺 JOne 上。