趙子晨 朱志祥 蔣來(lái)好
(1.西安郵電大學(xué) 西安 710061)(2.陜西省信息化工程研究院 西安 710061)
近幾年來(lái),“微服務(wù)架構(gòu)”的概念已經(jīng)在軟件開(kāi)發(fā)領(lǐng)域逐漸獲得認(rèn)可和實(shí)踐。微服務(wù)作為“面向服務(wù)架構(gòu)”(SOA)的下一代繼承者,其實(shí)際上也可以被歸為“分布式系統(tǒng)”這一范疇,并且進(jìn)一步發(fā)揚(yáng)面向服務(wù)架構(gòu)中的許多觀點(diǎn)和實(shí)踐。但是,它們區(qū)別的地方在于每個(gè)單獨(dú)的服務(wù)所應(yīng)承擔(dān)的功能范圍。在SOA中,每個(gè)服務(wù)將負(fù)責(zé)處理規(guī)模更廣的功能與數(shù)據(jù)領(lǐng)域,而微服務(wù)自從問(wèn)世以來(lái),業(yè)界普遍認(rèn)為,它所負(fù)責(zé)的部分是管理一個(gè)單獨(dú)的數(shù)據(jù)領(lǐng)域,以及圍繞著該領(lǐng)域的相關(guān)功能。使用分布式系統(tǒng)這種方式的目的在于將整體性的服務(wù)基礎(chǔ)設(shè)施解耦為獨(dú)立的可擴(kuò)展的子系統(tǒng),可以通過(guò)垂直分片的方式將這些子系統(tǒng)依賴合并在一起,并通過(guò)一種統(tǒng)一的傳輸方式將它們相互連接[1]。
微服務(wù)架構(gòu)對(duì)于服務(wù)之間交互的狀態(tài)性這方面有著嚴(yán)格的要求,不管采用了哪一種底層協(xié)議,微服務(wù)都需要保證通信的無(wú)狀態(tài)性,并且遵守RESTful模式風(fēng)格來(lái)實(shí)現(xiàn)這一點(diǎn),這在軟件開(kāi)發(fā)領(lǐng)域基本已經(jīng)達(dá)成了一致的認(rèn)可。Dubbo就是一個(gè)完美的構(gòu)建微服務(wù)的分布式服務(wù)框架,既可以實(shí)現(xiàn)RPC遠(yuǎn)程服務(wù)調(diào)用,又支持REST風(fēng)格遠(yuǎn)程調(diào)用(HTTP+JSON∕XML)。
使用Spring Boot開(kāi)發(fā)基于Dubbo框架的微服務(wù)的原因就是,將Dubbo微服務(wù)以Spring Boot形式標(biāo)準(zhǔn)化了。如此一來(lái)既可以享受Spring Boot框架和周邊的一系列研發(fā)支持,還可以用統(tǒng)一的形式發(fā)布、部署和運(yùn)維。即Spring Boot可使軟件開(kāi)發(fā)者面對(duì)很多個(gè)相同操作接口的微服務(wù),而不再是不同操作接口的微服務(wù)。
同時(shí)使用Maven+Docker進(jìn)行項(xiàng)目的快速構(gòu)建和可移植性部署,Maven可以使項(xiàng)目管理更加輕松,Docker容器作為一種輕量級(jí)的虛擬化技術(shù),提供和虛擬機(jī)相同的功能但又更加的強(qiáng)大,簡(jiǎn)單易用,輕快便捷[2]。
從本質(zhì)上來(lái)講,微服務(wù)(Microservice)在很早之前就是已經(jīng)存在的事物了,只是人們沒(méi)有給它定義一個(gè)比較專業(yè)的名稱而已。自SOA(Service Oriented Architecture)面向服務(wù)體系架構(gòu)誕生以來(lái),各大企業(yè)公司遵循SOA軟件架構(gòu)的思路,在服務(wù)化治理的道路上走了很長(zhǎng)的時(shí)間,總結(jié)了服務(wù)化思路的一種最佳實(shí)踐方向,這就是微服務(wù)。
微服務(wù)這個(gè)名字是和以前的服務(wù)化思路與實(shí)踐相對(duì)比得來(lái)的。很多年前的服務(wù)實(shí)現(xiàn)和實(shí)施思路是把許多從開(kāi)發(fā)到交付的功能給打包成一個(gè)特別大的服務(wù)單元,也即是單體式應(yīng)用(一般會(huì)稱之為Monolith),但是微服務(wù)的實(shí)現(xiàn)和實(shí)施思路是更強(qiáng)調(diào)功能趨向單一化的,即服務(wù)單元的小型化和微型化。如圖1是Monolith Service和Microservice,齒輪表示服務(wù)的功能。

