本文將以原理+實戰的方式,首先對「微服務」相關的概念進行知識點掃盲,而後開始手把手教你搭建這一整套的微服務系統。 前端
https://github.com/bz51/SpringBoot-Dubbo-Docker-Jenkinsjava
這套系統搭建完以後,那可就厲害了:mysql
微服務架構 你的整個應用程序將會被拆分紅一個個功能獨立的子系統,獨立運行,系統與系統之間經過RPC接口通訊。這樣這些系統之間的耦合度大大下降,你的系統將很是容易擴展,團隊協做效率提高了N個檔次。這種架構經過眼下流行的SpringBoot和阿里巴巴吊炸天的Dubbo框架來實現。git
容器化部署 你的各個微服務將採用目前處於浪潮之巔的Docker來實現容器化部署,避免一切因環境引發的各類問題,讓大家團隊的所有精力集中在業務開發上。github
自動化構建 項目被微服務化後,各個服務之間的關係錯中複雜,打包構建的工做量至關可怕。不過不要緊,本文將藉助Jenkins,幫助你一鍵自動化部署,今後你便告別了加班。web
咳咳,敲黑板啦!筆記趕忙記起來,課後我要檢查的!檢查不合格的同窗放學後留下來!redis
微服務一次近幾年至關火,成爲程序猿飯前便後裝逼熱門詞彙,你不對它有所瞭解如何在程序猿裝逼圈子裏混?下面我用最爲通俗易懂的語言介紹它。spring
要講清楚微服務,我先要從一個系統架構的演進過程講起。sql
我想你們最最最熟悉的就是單機結構,一個系統業務量很小的時候全部的代碼都放在一個項目中就行了,而後這個項目部署在一臺服務器上就行了。整個項目全部的服務都由這臺服務器提供。這就是單機結構。 那麼,單機結構有啥缺點呢?我想缺點是顯而易見的,單機的處理能力畢竟是有限的,當你的業務增加到必定程度的時候,單機的硬件資源將沒法知足你的業務需求。此時便出現了集羣模式,往下接着看。docker
集羣模式在程序猿界由各類裝逼解釋,有的讓你根本沒法理解,其實就是一個很簡單的玩意兒,且聽我一一道來。
單機處理到達瓶頸的時候,你就把單機複製幾份,這樣就構成了一個「集羣」。集羣中每臺服務器就叫作這個集羣的一個「節點」,全部節點構成了一個集羣。每一個節點都提供相同的服務,那麼這樣系統的處理能力就至關於提高了好幾倍(有幾個節點就至關於提高了這麼多倍)。
但問題是用戶的請求究竟由哪一個節點來處理呢?最好可以讓此時此刻負載較小的節點來處理,這樣使得每一個節點的壓力都比較平均。要實現這個功能,就須要在全部節點以前增長一個「調度者」的角色,用戶的全部請求都先交給它,而後它根據當前全部節點的負載狀況,決定將這個請求交給哪一個節點處理。這個「調度者」有個牛逼了名字——負載均衡服務器。
集羣結構的好處就是系統擴展很是容易。若是隨着大家系統業務的發展,當前的系統又支撐不住了,那麼給這個集羣再增長節點就好了。可是,當你的業務發展到必定程度的時候,你會發現一個問題——不管怎麼增長節點,貌似整個集羣性能的提高效果並不明顯了。這時候,你就須要使用微服務結構了。
先來對前面的知識點作個總結。 從單機結構到集羣結構,你的代碼基本無須要做任何修改,你要作的僅僅是多部署幾臺服務器,沒太服務器上運行相同的代碼就好了。可是,當你要從集羣結構演進到微服務結構的時候,以前的那套代碼就須要發生較大的改動了。因此對於新系統咱們建議,系統設計之初就採用微服務架構,這樣後期運維的成本更低。但若是一套老系統須要升級成微服務結構的話,那就得對代碼大動干戈了。因此,對於老系統而言,到底是繼續保持集羣模式,仍是升級成微服務架構,這須要大家的架構師深思熟慮、權衡投入產出比。
OK,下面開始介紹所謂的微服務。 微服務就是將一個完整的系統,按照業務功能,拆分紅一個個獨立的子系統,在微服務結構中,每一個子系統就被稱爲「服務」。這些子系統可以獨立運行在web容器中,它們之間經過RPC方式通訊。
舉個例子,假設須要開發一個在線商城。按照微服務的思想,咱們須要按照功能模塊拆分紅多個獨立的服務,如:用戶服務、產品服務、訂單服務、後臺管理服務、數據分析服務等等。這一個個服務都是一個個獨立的項目,能夠獨立運行。若是服務之間有依賴關係,那麼經過RPC方式調用。
這樣的好處有不少:
那麼問題來了,當採用微服務結構後,一個完整的系統可能有不少獨立的子系統組成,當業務量漸漸發展起來以後,而這些子系統之間的關係將錯綜複雜,並且爲了可以針對性地增長某些服務的處理能力,某些服務的背後多是一個集羣模式,由多個節點構成,這無疑大大增長了運維的難度。微服務的想法好是好,但開發、運維的複雜度實在是過高。爲了解決這些問題,阿里巴巴的Dubbo就橫空出世了。
Dubbo是一套微服務系統的協調者,在它這套體系中,一共有三種角色,分別是:服務提供者(下面簡稱提供者)、服務消費者(下面簡稱消費者)、註冊中心。
你在使用的時候須要將Dubbo的jar包引入到你的項目中,也就是每一個服務都要引入Dubbo的jar包。而後當這些服務初始化的時候,Dubbo就會將當前系統須要發佈的服務、以及當前系統的IP和端口號發送給註冊中心,註冊中心便會將其記錄下來。這就是服務發佈的過程。與此同時,也是在系統初始化的時候,Dubbo還會掃描一下當前系統所須要引用的服務,而後向註冊中心請求這些服務所在的IP和端口號。接下來系統就能夠正常運行了。當系統A須要調用系統B的服務的時候,A就會與B創建起一條RPC信道,而後再調用B系統上相應的服務。
這,就是Dubbo的做用。
當咱們使用了微服務架構後,咱們將一個本來完整的系統,按照業務邏輯拆分紅一個個可獨立運行的子系統。爲了下降系統間的耦合度,咱們但願這些子系統可以運行在獨立的環境中,這些環境之間可以相互隔離。
在Docker出現以前,若使用虛擬機來實現運行環境的相互隔離的話成本較高,虛擬機會消耗較多的計算機硬件/軟件資源。Docker不只可以實現運行環境的隔離,並且能極大程度的節約計算機資源,它成爲一種輕量級的「虛擬機」。
當咱們使用微服務架構後,隨着業務的逐漸發展,系統之間的依賴關係會日益複雜,並且各個模塊的構建順序都有所講究。對於一個小型系統來講,也許只有幾個模塊,那麼你每次採用人肉構建的方式也許並不感受麻煩。但隨着系統業務的發展,你的系統之間的依賴關係日益複雜,子系統也逐漸增多,每次構建一下你都要很是當心謹慎,稍有不慎整個服務都沒法正常啓動。並且這些構建的工做很low,但卻須要消耗大量的精力,這無疑下降了開發的效率。不過不要緊,Jenkins就是來幫助你解決這個問題的。
咱們只需在Jenkins中配置好代碼倉庫、各個模塊的構建順序和構建命令,在之後的構建中,只須要點擊「當即構建」按鈕,Jenkins就會自動到你的代碼倉庫中拉取最新的代碼,而後根據你事先配置的構建命令進行構建,最後發佈到指定的容器中運行。你也可讓Jenkins定時檢查代碼倉庫版本的變化,一旦發現變更就自動地開始構建過程,而且讓Jenkins在構建成功後給你發一封郵件。這樣你連「當即構建」的按鈕也不須要按,就能全自動地完成這一切構建過程。
接下來我會帶着你們,以一個在線商城爲例,搭建一套可以自動化部署的微服務框架。這個框架能作以下幾件事情:
本文我以一個你們都很是熟悉的在線商城做爲例子,一步步教你們如何搭建微服務框架,它有以下功能:
注意:本文的IDE使用的是intelliJ IDEA,推薦你們也用這個,用了都說好,用了你就會愛上它。
在動手以前,我先來講一說這一步的目標:
下面開始動手。
New一個Project
選擇Spring Initializr
設置groupId、artifactId、version
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi</artifactId>
<version>0.0.1-SNAPSHOT</version>
複製代碼
在Project上New Module
和剛纔同樣,選擇Spring Initializr,設置groupId、artifactId、version
依次建立好全部的Module,以下圖所示:
目前爲止,模塊之間沒有任何聯繫,下面咱們要經過pom文件來指定它們之間的依賴關係,依賴關係以下圖所示:
此外,爲了簡化各個模塊的配置,咱們將全部模塊的通用依賴放在Project的pom文件中,而後讓全部模塊做爲Project的子模塊。這樣子模塊就能夠從父模塊中繼承全部的依賴,而不須要本身再配置了。
下面開始動手:
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi-common-service-facade</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
複製代碼
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
複製代碼
<modules>
<module>Gaoxi-Analysis</module>
<module>Gaoxi-Order</module>
<module>Gaoxi-Product</module>
<module>Gaoxi-User</module>
<module>Gaoxi-Redis</module>
<module>Gaoxi-Controller</module>
<module>Gaoxi-Common-Service-Facade</module>
</modules>
複製代碼
<parent>
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
複製代碼
到此爲止,模塊的依賴關係配置完畢!但要注意模塊打包的順序。因爲全部模塊都依賴於Gaoxi-Common-Servie-Facade模塊,所以在構建模塊時,首先須要編譯、打包、安裝Gaoxi-Common-Servie-Facade,將它打包進本地倉庫中,這樣上層模塊才能引用到。當該模塊安裝完畢後,再構建上層模塊。不然在構建上層模塊的時候會出現找不到Gaoxi-Common-Servie-Facade中類庫的問題。
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>io.dubbo.springboot</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.0.0</version>
</dependency>
<!-- gaoxi-common-service-facade -->
<dependency>
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi-common-service-facade</artifactId>
<version>0.0.1</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.3-jre</version>
</dependency>
</dependencies>
複製代碼
當父模塊的pom中配置了公用依賴後,子模塊的pom文件將很是簡潔,以下所示:
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>gaoxi-user</name>
<parent>
<groupId>com.gaoxi</groupId>
<artifactId>gaoxi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
複製代碼
當項目的結構搭建完成以後,接下來你須要配置Docker環境,並將這些項目打包進容器中,驗證下是否能正常啓動。
在使用Docker以前,你固然先要安裝Docker,安裝過程較爲簡單,基本上就是傻瓜式操做,這裏就不做過多介紹了,你能夠在Docker的官網下載相應系統的安裝包。 https://www.docker.com/
在微服務架構中,一個完整的系統被拆分紅了多個被稱爲「微服務」的子系統,這些子系統能夠獨立運行在Web容器中。因此咱們須要爲這些系統提供運行的Web容器,這裏咱們選擇你們較爲熟悉的Tomcat。
咱們知道,Tomcat依賴於Java環境,安裝Tomcat以前要進行一系列環境的配置:安裝Java、配置環境變量、安裝Tomcat等等。這些操做仍是有些繁瑣的。不過不要緊,當使用了Docker以後,這些過程均可以垂手可得地完成。
咱們只需從Docker Hub上找到Tomcat的鏡像資源,而後從上面拉取下來就可使用。你可使用Tomcat官方的鏡像,也可使用我發佈在Docker Hub上的Tomcat鏡像。
注意點:推薦使用個人Tomcat鏡像資源chaimm/tomcat,由於這個鏡像中除了配置Tomcat的安裝環境之外,還有一些本項目中要用到的Jenkins相關的配置。
採用以下命令從Docker Hub上拉取鏡像:
docker pull chaimm/tomcat:1.1
複製代碼
簡單解釋下,docker pull是從從Docker Hub上拉取鏡像的命令,後面的chaimm/tomcat是鏡像的名稱,:1.1是鏡像的版本號。目前這個鏡像的最新版本號是1.1,推薦你們拉取這個。
這裏再簡單介紹下「鏡像」和「容器」的關係。 「鏡像」就比如是面向對象中的「類」,「容器」就比如「類」建立的「對象」。在面向對象中,「類」定義了各類屬性,「類」能夠實例化出多個「對象」;而在Docker中,「鏡像」定義了各類配置信息,它能夠實例化出多個「容器」。「容器」就是一臺能夠運行的「虛擬機」。
接下來咱們須要爲全部的微服務建立各自的容器:
以建立gaoxi-user容器爲例,採用以下命令建立容器:
docker run --name gaoxi-user-1 -p 8082:8080 -v /usr/web/gaoxi-log:/opt/tomcat/gaoxi-log chaimm/tomcat:1.1
複製代碼
這條命令執行成功後,你就能夠經過你的IP:8082
訪問到gaoxi-user-1容器的tomcat了。若是你看到了那隻眼熟了貓,那就說明容器啓動成功了!
接下來,你須要按照上面的方法,給剩下幾個系統建立好Tomcat容器。
注意點:這裏要注意的是,你須要給這些Tomcat容器指定不一樣的端口號,防止端口號衝突。固然,在實際開發中,你並不須要將容器的8080端口映射到宿主機上,這裏僅僅是爲了驗證容器是否啓動成功才這麼作的。
Dubbo一共定義了三種角色,分別是:服務提供者、服務消費者、註冊中心。註冊中心是服務提供者和服務消費者的橋樑,服務消費者會在初始化的時候將本身的IP和端口號發送給註冊中心,而服務消費者經過註冊中心知道服務提供者的IP和端口號。
在Dubbo中,註冊中心有多種選擇,Dubbo最爲推薦的即爲ZooKeeper,本文采用ZooKeepeer做爲Dubbo的註冊中心。
建立ZooKeeper容器也較爲簡單,你們能夠直接使用我建立的ZooKeeper鏡像,經過以下命令便可下載鏡像:
docker pull chaimm/zookeeper-dubbo:1.0
複製代碼
該鏡像中不只運行了一個zookeeper,還運行了一個擁有dubbo-admin項目的tomcat。dubbo-admin是Dubbo的一個可視化管理工具,能夠查看服務的發佈和引用的狀況。
使用以下命令啓動容器:
docker run --name zookeeper-debug -p 2182:2181 -p 10000:8080 chaimm/zookeeper-dubbo:1.0
複製代碼
啓動成功後,你就能夠經過你的IP:10000/dubbo-admin-2.8.4/
訪問到Dubbo-Admin,以下圖所示:
<!-- Spring Boot Dubbo 依賴 -->
<dependency>
<groupId>io.dubbo.springboot</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.0.0</version>
</dependency>
複製代碼
假設,咱們須要將Gaoxi-User項目中的UserService發佈成一項RPC服務,供其餘系統遠程調用,那麼咱們究竟該如何藉助Dubbo來實現這一功能呢?
public interface UserService {
public UserEntity login(LoginReq loginReq);
}
複製代碼
@Service(version = "1.0.0")
public class UserServiceImpl implements UserService {
@Override
public UserEntity login(LoginReq loginReq) {
// 具體的實現代碼
}
}
複製代碼
spring.dubbo.application.name=user-provider # 本服務的名稱
spring.dubbo.registry.address=zookeeper://IP:2182 # ZooKeeper所在服務器的IP和端口號
spring.dubbo.protocol.name=dubbo # RPC通訊所採用的協議
spring.dubbo.protocol.port=20883 # 本服務對外暴露的端口號
spring.dubbo.scan=com.gaoxi.user.service # 服務實現類所在的路徑
複製代碼
按照上面配置完成後,當Gaoxi-User系統初始化的時候,就會掃描spring.dubbo.scan所指定的路徑下的@Service註解,該註解標識了須要發佈成RPC服務的類。Dubbo會將這些類的接口信息+本服務器的IP+spring.dubbo.protocol.port所指定的端口號發送給Zookeeper,Zookeeper會將這些信息存儲起來。 這就是服務發佈的過程,下面來看如何引用一項RPC服務。
假設,Gaoxi-Controller須要調用Gaoxi-User 提供的登陸功能,此時它就須要引用UserService這項遠程服務。下面來介紹服務引用的方法。
@RestController
public class UserControllerImpl implements UserController {
@Reference(version = "1.0.0")
private UserService userService;
@Override
public Result login(LoginReq loginReq, HttpServletResponse httpRsp) {
// 登陸鑑權
UserEntity userEntity = userService.login(loginReq);
}
}
複製代碼
spring.dubbo.application.name=controller-consumer # 本服務的名稱
spring.dubbo.registry.address=zookeeper://IP:2182 # zookeeper所在服務器的IP和端口號
spring.dubbo.scan=com.gaoxi # 引用服務的路徑
複製代碼
上述操做完成後,當Gaoxi-Controller初始化的時候,Dubbo就會掃描spring.dubbo.scan所指定的路徑,並找到全部被@Reference修飾的成員變量;而後向Zookeeper請求該服務所在的IP和端口號。當調用userService.login()的時候,Dubbo就會向Gaoxi-User發起請求,完成調用的過程。這個調用過程是一次RPC調用,但做爲程序猿來講,這和調用一個本地函數沒有任何區別,遠程調用的一切都由Dubbo來幫你完成。這就是Dubbo的做用。
Jenkins是一個自動化構建工具,它能夠幫助咱們擺脫繁瑣的部署過程,咱們只須要在一開始配置好構建策略,之後部署只須要一鍵完成。
Jenkins採用Java開發,也須要Java環境,但咱們使用Docker後,一切都採用容器化部署,Jenkins也不例外。
docker pull docker.io/jenkins/jenkins
複製代碼
docker run --name jenkins -p 10080:8080 docker.io/jenkins/jenkins
複製代碼
IP:10080
Jenkins會帶着你進行一系列的初始化設置,你只要跟着它一步步走就好了,比較傻瓜式。接下來咱們要作的是,在Jenkins中爲每個服務建立一個項目,每一個項目中定義了構建的具體流程。因爲咱們將整個項目分紅了6個微服務,因此咱們須要在Jenkins中分別爲這6個服務建立項目。那句開始吧~
點擊頁面左側的「新建」按鈕:
輸入項目名稱gaoxi-user,選擇「構建一個Maven項目」,而後點擊「OK」:
配置Git倉庫 選擇Git,而後輸入本項目Git倉庫的URL,並在Credentials中輸入Git的用戶名和密碼,以下圖所示:
構建觸發器 選擇第一項,以下圖所示:
Pre Step Pre Step會在正式構建前執行,因爲全部項目都依賴於Gaoxi-Common-Service—Facade,所以在項目構建前,須要將它安裝到本地倉庫,而後才能被當前項目正確依賴。 所以,在Pre Step中填寫以下信息:
Build 而後就是正式構建的過程,填寫以下信息便可:
OK,Gaoxi-User的構建過程就配置完成了。當咱們點擊「當即構建」按鈕時,Jenkins首先會從咱們指定的Git倉庫中拉取代碼,而後執行Pre Step中的Maven命令,將Gaoxi-Common-Serivce-Facade打包安裝到本地倉庫。而後執行Build過程,將Gaoxi-User進行編譯打包。 但此時Gaoxi-User仍然只是一個本地war包,並無部署到Tomcat容器中,而咱們採用了容器化部署後,Jenkins服務和Gaoxi-User服務並不在同一個Docker容器中,那麼究竟該如何才能將Jenkins本地編譯好的war包發送到Gaoxi-User容器中呢?這就須要使用Jenkins的一個插件——Deploy Plugin。
下載插件 首先你須要下載Deploy Plugin,下載地址以下: https://wiki.jenkins.io/display/JENKINS/Deploy+Plugin
安裝插件 在系統管理–>插件管理–>高級上傳deploy.hpi進行安裝。
在父項目的pom文件中增長遠程部署插件:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.6.5</version>
<configuration>
<container>
<!-- 指明使用的tomcat服務器版本 -->
<containerId>tomcat8x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<cargo.remote.username>Tomcat的用戶名</cargo.remote.username>
<cargo.remote.password>Tomcat的密碼</cargo.remote.password>
</configuration>
</configuration>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>redeploy</goal>
</goals>
</execution>
</executions>
</plugin>
複製代碼
注意:若是你使用了chaimm/tomcat鏡像,那麼其中Tomcat配置都已經完成,默認用戶名:admin、默認密碼:jishimen2019。強烈建議修改用戶名和密碼。
在實際開發中,咱們的系統每每有多套環境構成,如:開發環境、測試環境、預發環境、生產環境。而不一樣環境的配置各不相同。若是咱們只有一套配置,那麼當系統從一個環境遷移到另外一個環境的時候,就須要經過修改代碼來更換配置,這樣無疑增長了工做的複雜度,並且易於出錯。但好在Maven提供了profile功能,能幫助咱們解決這一個問題。
<profiles>
<profile>
<id>dev</id>
<properties>
<profileActive>dev</profileActive>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<profileActive>test</profileActive>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profileActive>prod</profileActive>
</properties>
</profile>
</profiles>
複製代碼
<resources>
<resource>
<!-- 標識配置文件所在的目錄 -->
<directory>src/main/resources</directory>
<filtering>true</filtering>
<!-- 構建時將這些配置文件全都排除掉 -->
<excludes>
<exclude>application.properties</exclude>
<exclude>application-dev.properties</exclude>
<exclude>application-test.properties</exclude>
<exclude>application-prod.properties</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<!-- 標識構建時所須要的配置文件 -->
<includes>
<include>application.properties</include>
<!-- ${profileActive}這個值會在maven構建時傳入 -->
<include>application-${profileActive}.properties</include>
</includes>
</resource>
</resources>
複製代碼
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
複製代碼
在子項目中建立配置 分別爲dev環境、test環境、prod環境建立三套配置,application.proerpties中存放公用的配置。
在application.properties中添加spring.profiles.active=@profileActive@
spring.profiles.active=@profileActive@
複製代碼
-P test
,在打包的時候-P後面的參數將會做爲@profileActive@的值傳入系統中,從而根據該值打包相應的application-{profileActive}.properties文件。到此爲止,全部準備工做都已經完成,接下來就能夠進入代碼開發階段。下面我以一個例子,帶着你們感覺下有了這套微服務框架後,咱們的開發流程究竟有了哪些改變?下面以開發一個用戶登陸功能爲例,介紹下使用本框架以後開發的流程。
首先須要在Gaoxi-Common-Service-Facade中建立UserService接口,並在其中聲明登陸的抽象函數。
public interface UserService {
public UserEntity login(LoginReq loginReq);
}
複製代碼
PS:爲何要將UserService放在Gaoxi-Common-Service-Facade中? 在這個項目中,Gaoxi-User是UserService服務的提供方,Gaoxi-Controller是UserService服務的引用方。因爲兩者並不在同一個系統中,因此必需要藉助於Dubbo來實現遠程方法調用。而Dubbo發佈服務和引用服務的時候,都是根據服務的接口標識服務的,即服務引用方和發佈方都須要使用服務的接口,所以須要將服務的接口放在全部項目共同依賴的基礎模塊——Gaoxi-Common-Service-Facade中。
而後在Gaoxi-User中開發UserService的實現——UserServiceImpl。 UserServiceImpl上必需要加上Dubbo的@Service註解,從而告訴Dubbo,在本項目初始化的時候須要將這個類發佈成一項服務,供其餘系統調用。
@Service(version = "1.0.0")
@org.springframework.stereotype.Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Override
public UserEntity login(LoginReq loginReq) {
// 校驗參數
checkParam(loginReq);
// 建立用戶查詢請求
UserQueryReq userQueryReq = buildUserQueryReq(loginReq);
// 查詢用戶
List<UserEntity> userEntityList = userDAO.findUsers(userQueryReq);
// 查詢失敗
if (CollectionUtils.isEmpty(userEntityList)) {
throw new CommonBizException(ExpCodeEnum.LOGIN_FAIL);
}
// 查詢成功
return userEntityList.get(0);
}
}
複製代碼
當UserService開發完畢後,接下來Gaoxi-Controller須要引用該服務,並向前端提供一個登陸的REST接口。 若要使用userService中的函數,僅須要在userService上添加@Reference註解,而後就像調用本地函數同樣使用userService便可。Dubbo會幫你找到UserService服務所在的IP和端口號,併發送調用請求。但這一切對於程序猿來講是徹底透明的。
@RestController
public class UserControllerImpl implements UserController {
@Reference(version = "1.0.0")
private UserService userService;
/**
* 登陸
* @param loginReq 登陸請求參數
* @param httpRsp HTTP響應
* @return 登陸是否成功
*/
@GetMapping("/login")
@Override
public Result login(LoginReq loginReq, HttpServletResponse httpRsp) {
// 登陸鑑權
UserEntity userEntity = userService.login(loginReq);
// 登陸成功
doLoginSuccess(userEntity, httpRsp);
return Result.newSuccessResult();
}
}
複製代碼
上面的代碼完成後,接下來你須要將代碼提交至你的Git倉庫。接下來就是自動化部署的過程了。
你須要進入Jenkins,因爲剛纔修改了Gaoxi-User和Gaoxi-Controller的代碼,所以你須要分別構建這兩個項目。 接下來Jenkins會自動從你的Git倉庫中拉取最新的代碼,而後依次執行Pre Step、Build、構建後操做的過程。因爲咱們在Pre Step中設置了編譯Gaoxi-Common-Service-Facade,所以Jenkins首先會將其安裝到本地倉庫;而後再執行Build過程,構建Gaoxi-User,並將其打包成war包。最後將執行「構建後操做」,將war包發佈到相應的tomcat容器中。 至此,整個發佈流程完畢!
當Jenkins構建完成後,咱們能夠登陸Dubbo-Admin查看服務發佈和引用的狀態。
當咱們搜索UserService服務後,能夠看到,該服務的提供者已經成功發佈了服務:
點擊「消費者」咱們能夠看到,該服務已經被controller-consumer成功訂閱:
總結一下,這套框架有以下優點:
微服務架構 咱們藉助於SpringBoot和Dubbo實現了微服務架構。微服務架構的理念就是將一個本來龐大、複雜的系統,按照業務功能拆分紅一個個具備獨立功能、能夠獨立運行的子系統,系統之間如有依賴,則經過RPC接口通訊。從而最大限度地下降了系統之間的耦合度,從而更加易於擴展、更加易於維護。
容器化部署 咱們藉助於Docker實現了容器化部署。容器可以幫助咱們屏蔽不一樣環境下的配置問題,使得咱們只須要有一個Dockerfile文件,就能夠到處運行。和虛擬機同樣,Docker也擁有環境隔離的能力,但比虛擬機更加輕量級,因爲每一個容器僅僅是一條進程,所以它能夠達到秒級的啓動速度。
自動化構建 咱們藉助於Jenkins實現了全部項目的自動化構建與部署。咱們只須要點擊「當即構建」這個按鈕,Jenkins就能夠幫助咱們梳理好錯綜複雜的項目依賴關係,準確無誤地完成構建,並將war包發送到相應的web容器中。在啓動的過程當中,Dubbo會掃描當前項目所須要發佈和引用的服務,將所須要發佈的服務發佈到ZooKeeper上,並向ZooKeeper訂閱所需的服務。 有了Jenkins以後,這一切都是自動化完成。也許你並無太強烈地感覺到Jenkins所帶來的便利。可是你想想,對於一個具備錯綜複雜的依賴關係的微服務系統而言,若是每一個服務的構建都須要你手動完成的話,你很快就會崩潰,你大把的時間將會投入在無聊但又容易出錯的服務構建上。而Jenkins的出現能讓這一切自動化完成。