來自京東、惟品會對微服務編排、API網關、持續集成的實踐分享(上)

架構師小組交流會:每期選一個時下最熱門的技術話題進行實踐經驗分享。java

第三期:微服務。微服務架構以其高度的彈性、靈活性和效率的巨大提高,快速受到各領域架構師和技術決策者的關注。它的基本理念是將一個肥大的系統拆分紅若干小的服務組件,組件之間的通信採用輕量的協議完成。咱們本期小組交流會來探討一下,如今互聯網公司的微服務實踐狀況。python

嘉賓:京東章耿、原惟品會石廷鑫、七牛陳愛珍數據庫

本文是對這次交流的整理,分了上下兩篇文章。json

 

第一輪:自由交流後端

京東章耿:你們好,我是京東基礎架構部平臺中間件的章耿,主要負責京東的服務框架,配置中心等項目。京東11年末進行.NET轉Java的技術變革,當時就提出了接口的SOA化的概念。那時京東業務發展很是快,項目愈來愈多,服務化是必然的趨勢。京東的服務化框架是一共有兩代。第一代是12年開始,咱們使用開源的一個實現,用Dubbo做爲RPC框架,Zookeeper 做爲註冊中心,那時應該算一個主流的技術選型。咱們在開源的基礎上作了一些易用性和功能擴展,好比說支持REST、支持kryo/thrift等序列化,服務監控等,這個框架在那時的業務規模和節點數量下面仍是比較穩定的。14年初咱們開始自研服務框架。爲何這麼作呢?一個是以前的服務框架仍是有不少能夠提高的地方,無論是性能仍是服務治理的一些功能,由於京東的機器數,機房也在不停的建,網絡拓撲的複雜直接須要高級的服務治理功能;還有一個就是接口節點等數量級的增長,當時咱們的接口規模慢慢的已經好幾千了,接口的實例也幾十萬;另外就是用開源的有些內部系統打通比較麻煩,因此咱們要作升級換代。當時也是考量了用開源的改改,仍是所有本身從新作的抉擇。後來以爲一個是有時間,二是以爲本身有能力作一個符合京東本身的定製化的服務框架,因此14年咱們就開始自研框架,作了整整一年。15年初咱們上線新版的服務框架。服務器

 

咱們新的註冊中心,是無狀態的一些節點,基於數據庫作最終一致性。爲何選數據庫,替換之前的Zookeeper?由於Zookeeper是樹狀結構,從某些維度查詢它要遍歷整棵數,用數據庫的好處就是能夠從多維度的查詢分析過濾,無論是機房、 IP,均可以去查詢,分析,過濾比較結果。而後Zookeeper在跨機房的時候有一個問題,它是半數節點存活才能夠用,因此若是跨機房部署的話,最起碼得3個機房,才能保證集羣總體可用。還有Zookeeper它是強一致性的的,比較依賴網絡。若是網絡很差,若是跨機房斷網的時候,它實際上是不可用的,讀都不能讀,因此會帶來必定的問題。之前用zookeeper註冊服務端,就是寫一個臨時節點,等服務端死了節點自動消失的。可是你在網絡一抖的時候,或者是服務端和Zookeeper之間有網絡故障的時候,它其實會不當心把它摘掉,由於Zookeeper認爲它死了,但其實它不必定真的死了,因此這個時候就須要有一些輔助的去判斷它是否是真的死了。第一次遇到的狀況是那個臨時節點,後來咱們是把它改爲永久節點,而後定時的去telnet 它的端口,像Dubbo是直執行ls 命令,咱們也是直接執行一個命令,看它有沒有響應,那是第一代的時候。在JSF的框架裏有一個哨兵的組件,咱們的Provider會定時的發心跳,對於註冊中心來講,它知道最後的心跳時間,而後定時刷到數據庫裏面,看哨兵的狀況,若是沒有哨兵,數據庫裏面保存一個最後心跳時間,這時候你能夠用定時任務去找它,這是咱們最先的一個版本。後來咱們改進了,由於有時斷網了,這個心跳時間就不許了。因此在每一個機房還布了一套獨立的程序,沒心跳的同時再由它來判斷是否可用,若是這個同機房的程序都連不上,咱們再把它置成一個不可用的狀態,雙重保證。另外之前Zookeeper的時候服務列表是下發的全量列表,例如1000臺加一臺,下發的是1001臺,而新版註冊中心咱們是推變化的部分,只推加1臺,大大節省了數據的推送量。網絡

 

