本次分享的技術大綱以下:前端
挑戰1-- 研發成本高nginx
主要體如今以下幾個方面:數據庫
在實際項目分工時,開發都是各自負責幾個功能,即使開發之間存在功能重疊,每每也會選擇本身實現,而不是類庫共享,主要緣由以下:後端
跨地域、跨開發小組協調很困難,業務團隊可能跨地域研發,內部一般也會分紅多個開發小組,各開發小組之間的協調和溝通成本很是高。瀏覽器
代碼重複率變高以後,已有功能變動或者新需求加入都會很是困難,以充值繳費功能爲例,不一樣的充值渠道開發了相同的限額保護功能,當限額保護功能發生變動以後,全部重複開發的限額保護功能都須要從新修改和測試,很容易出現修改不一致或者被遺漏,致使部分渠道充值功能正常,部分存在Bug的問題,示例以下:安全
挑戰2-- 運維效率低網絡
在傳統的MVC架構中,業務流程是由一長串本地接口或者方法調用串聯起來的,臃腫而冗長,並且每每由一我的負責開發和維護。隨着業務的發展和需求變化,本地代碼在不斷的迭代和變動,最後造成了一個個垂直的功能孤島,只有原來的開發者才理解接口調用關係和功能需求,一旦原有的開發者離職或者調到其餘項目組,這些功能模塊的運維就會變得很是困難:數據結構
當垂直應用愈來愈多時,連架構師都沒法描述應用間的架構關係,隨着業務的發展和功能膨脹,這種架構很容易發生腐化。架構
如何解決傳統單體架構面臨的挑戰?app
解決對策:一、拆分 二、解耦 三、透明 四、獨立 五、分層。
服務的訂閱發佈機制
它的核心理念是實現服務消費者和服務提供者的解耦,讓服務消費者可以像使用本地接口同樣消費遠端的服務提供者,而不須要關心服務提供者的位置信息,實現透明化調用。
關鍵技術點:服務的訂閱、發佈機制、服務的健康狀態檢測和高HA。
經常使用的服務註冊中心有Zookeeper、ETCD,以及基於數據庫的配置中心。
你們在技術選型的時候,須要根據本身的業務實際狀況進行選擇。例如超大規模集羣,服務實例數超過10W,Zookeeper就會存在性能問題。
如今開源的分佈式配置服務不少,如無特殊需求,建議選擇開源方案。
服務化實踐-零侵入
實際上,徹底的零侵入很難作到,即便是聲明式配置,配置自己也是代碼的一部分,只不過相比於代碼類庫依賴,它不是編譯器依賴。
一種好的作法是,服務的發佈和消費經過聲明式或者註解的方式,而不是直接調用服務框架的接口,例如Thrift。客戶端須要調用Thrift提供的類庫訪問服務端,這就是代碼API級的依賴,對業務代碼侵入比較大。
一種比較成熟的實踐是 利用Spring的擴展機制,經過XML的方式實現服務的發佈和消費。
服務化實踐-容錯和路由
單體應用服務化以後,一般採用分佈式集羣的部署模式。
這會帶來兩個問題:
大部分的容錯和路由策略能夠抽象到分佈式服務框架中,經過策略配置的方式提供給用戶使用,下降用戶的開發成本。
從業務擴展性角度看,服務框架一般會提供擴展點,供業務作路由和容錯定製。例如,業務但願根據手機號碼和地市進行路由:
服務化實踐-本地短路策略
在電信行業中,小機仍是很廣泛,應用一般會合設,例如服務提供者和消費者部署到同一臺主機上。
爲了提高性能,下降時延,每每會提供本地短路策略,具體策略以下:
服務化實踐-多樣化調用方式
服務的調用方式,主要有三種:同步服務調用、異步服務調用、並行服務調用。最經常使用、簡單的就是同步服務調用。
異步服務調用的工做原理以下:
詳細步驟以下:
並行服務調用,目的是爲了提高服務調用的並行度,下降E2E時延。
服務化實踐-高性能、低時延
服務框架的性能,主要強調三個要素:一、I/O通訊;二、序列化框架;三、線程調用模型。
若是使用Java語言,I/O框架推薦 Netty。
序列化框架推薦:Thrift、Avro序列化框架、PB等。線程調度模型建議參考Reactor。
一種線程模型的參考實現方式:Netty的線程模型
服務化實踐-故障隔離
故障隔離很是重要,因爲常常會採用同步服務調用模式,核心服務和非核心服務共用同一個線程池和消息隊列,非核心服務處理慢每每會阻塞核心服務,致使雪崩現象。
故障隔離的核心技術點以下:
1. 支持服務部署到不一樣線程/線程池中
2. 核心服務和非核心服務隔離部署
服務化實踐-服務治理
隨着業務規模的不斷擴大,小服務資源浪費等問題逐漸顯現,須要可以基於服務調用的性能KPI數據進行容量管理,合理分配各個服務的資源佔用,提升機器的利用率。
線上業務發生故障時,須要對故障業務作服務降級、流量控制、流量遷移等,快速恢復業務。
隨着開發團隊的不斷擴大,服務的上線愈來愈隨意,甚至發生功能相同、服務名不一樣的服務同時上線。上線容易下線難,爲了規範服務的上線和下線,在服務發佈前,須要走服務預發佈流程,由架構師或者項目經理對須要上線的服務作發佈審覈,審覈經過的纔可以上線。
爲了知足服務線下管控、保障線上高效運行,須要有一個統一的服務治理框架對服務進行統1、有效管控,保障服務的高效、健康運行。
服務治理是分佈式服務框架的一個可選特性,儘管從服務開發和運行角度看它不是必須的,可是若是沒有服務治理功能,分佈式服務框架的服務SLA很可貴到保障,服務化也很難真正實施成功。
從架構上看,分佈式服務框架的服務治理分爲三層:
第1層爲服務治理展現層,它主要由服務治理Portal組成,提供可視化的界面,方便服務運維人員進行治理操做。
第2層爲服務治理SDK層,它主要由以下幾部分組成:
第3層爲後臺服務治理服務層:它一般由一組服務治理服務組成,能夠單獨部署,也能夠與應用合設。考慮到健壯性,一般選擇獨立集羣部署。治理服務的可靠性由分佈式服務框架自身來保證,治理服務宕機或者異常,不影響業務的正常使用。服務治理服務一般並不隨服務框架發佈,治理服務是可選的插件,單獨隨服務治理框架交付。
服務化實踐-高可靠性
關鍵技術點設計以下:
服務化會帶來不少收益,可是它卻不是銀彈。
服務化不是銀彈-時延問題
在服務化以前,業務一般都是本地API調用,本地方法調用性能損耗較小。服務化以後,服務提供者和消費者之間採用遠程網絡通訊,增長了額外的性能損耗。
服務化不是銀彈-問題定位
在分佈式環境下,如何高效的進行問題定界定位和日誌檢索
服務化不是銀彈-事務一致性
服務化、分佈式部署以後,有邏輯關聯關係的多個數據庫操做被打散到集羣中各個獨立的服務實例中,引入分佈式環境下的事務一致性問題。
服務化不是銀彈-先後臺直接通訊問題
先後臺直接通訊問題以下:
存在的問題以下:
服務化不是銀彈-團隊協做問題
微服務的劃分原則是難點,根據華爲的經驗:微服務劃分不是一步到位,而是不斷的迭代和演進,最終找到適合本身團隊和業務的微服務劃分原則。
將來演進方向-基於Docker部署微服務
使用Docker部署微服務的優勢總結:
將來演進方向-雲端微服務
利用雲平臺的彈性資源調度,動態性等,能夠實現微服務的Dev&Ops
最後咱們一塊兒回顧下服務化的演進歷程:
Q&A
Q1:上面提到服務化缺點的第三條接口變動問題,請問微服務是如何解決這個問題的呢?或者說微服務相比之下什麼優點會避免這個問題?
A1:根據咱們團隊的經驗,主要從以下幾個方面下降影響:一、微服務的接口就是契約,制定 接口兼容性規範;涉及到技術和管理兩個層面;二、微服務鼓勵只作一件事情,所以它更加穩定;三、基於消費者契約測試,快速發現兼容性問題。
Q2:微服務架構裏,分佈式事務如何作的,對數據一致性要求較高的系統是否適合拆分紅微服務,或者說微服務的粒度如何把握?
A2:分佈式事務是難點,策略以下:1)若是業務上可以承受非強一致性,建議經過事務補償的方式作最終一致性,能夠基於MQ等中間件來實現;2)若是是轉帳、實時計費、充值等對實時性要求高的,每每選擇強一致性事務,就須要引入TCC等分佈式事務框架。不管如何,只要作分佈式,事務一致性就會成爲問題,跟是不是微服務沒必然關係。
Q3:生產環境中的服務註冊中心必然是共享的,那如何去作灰度發佈或者A/B Test呢?
A3:一種比較好的服務灰度策略是:1)服務框架提供灰度規則框架,包括後臺引擎和前臺Portal,由業務配置灰度規則;2)分佈式服務框架支持灰度規則推送和業務自定義路由;3)前端SLB ,例如Ngix作灰度插件,接收灰度規則。消息從前端門戶接入到後端服務路由,都支持基於規則的路由分發策略,實現灰度發佈。
Q4:Netty的無鎖化串行會比有鎖的並行性能更高嗎?有案例嗎?華爲如今都是用Docker部署應用嗎?
A4:Netty的無鎖化串行性能問題:1)在實際項目中,線程池爭用模式和串行模式咱們都使用過,Netty的無鎖化串行模式性能更高。Docker部署應用:華爲的公有云和私有云都支持基於Docker部署應用,由客戶根據須要自主選擇。
Q5:IO通訊是怎麼保證每次鏈接成功的呢?
A5:NIO通訊自己並不保證每次鏈接都成功,它的鏈接是異步的,你能夠根據以下兩種策略得到異步連接的結果:1)發起鏈接以後主動調用同步方法等待結果返回,阻塞式;2)獲取異步鏈接Future,添加Listener監聽器監聽鏈接結果,這種模式是異步回調,不會阻塞當前線程。
Q6:使用zk做爲服務註冊中心,對與某個服務當客戶端鏈接數不少時候節點變化會引發羊羣效應,怎麼處理這種問題呢?或者說如何避免這種問題呢?
A6:這個問題真是好!一般而言,你們會使用服務註冊中心作服務可用性檢測,若是發現某個服務節點不可用,就會將其從註冊中心中刪除。可是,有一種場景是ZK檢測的結果跟客戶端和服務端實際的鏈接狀態不一致。從ZK看,服務提供者可使用。可是因爲服務消費者跟提供者之間的鏈路已經中斷,跟ZK的鏈路倒是正常,這種狀況下就會出現狀態不一致問題。因此,只依靠ZK作狀態檢測還不夠,須要服務提供者和消費者的鏈路層作雙向心跳檢測。
Q7:我如今作的系統是zk作註冊中心服務把地址註冊上去(臨時節點),客戶端拿地址請求,http的,如今發現若是是公網調用的話,對公網資源要求還挺多的,zk公網, 應用公網;爲了減小對公網需求,中間加一層nginx,把nx地址註冊上去,不過又得加個http探測監控程序,異常還得刪掉註冊數據,不知道這種作法是否穩當?
A7:Ng監聽ZK註冊的服務提供者URL便可,問題不大。
Q8:用Netty作同通訊框架,監控上報應該怎麼設計更完善?
A8:建議的方式以下:Netty自身不用告警,監聽Netty的異常事件,而後經過MQ吐出去,監控系統訂閱通訊框架的事件主題,實現通訊框架和監控系統解耦。
Q9:SOA和微服務架構的區別和聯繫是?看起來好像啊!
A9:1) 服務拆分粒度:SOA首先要解決的是異構應用的服務化;微服務強調的是服務拆分儘量小,最好是獨立的原子服務;
2) 服務依賴:傳統的SOA服務,因爲須要重用已有的資產,存在大量的服務間依賴;微服務的設計理念是服務自治、功能單一獨立,避免依賴其它服務產生耦合,耦合會帶來更高的複雜度;
3) 服務規模:傳統SOA服務粒度比較大,多數會採用將多個服務合併打成war包的方案,所以服務實例數比較有限;微服務強調儘量拆分,同時不少服務會獨立部署,這將致使服務規模急劇膨脹,對服務治理和運維帶來新的挑戰;
4) 架構差別:微服務化以後,服務數量的激增會引發架構質量屬性的變化,例如企業集成總線ESB(實總線)逐漸被P2P的虛擬總線替換;爲了保證高性能、低時延,須要高性能的分佈式服務框架保證微服務架構的實施;
5) 服務治理:傳統基於SOA Governance的靜態治理轉型爲服務運行態微治理、實時生效;
6) 敏捷交付:服務由小研發團隊負責微服務設計、開發、測試、部署、線上治理、灰度發佈和下線,運維整個生命週期支撐,實現真正的DevOps。
總結:量變引發質變,這就是微服務架構和SOA 服務化架構的最大差別。
Q10:若是要將現有單機服務重構到微服務,應該考慮哪些問題?數據遷移的安全問題怎麼解決?有什麼實踐方案嗎?
A10:須要考慮的問題以下:1)當前單機應用是否可以知足業務發展須要,有沒有必要作服務化改造和分佈式部署;2)評估遷移的工做量,以及人員技能培訓等。3)自研服務框架仍是使用開源的方案。
數據遷移安全問題:若是內網,一般不會涉及到複雜的安全控制問題;若是跨公網,建議加入API Gateway統一作安全管控。
實踐方案:公開的資料,能夠參考淘寶的服務化實踐、京東的服務化實踐等。其實華爲也有,不過遺憾的是目前政策不容許公開出來。
Q11:麻煩李老師介紹下大家華爲內部基於netty作socke通訊的協議設計的最佳實踐。
A11:這個問題很大,簡單介紹下思路。在11年和13年的時候我分別主持設計了華爲基於Mina和Netty的統一NIO通訊框架。設計要點以下:1)要熟悉Netty的線程調度模型、經常使用的類庫等,可以熟練使用Netty;2)NIO通訊框架的分層原則,哪些該作、哪些不應作,須要識別出來;3)擴展點,預留足夠的擴展點給上層應用協議棧作擴展;4)能夠內置配置化的安全策略、握手認證、心跳檢測等機制;5)可服務性設計,包括日誌、性能KPI指標等。