前言
上文介绍了 SOFARPC 的简单使用。在生产环境中,通常会将 SOFARPC 整合到 SpringBoot 中。蚂蚁金服提供了 SOFABoot 框架,SOFABoot 是蚂蚁金服开源的基于 Spring Boot 的研发框架,它在 Spring Boot 的基础上,提供了诸如 Readiness Check,类隔离,日志空间隔离等等能力。
image在增强了 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 的依赖,以便最后在浏览器中查看效果。
image2.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 必须要使用的参数。
- spring.application.name:用于标示当前应用的名称
- logging path:用于指定日志的输出目录
# 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
查看健康状态
- 在浏览器中输入 http://localhost:8080/sofaboot/versions 来查看当前 SOFABoot 中使用 Maven 插件生成的版本信息汇总,结果类似如下:
[
{
"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"
}
]
- 在浏览器中输入 http://localhost:8080/health/readiness 查看应用 Readiness Check 的状况,类似如下:
{
"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本帐号将持续分享后端技术干货,包括虚拟机基础,多线程编程,高性能框架,异步、缓存和消息中间件,分布式和微服务,架构学习和进阶等学习资料和文章。
网友评论