螞蟻金服SOFA-Boot整合SOFA-RPC(上篇)

零壹技術棧發表於2018-08-30

前言

上文介紹了 SOFARPC 的簡單使用。在生產環境中,通常會將 SOFARPC 整合到 SpringBoot 中。螞蟻金服提供了 SOFABoot 框架,SOFABoot 是螞蟻金服開源的基於 Spring Boot 的研發框架,它在 Spring Boot 的基礎上,提供了諸如 Readiness Check,類隔離,日誌空間隔離等等能力。

螞蟻金服SOFA-Boot整合SOFA-RPC(上篇)

在增強了 Spring Boot 的同時,SOFABoot 提供了讓使用者可以在 Spring Boot 中非常方便地使用 SOFA 中介軟體的能力。當前 SOFABoot 的 2.3.1 版本是基於 Spring Boot 1.4.2.RELEASE 來構建的。

其他文章

正文

1. 功能描述

SOFABoot 在 Spring Boot 的基礎上,提供了以下能力:

1.1. 擴充套件 Spring Boot 的健康檢查

在 Spring Boot 健康檢查能力的基礎上,提供了 Readiness Check 的能力,保證應用例項安全上線。

1.2. 日誌空間隔離能力

中介軟體框架自動發現應用的日誌實現依賴並獨立列印日誌,避免中介軟體和應用日誌實現繫結,通過 sofa-common-tools 實現。

1.3. 提供類隔離的能力

基於 SOFAArk 框架提供類隔離能力,方便使用者解決各種類衝突問題。

1.4. 中介軟體的整合管理

統一管控、提供中介軟體統一易用的程式設計介面、每一個 SOFA 中介軟體都是獨立可插拔的元件。

1.5. 完全相容 Spring Boot

SOFABoot 基於 Spring Boot 的基礎上進行構建,並且完全相容 Spring Boot。

2. 快速開始

2.1. 環境準備

要使用 SOFABoot,需要先準備好基礎環境,SOFABoot 依賴以下環境:

  • JDK7 或 JDK8
  • 需要採用 Apache Maven 3.2.5 或者以上的版本來編譯

2.2. 建立工程

SOFABoot 是直接構建在 Spring Boot 之上,因此可以使用 Spring Boot 的工程生成工具來生成。新增一個 Web 的依賴,以便最後在瀏覽器中檢視效果。

螞蟻金服SOFA-Boot整合SOFA-RPC(上篇)

2.3. 引入 SOFABoot

在建立好一個 Spring Boot 的工程之後,接下來就需要引入 SOFABoot 的依賴。首先,需要將上文中生成的 Spring Boot 工程的 zip 包解壓後,修改 maven 專案的配置檔案 pom.xml。

替換 spring-boot-starter-parent 為相應版本的 sofaboot-dependencies,例如:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath/>
</parent>
複製程式碼

替換為:

<parent>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>sofaboot-dependencies</artifactId>
    <version>2.3.1</version>
</parent>
複製程式碼

2.4. SOFABoot 健康檢查

引入相關依賴

新增 SOFABoot 健康檢查擴充套件能力的依賴:

<dependency>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>healthcheck-sofa-boot-starter</artifactId>
</dependency>
複製程式碼

最後,在工程的 application.properties 檔案下新增一個 SOFABoot 必須要使用的引數。

# Application Name
spring.application.name=SOFABoot Example
# logging path
logging.path=./logs
複製程式碼

執行 main() 方法,專案啟動以後,控制檯的日誌輸出如下:

2018-05-09 09:56:48.305  INFO 15097 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2018-05-09 09:56:48.309  INFO 15097 --- [           main] c.o.s.r.e.SofaBootExampleApplication     : Started SofaBootExampleApplication in 2.551 seconds (JVM running for 3.046)
2018-05-09 09:57:46.005  INFO 15097 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-05-09 09:57:46.005  INFO 15097 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2018-05-09 09:57:46.021  INFO 15097 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 16 ms
複製程式碼

檢視健康狀態

[
  {
    "GroupId": "com.alipay.sofa",
    "Doc-Url": "https://github.com/alipay/sofa-boot",
    "ArtifactId": "infra-sofa-boot-starter",
    "Bulit-Time": "2018-04-18T22:19:09+0800",
    "Commit-Time": "2018-04-18T22:07:52+0800",
    "Commit-Id": "466f0e039b250ff7b201dc693eec7fa07eb21ad7",
    "Version": "2.3.1"
  }
]
複製程式碼
{
  "status": "UP",
  "sofaBootComponentHealthCheckInfo": {
    "status": "UP"
  },
  "springContextHealthCheckInfo": {
    "status": "UP"
  },
  "DiskSpaceHealthIndicator": {
    "status": "UP",
    "total": 250790436864,
    "free": 208612020224,
    "threshold": 10485760
  }
}
複製程式碼

