首頁>技術>

微服務架構概述

微服務架構(Microservice Architecture)是近兩年來最流行的架構術語之一,大名鼎鼎的Martin Flower曾這樣描述它:

“微服務”只不過是滿大街充斥的軟體架構中的一個新名詞而已。儘管我們非常鄙視這樣的名詞,但其描述的軟體風格越來越吸引我們的注意。在過去幾年裡,我們發現越來越多的專案開始使用這種風格,以至於我們的同事在構建企業級應用時,理所當然地認為這是一種預設開發形式。然而,很不幸,微服務風格是什麼,應該怎麼開發,關於這樣的理論描述卻很難找到。

在網際網路時代,在極端情況下每天都有新需求要開發上線。隨著程式碼量及團隊成員的增加,傳統單體式架構的弊端日益凸顯,嚴重製約了業務的快速創新和敏捷交付,與網際網路所追求的“唯快不破”的目標越來越遠。這就是微服務架構興起的時代大背景。

微服務架構興起的原因

為什麼微服務架構會快速流行?為什麼越來越多的人認為微服務架構是--種預設的開發形式?

為了弄明白上面兩個問題,我們需要先弄明白另外兩個基本問題,即我們通常講的單體架構是怎樣一種架構?微服務架構又是怎樣的一種架構? 下面這張圖顯示了兩者間的區別。

傳統的應用架構又被稱為單體架構( Monolithic),表現為業務系統的各個模組是緊耦合的關係,各模組執行在一個程序中,每次升級系統時基本上都要重啟整個應用程序,如果某個模組有問題,則可能導致整個系統無法正常啟動。微服務架構則是將業務系統中的不同模組以微服務的方式進行拆分,使每個微服務都變成-一個獨立的Project,獨立編譯並且部署為一個獨立的程序,每個微服務都可以被部署為多個獨立的程序對外提供服務,對外的介面方式通常是REST或者RPC,不同的微服務程序也可以被部署到多個伺服器上。

我們透過對比就會發現,微服務架構透過將一- 個龐大的單體程序分解為相互獨立的多個微小程序,以分散式的思想巧妙解決了傳統單體架構在網際網路時代遭遇的各種問題。所以微服務架構這種新的理念被大家快速接受並且迅速流行,是有深刻原因的。

為了解決傳統單體架構面臨的挑戰,軟體架構先後演進出了SOA架構、RPC架構、分散式服務架構,最後演進為微服務架構。但我們需要牢記一點:軟體開發從來不存在銀彈,因此微服務化架構也不是銀彈,它更多的是一種架構思想與開發模式的改變,而在具體實施過程中還存在大量的技術問題及團隊問題需要妥善解決。

微服務架構實施過程中所面臨的最大技術問題之一就 是開發運維過程中的自動化。假如我們要把原來某個中等規模的系統架構改造為微服務架構,則最少也能拆分出十幾個微服務,於是這麼多微服務程序的編譯、部署、調測及升級就演化成一一個浩大的工程了,如果沒有自動化的手段,則微服務化是無法推動的。說到自動化,就不得不提到容器技術,它是促進微服務架構發展的重要動力,也是微服務架構得以快速流行的重要原因。

不得不提的容器技術

容器技術其實很早就被- - 些網際網路公司廣泛使用了,早在Docker 興起前的十幾年內,Google就- 直採用容器技術支撐著世界上最大的分散式叢集,只是一直對外保守秘密,直到祭出微服務架構利器Kubernetes。Google 之所以開源該技術,是因為容器技術已經被業界公認為IT界最重要的平臺級技術,如果不能搶佔先機和掌握話語權,就會逐步失去技術領先性所帶來的市場份額。

