蚂蚁金服SOFA-Boot整合SOFA-RPC(上篇)

前言

上文介绍了 SOFARPC 的简单使用。在生产环境中,一般会将 SOFARPC 整合到 SpringBoot 中。蚂蚁金服提供了 SOFABoot 框架,SOFABoot 是蚂蚁金服开源的基于 Spring Boot 的研发框架,它在 Spring Boot 的基础上,提供了诸如 Readiness Check,类隔离,日志空间隔离等等能力。php

在加强了 Spring Boot 的同时,SOFABoot 提供了让用户能够在 Spring Boot 中很是方便地使用 SOFA 中间件的能力。当前 SOFABoot 的 2.3.1 版本是基于 Spring Boot 1.4.2.RELEASE 来构建的。java

其余文章

正文

1. 功能描述

SOFABoot 在 Spring Boot 的基础上,提供了如下能力:docker

1.1. 扩展 Spring Boot 的健康检查

在 Spring Boot 健康检查能力的基础上,提供了 Readiness Check 的能力,保证应用实例安全上线。apache

1.2. 日志空间隔离能力

中间件框架自动发现应用的日志实现依赖并独立打印日志,避免中间件和应用日志实现绑定,经过 sofa-common-tools 实现。编程

1.3. 提供类隔离的能力

基于 SOFAArk 框架提供类隔离能力,方便使用者解决各类类冲突问题。json

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 的依赖,以便最后在浏览器中查看效果。

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

本账号将持续分享后端技术干货,包括虚拟机基础,多线程编程,高性能框架,异步、缓存和消息中间件,分布式和微服务,架构学习和进阶等学习资料和文章。

相关文章
相关标签/搜索