天天看點

從零寫分布式RPC架構 系列 1.0 (5)整合測試

本篇将對前面幾篇子產品作整合處理,使用spring-boot-starter的形式進行釋出。然後建立 examples 工程子產品對其測試使用。

系列文章:

項目GitHub位址:https://github.com/linshenkx/rpc-netty-spring-boot-starter

從零寫分布式RPC架構 系列 1.0 (1)架構設計

從零寫分布式RPC架構 系列 1.0 (2)RPC-Common子產品設計實作

從零寫分布式RPC架構 系列 1.0 (3)RPC-Server子產品設計實作

從零寫分布式RPC架構 系列 1.0 (4)RPC-Client子產品設計實作

從零寫分布式RPC架構 系列 1.0 (5)整合測試

使用gpg插件釋出jar包到Maven中央倉庫 完整實踐

文章目錄

    • 系列文章:
    • 一 建立spring-boot-starter子產品
    • 二 在主工程添加部署到Maven中央倉庫的配置
    • 三 建立examples工程
    • 四 編寫 rpc-lib 子產品
      • 結構及pom檔案
      • HelloService 接口
    • 五 編寫rpc-provider子產品
      • 結構及pom檔案
      • HelloService實作類
      • application檔案
    • 六 編寫 rpc-consumer 子產品
      • 結構及application檔案
      • HelloController
    • 七 項目測試

一 建立spring-boot-starter子產品

建立RPC-Server和RPC-Client對應的spring-boot-starter子產品如下,隻依賴了對應的spring-boot-autoconfigure,可以将其視為spring-boot-autoconfigure的包裝,兩者的差別還在于一些依賴沒有被傳遞到spring-boot-starter來,不過使用起來沒有差別

從零寫分布式RPC架構 系列 1.0 (5)整合測試

二 在主工程添加部署到Maven中央倉庫的配置

如果隻是想在本地玩玩的話,使用install就好,沒必要deploy,另外如果由于測試過程自動開啟RPC伺服器等待連接配接導緻測試不會結束,可以直接使用

-Dmaven.test.skip=true

跳過測試階段。

在主工程pom檔案中添加如下資訊:developers,scm,licenses,distributionManagement還有相關插件,代碼較多,這裡就不貼出來了。感興趣的也可以直接到GitHub檢視本項目,具體配置方法見使用gpg插件釋出jar包到Maven中央倉庫 完整實踐,該文章即以本項目為例。

三 建立examples工程

建立examples工程,包含3個子產品:

  • rpc-lib

    rpc接口子產品,定義RPC服務提供者和RPC消費者公用的接口規範

  • rpc-provider

    rpc服務提供者子產品,負責服務實作,并對外提供RPC調用服務

  • rpc-consumer

    rpc服務消費者子產品,負責服務消費,通過rpc-lib的契約(接口)向rpc-provider調用服務實作。