我們先來回顧Docker的發展歷史。Docker在2014年才釋出1.0 版本,成為2014年的熱門技術之一。從2004年年初的B輪融資到該年年末的DockerCon歐洲大會,Docker 在這一年裡順風順水,就連微軟、Google、AWS也對其青睞有加,彼時,微服務架構、雲計算、DevOps等技術理念如日中天,Docker恰恰完美地從技術上驅動了這些概念的落地。2015 年,CoreOS釋出了自己的容器引擎Rocket,引發容器技術分裂與統一的大爭論, 隨後在Linux基金會的干預下,Docker 公司與CoreOS公司握手言和,成立了OCI (Open Container Initiative)標準委員會,它類似於當年Java的JCP組織,參與者包括Google、RedHat 等巨頭,OCI 組織負責制定容器技術標準規範。2016 年釋出的Docker 1.11成為第一一個符合OCI標準的容器引擎。從2014年到2016年,DockerHub 的下載量從1億增加到了60億! 2017 年,Docker 公司將Docker的版本區分為企業版和社群版,開始面向企業收費,隨後又將Docker開源專案的程式碼遷移到新的Moby專案上,Moby 專案被推給社群維護。Docker 公司則提供兩個產品,其中Docker-ce是基於Moby專案的免費的容器產品,Docker-ce 是它的商業產品。我們知道,在軟體開發過程中有很多環節是靠人工的,比如搭建環境、釋出安裝包(釋出安裝包到某個FTP伺服器上或者以隨身碟方式複製)、部署應用、升級系統等,這些過程都比較耗時耗力,很難保證任務的質量與完成時間。在分散式系統中,一-旦叢集上了 規模,上述人工操作就極易因為大量重複性的勞動導致各種難以排查的錯誤。Docker公司敏銳地察覺到了傳統軟體開發中的上述痛點,以創新性的標準化映象(Docker Image) 打包釋出應用技術為突破口,成功定義了“軟體生命週期中的標準化與自動化”的新標準。下面這張圖給出了Docker的標準化映象的示意圖。

Docker映象是一一個包含了目標程式所有依賴檔案的“All in one"的分層壓縮包,你可以認為它是一一個沒有Linux核心但有Linux檔案系統和基礎命令的一個最精簡版的虛機,在這個虛機裡包括了已經安裝和配置好的目標應用二進位制程式碼,以及執行目標程式中的所有其他依賴包,比如一個執行在Torncat中的完整應用的Docker映象組成如下。

啟動映象的過程就是啟動打包製作映象時指定的目標程式,比如對於Tomcat來說,就是執行tomcat.sh命令。此外,由於映象本身已經固化了安裝過程及配置引數,所以透過Docker映象建立和啟動一個容器就變成了一個非常簡單並且不會出錯的命令:

docker run xxximage

而執行期間需要指定的引數可以透過環境變數及啟動命令的引數等方式傳遞到容器中,不同的容器之間相互隔離,可以在一個主機上同時啟動不同映象版本的容器並測試資訊。更進一步地,Docker將製作映象(build image)、建立容器,以及啟動、停止、掛起、恢復、銷燬容器:的所有功能都做成了RESTAPI,於是我們可以透過程式設計來實現自動化控制,後面提到的Kubernetes就採用了Docker的API實現了全自動的微服務架構平臺。

打包好的Docker映象是否可以像原始碼一樣進行版本管理、集中託管並且被全球任意聯網的機器下載執行呢?Docker公司的第二個創意就模仿了GitHub的做法,建立了全球唯-的開放性Docker倉庫一Docker Hub,任何組織和個人都可以註冊賬號,並且分享自己打包的Docker映象,現在你所能想到的任何中介軟體或基礎應用幾乎都在Docker Hub上存在映象,比如下面這行命令就自動從Docker Hub拉下來-一個 MySQL映象,並且在本機上啟動了一個MySQL伺服器,可以讓遠端機器訪問。Docker Hub的存在大大加速了Docker技術的普及和發展。

docker run -it一e MYSQL ROOT PASSWORD=123456 mysq1/mysql-server

私有的映象倉庫被稱為Docker Regitry,通常每個使用Docker的公司都需要自己建立一個私有的Docker Regitry,存放從Docker Hub拉取的標準基礎映象,以及基於這些基礎映象而打包的私有映象。下圖給出了Docker映象打包、執行過程中與Docker Registry之間的互動過程。

綜上所述,我們透過Docker技術可以很容易地將軟體開發從原始碼編譯、映象打包、測試環境部署、版本釋出、系統升級到生產環境釋出等生命週期中的所有重要環節自動化,這是加速微服務架構實施的重要技術保障手段,下圖是這個過程的一個簡單示意圖。

如何全面理解微服務架構

微服務架構是從SOA架構、RPC架構、分散式服務架構演變而來的,它也具有以下特點。

