

- 
微服務架構 你的整個應用程式將會被拆分成一個個功能獨立的子系統,獨立執行,系統與系統之間透過RPC介面通訊。這樣這些系統之間的耦合度大大降低,你的系統將非常容易擴充套件,團隊協作效率提升了N個檔次。這種架構透過眼下流行的SpringBoot和阿裡巴巴弔炸天的Dubbo框架來實現。 
- 
容器化部署 你的各個微服務將採用目前處於浪潮之巔的Docker來實現容器化部署,避免一切因環境引起的各種問題,讓你們團隊的全部精力集中在業務開發上。 
- 
自動化構建 專案被微服務化後,各個服務之間的關係錯中複雜,打包構建的工作量相當可怕。不過沒關係,本文將藉助Jenkins,幫助你一鍵自動化部署,從此你便告別了加班。 

- 
系統之間的耦合度大大降低,可以獨立開發、獨立部署、獨立測試,系統與系統之間的邊界非常明確,排錯也變得相當容易,開發效率大大提升。 
- 
系統之間的耦合度降低,從而系統更易於擴充套件。我們可以針對性地擴充套件某些服務。假設這個商城要搞一次大促,下單量可能會大大提升,因此我們可以針對性地提升訂單系統、產品系統的節點數量,而對於後臺管理系統、資料分析系統而言,節點數量維持原有水平即可。 
- 
服務的復用性更高。比如,當我們將使用者系統作為單獨的服務後,該公司所有的產品都可以使用該系統作為使用者系統,無需重覆開發。 

- 
基於SpringBoot快速開發 我們將選擇目前熱度很高的SpringBoot,最大限度地降低配置複雜度,把大量的精力投入到我們的業務開發中來。 
- 
基於Dubbo的微服務化 我們會使用阿裡巴巴的開源框架Dubbo,將我們的系統拆分成多個獨立的微服務,然後用Dubbo來管理所有服務的釋出和取用。有了Dubbo之後,呼叫遠端服務就像呼叫一個本地函式一樣簡單,Dubbo會幫我們完成遠端呼叫背後所需要的一切。 
- 
基於Docker的容器化部署 由於使用了微服務架構後,我們的系統將會由很多子系統構成。為了達到多個系統之間環境隔離的目的,我們可以將它們部署在多臺伺服器上,可這樣的成本會比較高,而且每臺伺服器的效能可能都沒有充分利用起來。所以我們很自然地想到了虛擬機器,在同一臺伺服器上執行多個虛擬機器,從而實現環境的隔離,每個虛擬機器上執行獨立的服務。然而虛擬機器的隔離成本依舊很高,因為它需要佔用伺服器較多的硬體資源和軟體資源。所以,在微服務結構下,要實現服務環境的隔離,Docker是最佳選擇。它比虛擬機器更加輕量級,佔用資源較少,而且能夠實現快速部署。 
- 
基於Jenkins的自動化構建 當我們採用了微服務架構後,我們會發現這樣一個問題。整個系統由許許多多的服務構成,這些服務都需要執行在單獨的容器中,那麼每次釋出的複雜度將非常高。首先你要搞清楚這些服務之間的依賴關係、啟動的先後順序,然後再將多個子系統挨個編譯、打包、釋出。這些操作技術難度低,卻又容易出錯。那麼有什麼工具能夠幫助我們解決這些問題呢?答案就是——Jenkins。 它是一款自動化構建的工具,簡單的來說,就是我們只需要在它的介面上按一個按鈕,就可以實現上述一系列複雜的過程。 
- 
產品管理,產品的增刪改查。 
- 
訂單管理,訂單的增刪改查、購物車功能。 
- 
使用者管理,使用者的登入、註冊、許可權管理、收貨地址等等。 
- 
資料分析,提供對本系統資料分析的功能。 
- 
建立一個Maven Project,命名為“Gaoxi”。這個Project由多個Module構成,每個Module對應著“微服務”的一個子系統,可獨立執行,是一個獨立的專案。 這也是目前主流的專案組織形式,即多模組專案。 
- 
在Gaoxi這個專案下建立各個子模組,每個自模組都是一個獨立的SpringBoot專案: Gaoxi-User 使用者服務 Gaoxi-Order 訂單服務 Gaoxi-Product 產品服務 Gaoxi-Analysis 資料分析服務 Gaoxi-Controller 本系統的控制層,和以往三層結構中的Controller層的作用一樣,都是用作請求排程,只不過在微服務架構中,我們將它抽象成一個單獨的系統,可以獨立執行。 Gaoxi-Common-Service-Facade 它處於本系統的最底層,被所有模組依賴,一些公用的類庫都放在這裡。 Gaoxi-Redis 我們將Redis封裝成一個單獨的服務,執行在獨立的容器中,當哪一個模組需要使用Redis的時候,僅需要引入該服務即可,就免去了各種繁瑣的、重覆的配置。而這些配置均在Gaoxi-Redis系統中完成了。  