圖1 Monolith Service(左)和Microservice(右)
所以從思路與理念上來(lái)說(shuō),微服務(wù)就是提倡盡量將復(fù)雜一點(diǎn)的功能進(jìn)行拆分,把服務(wù)粒度做更小,讓它能夠獨(dú)立承擔(dān)對(duì)外服務(wù)的職責(zé),順著這個(gè)思路開(kāi)發(fā)和交付的軟件服務(wù)就稱為“微服務(wù)”。
提到服務(wù)化和框架,國(guó)內(nèi)大部分研發(fā)者第一印象或許會(huì)直接想到Dubbo這樣的服務(wù)框架。Dubbo是阿里巴巴公司開(kāi)源出來(lái)的SOA服務(wù)化治理方案的核心框架,它是一個(gè)分布式的專注于提供高性能和透明化的RPC遠(yuǎn)程服務(wù)調(diào)用,以及SOA服務(wù)治理的方案。其核心部分包含:
1)遠(yuǎn)程通訊:提供對(duì)多種基于長(zhǎng)連接的NIO框架抽象封裝,包括幾種信息交換方式如,多種線程模型,序列化,以及“請(qǐng)求-響應(yīng)”模式。
2)集群容錯(cuò):提供基于接口方法的透明遠(yuǎn)程過(guò)程調(diào)用,支持多協(xié)議,以及軟負(fù)載均衡,失敗容錯(cuò),地址路由,動(dòng)態(tài)配置等。
3)自動(dòng)發(fā)現(xiàn):基于注冊(cè)中心的目錄服務(wù),主要提供了服務(wù)消費(fèi)方能動(dòng)態(tài)的查找服務(wù)提供方,地址透明,服務(wù)提供方可以平滑增加或減少機(jī)器[5]等幾項(xiàng)功能。
Dubbo的架構(gòu)如圖2所示。

圖2 Duboo架構(gòu)
節(jié)點(diǎn)角色說(shuō)明如下:
1)Provider:暴漏服務(wù)的服務(wù)提供方。
2)Consumer:調(diào)用遠(yuǎn)程服務(wù)的服務(wù)消費(fèi)方。
3)Register:服務(wù)注冊(cè)與發(fā)現(xiàn)的注冊(cè)中心。
4)Monitor:監(jiān)控中心負(fù)責(zé)統(tǒng)計(jì)服務(wù)的調(diào)取次數(shù)和調(diào)取時(shí)間。
5)Container:服務(wù)運(yùn)行容器。
架構(gòu)中各節(jié)點(diǎn)的調(diào)用關(guān)系說(shuō)明如下(與圖2中序號(hào)對(duì)應(yīng)):
2)服務(wù)提供者在容器啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己所提供的服務(wù)。
3)服務(wù)消費(fèi)者在應(yīng)用服務(wù)器啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
4)注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者。
5)在注冊(cè)中心的服務(wù)提供者列表中,服務(wù)消費(fèi)者基于軟負(fù)載均衡算法選擇一個(gè)服務(wù)提供者進(jìn)行調(diào)用,如果調(diào)取失敗,注冊(cè)中心經(jīng)過(guò)負(fù)載均衡算法動(dòng)態(tài)的再次分配給服務(wù)消費(fèi)者另一臺(tái)。
6)監(jiān)控中心每分鐘接受一次來(lái)自內(nèi)存中的統(tǒng)計(jì)數(shù)據(jù),來(lái)記錄服務(wù)提供者和消費(fèi)者的調(diào)用次數(shù)和調(diào)用時(shí)間。
基于以上Dubbo這些核心功能,對(duì)于開(kāi)發(fā)功能趨向單一,數(shù)量眾多,相互調(diào)用的Spring Boot微服務(wù)具有重大意義。Dubbo可以提供以下功能:
Lab顏色模型基于人對(duì)顏色的感覺(jué),其中數(shù)值描述正常視力的人能夠看到的所有顏色.由于不是所有在范圍L∈[0,100],a,b∈[-128,127]中的顏色都與實(shí)際顏色對(duì)應(yīng),所以顏色的量化在RGB空間中進(jìn)行,但是為了與人類感知相符合,在Lab的顏色空間中進(jìn)行空間顏色距離的度量.然后在Lab空間內(nèi),獲取前后景區(qū)域間的顏色距離集合.區(qū)域r1和r2之間的顏色距離dr(r1,r2)被定義為
1)像調(diào)用本地方法一樣透明化的調(diào)用遠(yuǎn)程方法,只需要在配置文件中簡(jiǎn)單注入,沒(méi)有任何API接口侵入。
2)軟負(fù)載均衡及容錯(cuò)機(jī)制,可在內(nèi)網(wǎng)替代F5等硬件負(fù)載均衡器,降低成本,減少單點(diǎn)。
3)Provider提供的服務(wù)動(dòng)態(tài)注冊(cè)和發(fā)現(xiàn),不再須要寫(xiě)死服務(wù)地址,注冊(cè)管理中心基于API名查詢服務(wù)提供者的IP地址,并且能夠平滑添加或刪除服務(wù)提供者[8]。
隨著微服務(wù)理念的盛行,一個(gè)流行的概念也隨之誕生-微框架(Micro Framework),Spring Boot是一個(gè)可使用Java構(gòu)建微服務(wù)的微框架。Spring Boot是Spring框架對(duì)“約定優(yōu)先于配置(Convention Over Configuration)”里面的最佳實(shí)踐的產(chǎn)物,一個(gè)典型的Spring Boot應(yīng)用本質(zhì)上其實(shí)就是一個(gè)基于Spring框架的應(yīng)用,它在Spring之上,構(gòu)建了全新的開(kāi)發(fā)模型,移除了開(kāi)發(fā)Spring應(yīng)用中很多單調(diào)乏味的內(nèi)容[9]。
在Spring體系中,Spring Boot是令人興奮的新項(xiàng)目,它也可能改變軟件開(kāi)發(fā)領(lǐng)域的游戲規(guī)則。它提供了四個(gè)主要的特性,能夠改變開(kāi)發(fā)Spring應(yīng)用程序的方式:
1)Spring Boot Starter:它將軟件項(xiàng)目經(jīng)常用到的依賴進(jìn)行了統(tǒng)一歸并,將其添加到一個(gè)依賴中,然后就可以統(tǒng)一添加到項(xiàng)目的Maven或Gradle構(gòu)建中;
2)自動(dòng)配置:Spring Boot的自動(dòng)配置特性繼承了Spring4對(duì)條件化配置的支持,合理地推測(cè)軟件應(yīng)用所需的bean依賴并動(dòng)態(tài)配置它們;
3)命令行接口(Command-line interface,CLI):Spring Boot的CLI發(fā)揮了Groovy編程語(yǔ)言的優(yōu)勢(shì),并結(jié)合自動(dòng)配置進(jìn)一步簡(jiǎn)化Spring應(yīng)用的開(kāi)發(fā)[10]。
4)Actuator:它為 Spring Boot應(yīng)用添加了一定的管理特性,使監(jiān)控變的簡(jiǎn)單。采用了spring-boot-start-actuator之后,然后直接以rest的方式,獲取線程的運(yùn)行期性能參數(shù)。
如圖3,是Spring Boot應(yīng)用啟動(dòng)步驟的簡(jiǎn)要示意圖,SpringApplication作為Spring Boot程序啟動(dòng)的一站式解決方案,將一個(gè)Spring Boot應(yīng)用啟動(dòng)的流程“模版化”,對(duì)開(kāi)發(fā)基于Spring框架的微服務(wù)更加方便高效。