status: "UP" 表示應用 Readiness Check 的就緒狀態是健康的。

  • 在瀏覽器中輸入 http://localhost:8080/health 來檢視應用的執行時健康狀態(可能會隨著時間發生變化,Spring Boot原生自帶功能)。
{
  "status": "UP",
  "sofaBootComponentHealthCheckInfo": {
    "status": "UP",
    "Middleware": {
      
    }
  },
  "springContextHealthCheckInfo": {
    "status": "UP"
  },
  "diskSpace": {
    "status": "UP",
    "total": 250790436864,
    "free": 208612528128,
    "threshold": 10485760
  }
}
複製程式碼

檢視日誌

在上面的 application.properties 裡面,我們配置的日誌列印目錄是 ./logs 即當前應用的根目錄(我們可以根據自己的實踐需要配置),在當前工程的根目錄下可以看到類似如下結構的日誌檔案:

./logs
├── health-check
│   ├── sofaboot-common-default.log
│   └── sofaboot-common-error.log
├── infra
│   ├── common-default.log
│   └── common-error.log
└── spring.log

複製程式碼

如果應用啟動失敗或者健康檢查返回失敗,可以通過相應的日誌檔案找到錯誤的原因,有些需要關注 common-error.log 日誌。

2.5. SOFA-RPC 環境準備

引入相關依賴

SOFABoot 使用一系列字尾為 -sofa-boot-starter 來標示一箇中介軟體服務,如果想要使用某個中介軟體,直接新增對應的依賴即可。進一步引入 SOFA-RPC 的 starter 依賴:

<dependency>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>rpc-sofa-boot-starter</artifactId>
</dependency>
複製程式碼

選擇 Zookeeper 作為服務註冊列表,在 pom.xml 檔案中引入相關依賴:

<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
    <version>0.10</version>
</dependency>
複製程式碼

注意將 zkclient 重複的依賴排除在外,以免引起衝突。

配置 zookeeper 叢集

在 application.properties 中進一步配置 zookeeper 的地址資訊。

# zookeeper address list
com.alipay.sofa.rpc.registry.address=zookeeper://127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183?file=/home/admin/registry
複製程式碼

為了方便起見,本地使用 docker 環境對 zookeeper 叢集進行容器編排。多個 zookeeper 節點通過逗號分隔,file 引數指定當 zookeeper 不可用時,可以利用本地快取檔案進行服務發現。

編寫 docker-compose.yml 檔案如下:

version: '2'
services:
  zoo1:
    image: zookeeper:latest
    restart: always
    hostname: zoo1
    ports:
      - 2181:2181
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
  zoo2:
    image: zookeeper:latest
    restart: always
    hostname: zoo2
    ports:
      - 2182:2181
    environment:
      ZOO_MY_ID: 2
      ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888 server.3=zoo3:2888:3888
  zoo3:
    image: zookeeper:latest
    restart: always
    hostname: zoo3
    ports:
      - 2183:2181
    environment:
      ZOO_MY_ID: 3
      ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=0.0.0.0:2888:3888
複製程式碼

進入 docker-compose.yml 所在檔案目錄, 執行 docker-compose up -d 啟動3臺 zookeeper 容器。啟動完成後,執行 docker-compose ps 檢視程式狀態如下:

$ docker-compose ps
      Name                    Command               State                     Ports                   
------------------------------------------------------------------------------------------------------
zookeeper_zoo1_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2181->2181/tcp, 2888/tcp, 3888/tcp
zookeeper_zoo2_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2182->2181/tcp, 2888/tcp, 3888/tcp
zookeeper_zoo3_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2183->2181/tcp, 2888/tcp, 3888/tcp
複製程式碼

zookeeper 容器叢集啟動完成,如果想要檢視叢集 leader,可以執行 docker exec -it [container-id] /bin/bash 進入容器執行 zkServer.sh status 逐一檢視。這裡加以不累述!

XSD管理

在要使用的 XML 配置檔案中將頭部 xsd 檔案的宣告設定為如下,這樣就能夠使用 SOFABoot 定義的 XML 元素進行開發。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sofa="http://sofastack.io/schema/sofaboot"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://sofastack.io/schema/sofaboot   http://sofastack.io/schema/sofaboot.xsd"
       default-autowire="byName">
複製程式碼

2.6. SOFA-Boot 整合 SOFA-RPC