主工程pom檔案如下:

  1. spring-cloud-dependencies是spring-cloud的依賴管理子產品,也可以去掉
  2. rpc-lib是rpc-provider和rpc-consumer共同依賴的子產品,是以放在這裡維持版本統一
  3. rpc-netty-server-spring-boot-starter和rpc-netty-client-spring-boot-starter則是我們的項目,也是實作RPC的核心依賴
  4. 最後面我還加上了repository位址,在項目deploy到中央倉庫之前會先加入這個倉庫,是以這個倉庫可以更快拉取的最新發現jar包,對于調試來說就不用再等了,日常使用中可以去掉。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.github.linshenkx.test</groupId>
    <artifactId>rpc-netty-spring-boot-starter-examples</artifactId>
    <version>1.0.5.RELEASE</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
        <spring-boot.version>${project.parent.version}</spring-boot.version>
        <rpc-netty-linshen.version>1.0.5.RELEASE</rpc-netty-linshen.version>
    </properties>

    <modules>
        <module>rpc-lib</module>
        <module>rpc-provider</module>
        <module>rpc-consumer</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--公共rpc子產品-->
            <dependency>
                <groupId>com.github.linshenkx.test</groupId>
                <artifactId>rpc-lib</artifactId>
                <version>${project.version}</version>
            </dependency>
            <!--核心rpc-netty-spring-boot依賴-->
            <dependency>
                <groupId>com.github.linshenkx</groupId>
                <artifactId>rpc-netty-client-spring-boot-starter</artifactId>
                <version>${rpc-netty-linshen.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.linshenkx</groupId>
                <artifactId>rpc-netty-server-spring-boot-starter</artifactId>
                <version>${rpc-netty-linshen.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>sonatype-repository</id>
            <name>sonatype-repository</name>
            <url>https://oss.sonatype.org/content/groups/staging</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>
           

四 編寫 rpc-lib 子產品

該子產品隻提供接口,故無需依賴什麼。

結構及pom檔案

從零寫分布式RPC架構 系列 1.0 (5)整合測試

HelloService 接口

public interface HelloService {
  String say(String name);
}
           

五 編寫rpc-provider子產品

該子產品負責服務提供,這裡我寫了兩個 profile的application配置檔案(slave1和slave2),模拟rpc-provider的叢集。

結構及pom檔案

從零寫分布式RPC架構 系列 1.0 (5)整合測試

HelloService實作類

@RpcService(HelloService.class)
public class HelloServiceImpl implements HelloService {

  @Override
  public String say(String name) {
    return "hello " + name;
  }

}
           

application檔案

如下,application.yml 提供公共配置,各個slave提供個性化配置。預設使用slave1。

另外,需要注意,這裡并沒有指定server.port,也沒有引入spring-web依賴,即該服務不是web服務,使用的是我們自己實作的RPC協定。

如果rpc-provider部署在不同的叢集上,則使用一個aplication.yml即可,這裡因為是僞叢集,是以需要提供profile指定不同端口。

########### application.yml ###############
zk:
  addressList:
    - IP:2181
    - IP:2182
    - IP:2183
  connectTimeOut: 10000
  sessionTimeOut: 10000
  registryPath: "/defaultRegistry"
spring:
  profiles:
    active: slave1
########### application-slave1.yml ###############
rpc:
  server:
    port: 9991
########### application-slave2.yml ###############
rpc:
  server:
    port: 9992
           

六 編寫 rpc-consumer 子產品

該子產品依賴和rpc-provider基本一緻,隻是多了spring-boot-starter-web,application則對應多了server.port。另外需要注意,application不需要指定rpc.server.port,指定了也沒有用,服務位址是依靠服務發現擷取的。

結構及application檔案

從零寫分布式RPC架構 系列 1.0 (5)整合測試

HelloController

這裡我還用了org.springframework.util提供的 計時器 進行服務計時,小小地測試性能。

/**
 * @version V1.0
 * @author: lin_shen
 * @date: 2018/11/1
 * @Description: TODO
 */
@RestController
@Log4j2
public class HelloController {
    @Autowired
    private RpcClient rpcClient;

    @GetMapping("/hello")
    public String sayHello(@RequestParam(defaultValue = "lin") String name){
        StopWatch stopwatch = new StopWatch();
        stopwatch.start();
        HelloService helloService= rpcClient.create(HelloService.class);
        String returnString= helloService.say(name);
        stopwatch.stop();
        log.info("耗時:"+stopwatch.getTotalTimeSeconds()+"seconds");
        return returnString;
    }

}
           

七 項目測試

測試之前應先将公共子產品 rpc-lib install到本地,然後再把整個examples install 到本地。

然後依次啟動 rpc-provider-slave1、rpc-provider-slave2和rpc-consumer

可以根據列印的日志判斷啟動是否符合預期,如下為slave1的啟動資訊

可以看到其服務注冊位址為:/defaultRegistry/com.github.linshenkx.rpclib.HelloService/address-0000000036

自身服務位址為: 192.168.200.1:9991

從零寫分布式RPC架構 系列 1.0 (5)整合測試

這個時候分别打開連結 http://localhost:9090/hello?name=linShen1,http://localhost:9090/hello?name=linShen2,http://localhost:9090/hello?name=linShen3等,可以順利獲得對應的 hello資訊。

另外,檢視兩個slave的控制台輸出,可以發現請求被随機轉發到所有的slave下,即實作了負載均衡(其實算不上,隻是随機選擇而已)。

另外這個項目1.0版本性能較差,根據測試,第一次請求大概耗時11s(需要到ZK叢集擷取服務資訊生成動态代理類,再建立RPC連接配接擷取結果),之後耗時都是5s多。