圖3 Spring Boot應(yīng)用啟動(dòng)步驟示意圖
新建Maven項(xiàng)目 spring-boot-starter-dubbo,將針對(duì)Dubbo框架的依賴以及對(duì)服務(wù)啟動(dòng)類的規(guī)范進(jìn)行封裝,此后,要開(kāi)發(fā)一個(gè)基于Spring Boot的Dubbo服務(wù),只要依賴這一自動(dòng)配置模塊即可。
1)項(xiàng)目 pom.xml中依賴 spring-boot-starter和Dubbo
2)創(chuàng)建ShutdownLatch類,目的是為了阻止Dubbo服務(wù)的進(jìn)程退出(主線程執(zhí)行完畢,無(wú)其他非daemon線程存活)。具體做法是設(shè)置一個(gè)服務(wù)是否關(guān)閉的開(kāi)關(guān),只有當(dāng)外部調(diào)用相應(yīng)管理接口將服務(wù)關(guān)閉之后,再關(guān)閉當(dāng)前的Dubbo服務(wù)。ShutdownLatch部分代碼如下:

3)所有的Spring Boot應(yīng)用啟動(dòng)都是基于標(biāo)準(zhǔn)的SpringApplication.run完成的,為了在啟動(dòng)類執(zhí)行完成后可以阻止Dubbo服務(wù)進(jìn)程的退出,需要在Spring Boot啟動(dòng)類的main函數(shù)最后調(diào)用Shutdown-Latch.await(),但是如果要求每個(gè)開(kāi)發(fā)者在自己的Spring Boot啟動(dòng)類中調(diào)用這段代碼,顯然這并沒(méi)有給開(kāi)發(fā)者的工作帶來(lái)任何簡(jiǎn)化,所以本文選擇使用Spring Boot中的CommandLineRunner來(lái)完成針對(duì)ShutdownLatch.await()的調(diào)用工作,任何注冊(cè)到Spring Boot應(yīng)用的CommandLineRunner都將在SpringApplication.run執(zhí)行完成后再執(zhí)行,恰好符合當(dāng)前場(chǎng)景需要。部分代碼如下:

4)定義一個(gè)JavaConfig類DubboAutoConfiguration,將 DubboServiceLatchCommandLineRunner注冊(cè)到Spring Boot應(yīng)用的容器之中。使用@Order和@Configuration注解標(biāo)注該配置類以保證DubboServiceLatchCommandLineRunner在最后執(zhí)行,以避免阻塞其他邏輯的執(zhí)行
5)要實(shí)現(xiàn)一個(gè)Spring Boot的自動(dòng)配置模塊,需要將上面創(chuàng)建的DubboAutoConfiguration配置類通過(guò)META-INF∕spring.factories配置文件注冊(cè)并發(fā)布。
6)以后開(kāi)發(fā)Dubbo服務(wù)就只需要在服務(wù)的項(xiàng)目依賴中添加spring-boot-starter-dubbo依賴,然后以標(biāo)準(zhǔn)的SpringApplication加載Dubbo服務(wù)的配置并啟動(dòng)就可以了。

圖4 Dubbo構(gòu)建Spring Boot微服務(wù)流程圖
如圖4是基于Dubbo服務(wù)框架構(gòu)建Spring Boot微服務(wù)的整體流程圖。快速構(gòu)建一個(gè)基于Dubbo框架的Spring Boot微服務(wù),在Maven項(xiàng)目的pom.xml文件中依賴本文提出開(kāi)發(fā)的spring-boot-start-dubbo,它是利用Spring Boot體系中原生的CommandLineRunner接口實(shí)現(xiàn)的,可以阻止Dubbo服務(wù)進(jìn)程的退出。
使用Docker進(jìn)行發(fā)布和部署,首先,提供一個(gè)Dockerfile用于描述Docker發(fā)布成品的構(gòu)建過(guò)程,接著使用docker build命令讀取Dockerfile開(kāi)始構(gòu)建一個(gè)Docker的image。有了docker image之后,使用docker push命令將其發(fā)布到一個(gè)Docker的image register,完成部署[15]。
1)部署實(shí)驗(yàn)環(huán)境
采用Dockerfile創(chuàng)建鏡像,使用容器編排工具docker-compose自動(dòng)化創(chuàng)建基于docker容器的dubbo+zookeeper實(shí)驗(yàn)環(huán)境。
將dubbo-master.zip拷貝目標(biāo)機(jī)解壓,如圖5所示。
#mvn clean install-Dmaven.test.skip

圖5 dubbo在目標(biāo)機(jī)解壓
說(shuō)明,如果整體編譯失敗。可以進(jìn)入單個(gè)進(jìn)行編譯,然后在整體編譯。如圖6所示,Dubbo部署成功。
#cd dubbo
#ls

圖6 Duboo編譯成功
2)開(kāi)發(fā)微服務(wù)
新建多個(gè)服務(wù)項(xiàng)目,在Maven項(xiàng)目pom.xml中依賴spring-boot-starter-dubbo,一鍵式化構(gòu)建基于Dubbo框架的Spring Boot微服務(wù)。

圖7 微服務(wù)應(yīng)用

圖8 微服務(wù)API
由圖7和圖8可知,服務(wù)提供者構(gòu)建的多個(gè)Dubbo+Spring Boot微服務(wù),可以成功運(yùn)行,也可以成功被服務(wù)消費(fèi)者調(diào)用。實(shí)驗(yàn)證明,構(gòu)建多個(gè)Dubbo+Spring Boot微服務(wù),具有統(tǒng)一接口。
使用Spring Boot開(kāi)發(fā)具有標(biāo)準(zhǔn)接口的微服務(wù),Maven在服務(wù)開(kāi)發(fā)階段進(jìn)行項(xiàng)目管理和構(gòu)建,Dubbo提供數(shù)量眾多的微服務(wù)之間的相互通信和治理。Maven+Dubbo+Spring Boot的開(kāi)發(fā)模式,使微服務(wù)的開(kāi)發(fā)更加簡(jiǎn)單、邏輯清晰、標(biāo)準(zhǔn)化、規(guī)范化,讓開(kāi)發(fā)人員更關(guān)注業(yè)務(wù)上的功能開(kāi)發(fā),縮短軟件開(kāi)發(fā)生命周期。微服務(wù)在軟件行業(yè)是一個(gè)新的里程碑,使服務(wù)功能模塊化,將一個(gè)大的系統(tǒng)每一個(gè)功能單元進(jìn)行拆分,本文提供了一種基于Spring Boot的標(biāo)準(zhǔn)化的Dubbo服務(wù)開(kāi)發(fā)和實(shí)踐,這對(duì)于海量微服務(wù)的開(kāi)發(fā)和運(yùn)維來(lái)說(shuō)是很重要的。