編寫服務介面和實現類

HelloSyncService.java

public interface HelloSyncService {
    String saySync(String string);
}
複製程式碼

HelloSyncServiceImpl.java

public class HelloSyncServiceImpl implements HelloSyncService {
    @Override
    public String saySync(String sync) {
        return sync;
    }
}
複製程式碼

編寫服務提供方配置檔案

simple-server-example.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sofa="http://sofastack.io/schema/sofaboot"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd"
       default-autowire="byName">
    <bean id="helloSyncServiceImpl" class="com.ostenant.sofa.rpc.example.simple.HelloSyncServiceImpl"/>

    <!-- 以多種通訊協議釋出服務 -->
    <sofa:service ref="helloSyncServiceImpl" interface="com.ostenant.sofa.rpc.example.simple.HelloSyncService">
        <sofa:binding.bolt/>
        <sofa:binding.rest/>
        <sofa:binding.dubbo/>
    </sofa:service>
</beans>
複製程式碼

通過 sofa:service 元素將該服務釋出,其中 ref 屬性表示釋出的服務例項,interface 屬性表示該服務的介面。

  • sofa:binding.bolt: 服務通過 bolt 協協議通道釋出,底層基於 Netty 實現。
  • sofa:binding.rest: 服務通過 http 協議釋出。
  • sofa:binding.dubbo: 服務基於 dubbo 的協議通道釋出。

編寫服務提供方啟動程式

SimpleServerApplication.java

@ImportResource({ "classpath:simple-server-example.xml" })
@SpringBootApplication
public class SimpleServerApplication {

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SimpleServerApplication.class);
        ApplicationContext applicationContext = springApplication.run(args);
    }
}
複製程式碼

編寫服務消費方配置檔案

simple-client-example.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sofa="http://sofastack.io/schema/sofaboot"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd"
       default-autowire="byName">

    <!-- bolt引用 -->
    <sofa:reference id="boltHelloSyncServiceReference" interface="com.ostenant.sofa.rpc.example.simple.HelloSyncService">
        <sofa:binding.bolt/>
    </sofa:reference>

    <!-- rest引用 -->
    <sofa:reference id="restHelloSyncServiceReference" interface="com.ostenant.sofa.rpc.example.simple.HelloSyncService">
        <sofa:binding.rest/>
    </sofa:reference>

    <!-- dubbo引用 -->
    <sofa:reference id="dubboHelloSyncServiceReference" interface="com.ostenant.sofa.rpc.example.simple.HelloSyncService">
        <sofa:binding.dubbo/>
    </sofa:reference>
</beans>
複製程式碼

編寫服務提供方啟動程式

SimpleClientApplication.java

@ImportResource({ "classpath:simple-client-example.xml" })
@SpringBootApplication
public class SimpleClientApplication {

    public static void main(String[] args) {
        System.setProperty("server.port", "8081");
        SpringApplication springApplication = new SpringApplication(SimpleClientApplication.class);
        ApplicationContext applicationContext = springApplication.run(args);

        HelloSyncService boltHelloSyncService = (HelloSyncService) applicationContext.getBean("boltHelloSyncServiceReference");
        HelloSyncService restHelloSyncService = (HelloSyncService) applicationContext.getBean("restHelloSyncServiceReference");
        HelloSyncService dubboHelloSyncService = (HelloSyncService) applicationContext.getBean("dubboHelloSyncServiceReference");

        System.out.println("Bolt result:" + boltHelloSyncService.saySync("bolt"));
        System.out.println("Rest result:" + restHelloSyncService.saySync("rest"));
        System.out.println("Dubbo result:" + dubboHelloSyncService.saySync("dubbo"));
    }
}
複製程式碼

分別啟動服務端和客戶端

客戶端控制檯輸出日誌如下:

Bolt result: bolt
Rest result: rest
Dubbo result: dubbo
複製程式碼

對於同一個服務,在服務釋出方配置時,可在以 sofa:service 中通過 sofa:binding.xxx 提供多種協議通道配置;在服務消費方配置時,可以在 sofa:reference 中通過 sofa:binding.xxx 提供對不同通道服務的引用。

小結

本文引入了 SOFA-Boot 框架,對 SOFA-Boot 的將康檢查功能和日誌管理的使用進行了簡單說明,然後在 SOFA-Boot 環境中引入了 SOFA-RPC 框架,並提供了一個完整的服務釋出和註冊的示例程式。

關於 SOFA-RPC 更豐富、強大的功能介紹,下篇敬請期待!


歡迎關注技術公眾號: 零壹技術棧

image

本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。

相關文章