RPC框架,咱們內部叫傑夫,JSF,京東服務框架的簡稱。咱們是用基於Netty本身研發的。爲了兼容上一代版本,兼容以前的dubbo協議,因此咱們也是用的無代碼入侵的;咱們在同一個端口支持多協議,包括自定義的JSF協議,http協議,dubbo協議等。目前咱們只有C++和Java的客戶端,而後若是是其它語言例如Golang,python,PHP的話,咱們都會讓他向咱們的一個HTTP的網關發請求,這個網關主要就是轉發。把前面的http請求轉換到後面一個JSF請求,也是基於Netty作的。序列化默認是Message Pack,是個跨語言的協議,也支持hessian,json,Java,Protobuf等。註冊中心和RPC框架直接是長鏈接,能夠進行一個通信。架構

 

惟品會石廷鑫:你們好,我是石廷鑫,原來在京東、惟品會,如今在宅急送。我基本上都是在倉儲物流這方面。之前在亞洲一號是按照倉庫的整個操做細節分紅各個模塊來作的服務拆分,每一個模塊是單獨部署的。倉儲的每一個倉,根據種品類不同,整個的操做流程是不同的。可是核心的東西,如庫存、訂單管理,都是同樣的,只是一些組合不同。舉個例子,小件商品上下架都要作的,可是對於大件商品,好比說你們電,基本上都不須要放架。打訂單也不須要,完成配送才須要訂單,其實是到了最後才綁定訂單。因此每一個流程不同,須要的組合也不同。那時咱們就想到了,把每一個模塊先拆出來,主要是用KVM運行整個節點,業務部分就用這些節點來整個串聯起來。核心的東西好比說庫存、訂單、商品資料,基本上都是用這個簡單的模塊。併發

 

惟品會的倉儲也是按這種思路來作的。當時惟品會用的是Dropwizard,其實是咱們用了它的一個殼,後面仍是用的Spring,也作了一個模塊,把Spring集成到一塊。後來Springboot作了出來,基本上就把Dropwizard拋棄掉了。由於Dropwizard版本升級變化比較大。但它有一個好處,就是Bundle比較好,服務化拆分的時候能夠根據它的大小進行可分可合,若是不須要拆分的時候,咱們就把Bundle合到一塊,若是須要拆分的話,就把Bundle再拆出來,單獨這個應用是很是容易的。負載均衡

 

我去年到的宅急送,咱們的服務註冊、服務發現、網關都使用的Spring Cloud的這一套。目前來講仍是不錯的,基本沒發現大的毛病。惟一的問題是若是前期沒有作好的整個數據抽取,整個報表可能會比較麻煩一些。

 

七牛陳愛珍:你們好,我是七牛的陳愛珍。微服務架構的設計理念很是適合七牛的業務特色,每一個服務只負責單一的職責。好比音視頻的處理服務:音視頻轉碼 , 音視頻拼接 , 視頻幀縮略圖,點播流式轉碼,都是以微服務的方式構建,這樣每一個服務都擁有獨立的運行環境,而且能夠根據自身的業務壓力狀況進行獨立擴展,動態的彈性擴展還能夠提升資源的利用率。一個可落地的微服務架構應該爲微服務提供獨立的運行環境,調度框架,註冊中心,配置管理中心和監控平臺。 七牛採用的是Mesos+Docker+自研調度系統的架構。Docker作環境封將,Mesos作資源調度,自研的調度系統負責對Docker進行彈性的調度。

 