<groupId>com.gaoxigroupId>
<artifactId>gaoxiartifactId>
<version>0.0.1-SNAPSHOTversion>



<groupId>com.gaoxigroupId>
<artifactId>gaoxi-common-service-facadeartifactId>
<version>0.0.1version>
<packaging>jarpackaging>
<groupId>com.gaoxigroupId>
<artifactId>gaoxi-userartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<modules>
    <module>Gaoxi-Analysismodule>
    <module>Gaoxi-Ordermodule>
    <module>Gaoxi-Productmodule>
    <module>Gaoxi-Usermodule>
    <module>Gaoxi-Redismodule>
    <module>Gaoxi-Controllermodule>
    <module>Gaoxi-Common-Service-Facademodule>
modules>
<parent>
    <groupId>com.gaoxigroupId>
    <artifactId>gaoxiartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <relativePath>../pom.xmlrelativePath>
parent>
<dependencies>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starterartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    
    <dependency>
        <groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
        <version>1.3.1version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <scope>runtimescope>
    dependency>
    
    <dependency>
        <groupId>io.dubbo.springbootgroupId>
        <artifactId>spring-boot-starter-dubboartifactId>
        <version>1.0.0version>
    dependency>
    
    <dependency>
        <groupId>com.gaoxigroupId>
        <artifactId>gaoxi-common-service-facadeartifactId>
        <version>0.0.1version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-aopartifactId>
    dependency>
    
    <dependency>
        <groupId>com.google.guavagroupId>
        <artifactId>guavaartifactId>
        <version>23.3-jreversion>
    dependency>