首先,微服務架構是一個分散式系統架構。也就是說,分散式系統設計的原則、經驗,以及常用的分散式基礎設施和中介軟體依然是微服務架構中的重要組成部分,如果拋開分散式架構中的這些技術,只是空談微服務架構,則好像空中樓閣。

其次,與SOA架構-一樣,微服務架構與開發語言無關,它並沒有公認的技術標準規範與實施方案,更多地體現了一種被 普遍接受的新的設計理念和指導思想,歸納下來有以下幾點。

輕量級的服務:每個服務例項都只提供密切相關的一種或幾種服務,粒度小、輕量級,便於微團隊快速開發、部署、測試與升級。

松耦合的系統:微服務之間的呼叫也是客戶端的一種呼叫方式,僅限於介面層的耦合,避免了服務實現層的深耦合,因此服務之間的依賴性被降到最低,系統的整體穩定性與平衡升級(滾動升級)能力得到切實保障。

平滑擴容能力:由於在微服務架構平臺中原生地提供了某種微服務負載均衡機制,因此對於無狀態的微服務,可以透過獨立部署多個服務程序例項來提升整體的吞吐量。由於每個微服務都可以單獨擴容,因此微服務架構具有很強的執行時的效能調優能力。

積木式的系統:每個微服務通常都被設計為複雜業務流程中一個最小粒度的邏輯單元(積木),某個完整的業務流程就是合理編排(搭積木)這些微服務而形成的工作流,升級或者重新開發一個新業務流程變成了簡單的積木遊戲,而隨著微服務越來越多,業務單元(微服務)的複用價值越來越大,因此新業務快速上線的需求變成了一個可準確評估和預測的計劃任務。最後,微服務架構也有某些事實上公認的框架與工具,目前最經典的有以下三個微服務架構開源平臺。

從RPC架構演變而來的IceGrid微服務架構平臺。

基於REST介面演變而來的Spring Cloud微服務架構平臺。

基於容器技術的Kubernetes微服務架構平臺。

上述這三個經典微服務架構平臺能提供完備的微服務架構與管理工具,在技術上各有千秋,從總體來看,Google 出品的Kubermetes是很優秀的微服務架構,也是本章要重點分析和講解的微服務架構。

接下來,我們一起看看在實施一-個微服務架構專案的過程中可能遇到的問題及應對策略。

首先,架構師需要對專案組的全體成員進行培訓,讓大家明白微服務架構的思想和優點,培訓的一個重要目標是要讓大家明白,微服務架構在實施過程中會給專案組帶來很明顯的技能升級需求,不管是對於開發人員還是對於運維測試人員來說,這都是一一個難得的新技術學習與自我技能提升的好機會,希望大家頂住壓力完成專案。

其次,要正確選擇-一個合適的微服務架構平臺而不是自己研發。這種大型基礎平臺的研發成本很高、開發週期長而且平臺可持續升級的可能性較低,因此目前很少有公司會自己進行研發,即使是RedHat這樣有實力、有經驗的開源軟體服務型公司,也放棄了自己的微服務架構,轉而應用Kubermetes 那麼,如何選擇適合自己公司和專案組的微服務架構平臺呢?以本節提到的三個典型的微服務架構平臺為例,可參 考如下條件進行選擇。

如果整個團隊對容器技術沒有什麼經驗,則排除Kubermetes,否則優先選擇它。

如果系統的效能要求很高,同時很多高頻流程中涉及大量微服務的呼叫,以及微服務之間也存在大量呼叫,則先考慮以RPC二進位制方式通訊的微服務平臺,優先考慮Ice,其次是Kubernetes,最後是Spring Cloud。

如果系統中更多的是自己內部開發的各種服務之間的遠端呼叫,很少使用中介軟體,只需要高效能的通訊及水平擴充套件能力,則Ice可能是最佳選擇,其次是Spring Cloud,最後才是Kubermetes。因為Kubernetes並沒有提供一一個 RPC架構,所以在這種情況下,反而增加了系統的複雜性。

如果專案是用多個語言協同開發的,則在這種情況下,可以優先選擇Kubernetes 架構與Ice.

再者,在微服務架構專案的實施過程中經常需要考慮如下工作。