咱們使用Consul作註冊中心,實現服務的註冊與發現。Consul自帶key/value存儲,可經過DNS接口作服務發現,且具體健康檢查的功能,並支持跨數據中心的服務發現。API Gateway 能夠經過 Consul提供的DNS接口查詢到服務全部的可用實例的列表信息,並將請求進行轉發。流量轉發具備負載均衡的功能,採用的是輪詢的方式,服務發現則是基於Consul作的。用戶請求進來後經過Consul查詢到全部可用節點的訪問地址,再經過輪詢的方式將請求發給後端的服務進行處理,對於返回的結果僅做轉發,由請求方解釋和使用。而且在API網關中帶有監控的組件,對請求數,失敗數等進行監控,傳送到Prometheus服務器上。經過監控數據對請求進行流量控制及服務降級等相應的處理。

 

當須要調用多個微服務時,根據七牛雲的數據處理的業務特色咱們使用管道(pipeline)來進行串行的處理。每個微服務的輸出都是下一個微服務的輸入,直到最後一個微服務執行結束纔是最終數據處理的內容。好比上傳一個視頻資源後,須要作兩個數據處理操做: 轉成mp4資源和進行HLS切片,這種場景下不能對原資源同時執行兩個數據處理的操做,必須按序執行。 

   

第二輪:話題交流

主持人:服務與服務之間的依賴關係怎麼管理?服務編排怎麼作?把這些服務節點串起來。

 

惟品會石廷鑫:比方說不是業務的,基礎服務,如圖片服務器這些,都是獨立的。惟一相關的是下面的業務層和底下的基礎服務有之間調用,還有是業務模塊之間有服務的調用,在系統裏是沒作體現的,可是咱們在服務和服務之間,就加了相似於熔斷的那個默認的東西。系統之間的依賴關係,咱們本身作了一個簡單的系統進行維護。Spring cloud eureka是都是存在內存裏,咱們改良過,我都改到一個數據庫。咱們交互所有都是Rest ,咱們後邊還寫過一套,Google protobuf。咱們倉儲的內部的業務模塊之間是用Google protobuf來作的。咱們自個作了一套虛擬化的在裏邊的。

 

惟品會石廷鑫:我如今用的是Apache camel作編排,能夠用DSL描述把服務串起來。其實更多的是業務的流程怎麼組織,怎麼去把基礎服務讓串起來,造成一個真正大的業務場景。

 

京東章耿:目前京東大部分一個接口一個方法就已是操做多張表了,通常認爲是一個比較原子性的操做了,若是再在外面有一個東西把它包一下,例如把3個方法包成一個方法,其實意義不大,因此咱們如今是沒有作這方面的工做。另外京東有彈性雲,用的Docker,不過不是大家想象中那種微服的那個Docker用法,京東如今用叫「胖容器」,更像一個虛擬機同樣的一個東西。Docker裏面運行的是一個應用,而後這個應用,它可能包含多個接口多個方法。可能你們理解微服務的Docker用法應該是一個容器裏面,他只跑一個獨立的邏輯,對數據的一個操做,或者對一個資源的操做。好比說下訂單、扣庫存,這兩步操做,他可能跑了兩個容器。把它編排成一個service的這種,咱們好像沒有這種。

 

主持人:服務拆分是怎麼作的?

京東章耿:京東如今的服務其實也是沒拆太細,主要仍是業務部門本身控制服務粒度。京東的業務仍是比較複雜的,各個應用之間互相依賴,互相調用,每一個操做基本都會涉及到不少資源的變動,像微服務推崇的那種對單一資源的操做,基本上沒有。說實話,這種大型互聯網公司裏面的服務根本就微不起來的,不可能像RESTful同樣,對一個資源的一個put post 操做基本不可能,咱們如今都是力度仍是由使用咱們框架的研發人員本身定的,而後通常他們都是根據這種方法之間的一些關聯性或者原子性,或者是擴展性來進行組合或者拆分。因此咱們通常叫本身服務化框架,不叫微服務框架。另外他們可能還會考慮一些服務是否能夠獨立部署,拆的時候可能會考慮一下這些。

 