dependencies>}}}
當父模組的pom中配置了公用依賴後,子模組的pom檔案將非常簡潔,如下所示:
{{{<groupId>com.gaoxigroupId>
<artifactId>gaoxi-userartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<name>gaoxi-username>
<parent>
    <groupId>com.gaoxigroupId>
    <artifactId>gaoxiartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <relativePath>../pom.xmlrelativePath>
parent>
docker pull chaimm/tomcat:1.1
- 
gaoxi-user 
- 
gaoxi-product 
- 
gaoxi-order 
- 
gaoxi-analysis 
- 
gaoxi-controller 
- 
gaoxi-redis 
docker run --name gaoxi-user-1 -p 8082:8080 -v /usr/web/gaoxi-log:/opt/tomcat/gaoxi-log chaimm/tomcat:1.1- 
–name:指定容器的名字 
- 
-p:指定容器的埠對映 -p 8082:8080 表示將容器的8080埠對映到宿主機的8082埠上 
- 
-v:指定容器資料捲的對映 xxx:yyy 表示將容器yyy目錄對映到宿主機的xxx目錄上,從而訪問宿主機的xxx目錄就相當於訪問容器的yyy目錄。 
- 
chaimm/tomcat:1.1:表示容器所對應的映象。 

docker pull chaimm/zookeeper-dubbo:1.0
docker run --name zookeeper-debug -p 2182:2181 -p 10000:8080 chaimm/zookeeper-dubbo:1.0
- 
-p 2182:2181:將容器的2181埠對映到宿主機的2182埠上,該埠是ZooKeeper的埠號。 
- 
-p 10000:8080:將容器的8080埠對映到宿主機的10000埠上,該埠是Dubbo-Admin所在Tomcat的埠號。 

<dependency>
    <groupId>io.dubbo.springbootgroupId>
    <artifactId>spring-boot-starter-dubboartifactId>
    <version>1.0.0version>
dependency>
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 # 服務實現類所在的路徑
@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 # 取用服務的路徑
docker pull docker.io/jenkins/jenkins
docker run --name jenkins -p 10080:8080 docker.io/jenkins/jenkins






<plugin>
    <groupId>org.codehaus.cargogroupId>
    <artifactId>cargo-maven2-pluginartifactId>
    <version>1.6.5version>
    <configuration>
        <container>
            
            <containerId>tomcat8xcontainerId>
            <type>remotetype>
        container>
        <configuration>
            <type>runtimetype>
            <cargo.remote.username>Tomcat的使用者名稱cargo.remote.username>
            <cargo.remote.password>Tomcat的密碼cargo.remote.password>
        configuration>
    configuration>
    <executions>
        <execution>
            <phase>deployphase>
            <goals>
                <goal>redeploygoal>
            goals>
        execution>
    executions>
plugin>


<profiles>
    <profile>
        <id>devid>
        <properties>
            <profileActive>devprofileActive>
        properties>
        <activation>
            <activeByDefault>trueactiveByDefault>
        activation>
    profile>
    <profile>
        <id>testid>
        <properties>
            <profileActive>testprofileActive>
        properties>
    profile>
    <profile>
        <id>prodid>
        <properties>
            <profileActive>prodprofileActive>
        properties>
    profile>
profiles>
<resources>
    <resource>
        
        <directory>src/main/resourcesdirectory>
        <filtering>truefiltering>
        
        <excludes>
            <exclude>application.propertiesexclude>
            <exclude>application-dev.propertiesexclude>
            <exclude>application-test.propertiesexclude>
            <exclude>application-prod.propertiesexclude>
        excludes>
    resource>
    <resource>
        <directory>src/main/resourcesdirectory>
        <filtering>truefiltering>
        
        <includes>
            <include>application.propertiesinclude>
            
            <include>application-${profileActive}.propertiesinclude>
        includes>
    resource>
resources>
<plugin>
    <artifactId>maven-resources-pluginartifactId>
    <version>3.0.2version>
    <configuration>
        <delimiters>
            <delimiter>@delimiter>
        delimiters>
        <useDefaultDelimiters>falseuseDefaultDelimiters>
    configuration>
plugin>

spring.profiles.active=@profileActive@ 
- 
在Gaoxi-User系統中實現登入的業務邏輯,併發布成RPC服務。 
- 
在Gaoxi-Controller中遠端呼叫登入服務,並向前端提供登入的REST介面。 

public interface UserService {
    public UserEntity login(LoginReq loginReq);
}
@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 userEntityList = userDAO.findUsers(userQueryReq);
        // 查詢失敗
        if (CollectionUtils.isEmpty(userEntityList)) {
            throw new CommonBizException(ExpCodeEnum.LOGIN_FAIL);
        }
        // 查詢成功
        return userEntityList.get(0);
    }
}
 @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);
        // 登入成功
        doLoginSuccess(userEntity, httpRsp);
        return Result.newSuccessResult();
    }
}


- 
微服務架構 我們藉助於SpringBoot和Dubbo實現了微服務架構。微服務架構的理念就是將一個原本龐大、複雜的系統,按照業務功能拆分成一個個具有獨立功能、可以獨立執行的子系統,系統之間若有依賴,則透過RPC介面通訊。從而最大限度地降低了系統之間的耦合度,從而更加易於擴充套件、更加易於維護。 
- 
容器化部署 我們藉助於Docker實現了容器化部署。容器能夠幫助我們遮蔽不同環境下的配置問題,使得我們只需要有一個Dockerfile檔案,就可以處處執行。和虛擬機器一樣,Docker也擁有環境隔離的能力,但比虛擬機器更加輕量級,由於每個容器僅僅是一條行程,因此它可以達到秒級的啟動速度。 
- 
自動化構建 我們藉助於Jenkins實現了所有專案的自動化構建與部署。我們只需要點選“立即構建”這個按鈕,Jenkins就可以幫助我們梳理好錯綜複雜的專案依賴關係,準確無誤地完成構建,並將war包傳送到相應的web容器中。在啟動的過程中,Dubbo會掃描當前專案所需要釋出和取用的服務,將所需要釋出的服務釋出到ZooKeeper上,並向ZooKeeper訂閱所需的服務。 有了Jenkins之後,這一切都是自動化完成。也許你並沒有太強烈地感受到Jenkins所帶來的便利。但是你想一想,對於一個具有錯綜複雜的依賴關係的微服務系統而言,如果每個服務的構建都需要你手動完成的話,你很快就會崩潰,你大把的時間將會投入在無聊但又容易出錯的服務構建上。而Jenkins的出現能讓這一切自動化完成。 


 知識星球
知識星球