(1)引入自動化工具與集中運維管理工具。自動化工具被用於程式編譯打包、自動化部署和升級等工作過程中。在集中化的運維監控工具方面主要包括日誌收集與查詢展示系統,用於收集分佈在各個節點上的系統日誌、應用日誌,以及資源監控與故障系統,用於展示資源使用狀態與應用告警。

(2)研究、測評大量相關開源產品(與工具)並引入微服務架構中。微服務架構本質上是一種分 布式架構,所以之前在單體架構開發中所寫的一些通用程式碼是無法被應用到微服務架構系統中的,比如最常見的配置模組、定時任務、同步邏輯等。此外,對於很多中介軟體來說,原先可能只用了單節點的方式,而在微服務架構下往往要切換成叢集模式,在這種情況下也需要對這些中介軟體進行更為深入的研究測試,甚至可能會因此轉向其他類似的中介軟體。

(3)團隊的重構。在微服務模式下,整個系統從架構層來看基本只分為展現層與微服務層。考慮到微服務在整個系統中的重要性,建議團隊中的骨幹技術人員成為微服務層的開發主力,大家作為一個 總體對所有微服務程式碼負責,一起設計每個微服務介面,一起評審所有微服務程式碼,而在具體的開發過程中,則可以將相似度較高的幾個微服務模組交由同一個人研發。這種模式基本符合二八定律。

(4)高質量的文件。在微服務架構下,文件特別是每個微服務的介面文件的重要性越來越高,因為每個使用微服務的人都要清楚當前所要呼叫的微服務是哪個、應該呼叫哪個介面、引數有什麼含義,以及返回值的意義。因此,我們需要一-份 詳細並且準確的微服務介面文件,還要保持文件與程式碼同步更新。

接下來看看如何設計系統中的微服務。一-開始, 我們其實並不很清楚要將哪些功能和服務設計成一一個微服務,以及-一個微服務究竟應該包括多少個介面,每個介面應該如何設計。筆者的建議是先粗粒度地劃分微服務,每個微服務包括比較多的介面以減少微服務的個數,這樣可以減少開發、程式打包、測試及部署的工作量,有利於快速推進專案。

系統中的微服務按照呼叫客戶端的不同,可以劃分為流程控制類、介面類及基礎核心類三種,如下圖所示。

一般來講,這三種不同的微服務的介面設計也有所不同。

流程控制類微服務主要面向UI呼叫,所以它的介面設計應該以頁面展示的便利性為第一目標,即大部分情況下采用JSON或TEXT文字的方式傳遞引數與返回值,並且考慮在呼叫邏輯出錯的情況下告訴客戶端錯誤的程式碼與原因,於是這類微服務的返回值通常會是下面的結構體:

public class CallResult    int resultCode; //返回程式碼,0為成功,其他為呼叫錯誤    string resultData;//呼叫結果,通常為JSON的字串    String errmsg;//呼叫錯誤的時候,展示給使用者的可讀錯誤資訊

介面類微服務主要面向第三方系統,所以特別需要注意安全問題,因此在介面設計中必須有安全措施,比較常見的方案是在呼叫引數中增加Token, 並考慮引數加密的問題,同時建議介面類微服務在實現過程中重視日誌的輸出問題,以方便介面聯調,並方便在執行期間排查介面故障,在日誌中應該記錄入口引數、關鍵邏輯分支、返回結果等重要資訊。

基礎核心類微服務主要被UI及其他兩種微服務所呼叫,在這類微服務的介面設計中主要考慮效率和呼叫的方便性。建議將其設計得與普通Java類的介面看起來一樣, 這樣可以避免將很多複雜Bean物件作為引數及返回值時不但增加呼叫者的負擔而且降低介面效能。

在微服務設計中,我們還需要考慮介面相容性的問題,比如如下微服務介面設計:

publie void doBusiness (paraml,param2,param3)

如果引數的個數存在增加的可能性,那麼為了相容舊版本,最好改為如下設計:

public class XXXBean{private String paraml;private String param2;private string param3;private String param4;}public void doBusiness (XXXBean thebean)

這樣一來,對舊介面無須重新編譯,只要升級XXXBean所在的JAR檔案即可相容舊版本。

33
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 老闆居然讓我在Java專案中“造假”