主持人:其實不少大型電商互聯網也拆不開,也不能稱之微服務,是那種服務力度很粗,而後每一個服務號有若干個接口,其實耦合性很高的合在一塊兒,相關度很高,數據都在一塊兒。

 

京東章耿:都差很少,都是業務開發本身來折分服務粒度的。就像剛纔說的下單。確定是一次要操做好多表的。業務開發認爲這是幾回表操做實際上是一個下單的原子操做,那麼他就拆到這麼細了。

 

惟品會石廷鑫:咱們服務不是說一個部一個,實際上它是和數據域相關的,都擱到一塊。

 

惟品會石廷鑫:按功能分的,功能跟功能之間調用,若是不是同一個數據域裏邊的,仍是用RPC來調用的。

 

京東章耿:那個聽起來很美好,你想咱們如今這樣拆,都已經上萬了接口,方法基本都上十萬了。你這樣拆的話,起碼乘以10的接口,並且這樣搞的話就得整個公司都要動用很是很是大的能力去搞好這個事情。

 

主持人:單體他若是拆成像市場上去提倡的那種微服務,其實他對內部的消耗是很是大的,由於咱們不少的服務內部的調用,實際上是很是頻繁,若是都把它拆開了去獨立部署的話,它其實對網絡的消耗是要求很是高的。

 

惟品會石廷鑫:就是最難的點,一開始你是拆不開這個數據。

 

主持人:數據只要能拆開,你什麼都好乾。你只要能把數據粒度拆的很細的話,那就沒問題了,那也能作的很細,但就是拆不開。其實好多數據都是陳年老表,都是很都是從原來系統繼承下來的,就很難拆。

 

惟品會石廷鑫:因此新作一個系統還能夠。要作這個老系統計劃很難的,拆個表就要拆數日。

 

京東章耿:並且是數據量比較少,而後邏輯比較簡單的,例如那種創業型公司,使用開源的方案,這種能夠很方便。

 

主持人:在雙11時各個電商確定會有大型的促銷,這時服務的壓力確定會有很大的增加,怎麼解決服務的伸縮的問題?

 

惟品會石廷鑫:就像咱們這邊的話,就看哪一個基點的壓力比較大一些,而後你多布幾個基點就能夠了。如今基本上都是中泰的那個,就是Spring cloud那套。擴展都是提早先作一步。自動擴的話,就是至關於咱們租了一個相似於簡單的監控。就是根據他的實例,而後由於微服務,咱們如今是Spring cloud ,基本上都是java -jar,而後本身啓就得了,反正那個jar,你能夠放到一個公用的地,遠程java -jar要幹架就起來了,監控的時候根據他的量,而後隨時能夠啓就好了。

 

京東章耿:京東的服務發佈都是掛在應用下面的,而應用發佈的平臺其實會和各個系統打通,好比說數據庫受權的系統,而後自動掛VIP的一些系統,掛監控平臺,日誌系統等。而後咱們還有個監控平臺,監控一些指標,例如機器狀況,應用狀況,還有本身業務埋點的性能等數據。至於服務是否有壓力,都是本身評估,本身提早擴展。 通常大促前會進行大規模的壓測,他們本身壓測,而後根據結果本身擴就能夠了。京東是沒有開自動彈性擴展的,基本都是大促前提早申請容器,而後提早擴完。

 

惟品會石廷鑫:併發量大的業務都是放在公有云,雙十一比日常多了兩倍的機器,咱們只買 了一個月的雲主機。臨時用幾天,結束就不用了。

相關文章
相關標籤/搜索