概述
下图是一个典型的微服务架构图。业务系统被拆分成基础服务和业务中台,基础服务支撑业务中台,业务中台暴露RESTful API
向外提供服务。客户端和中台服务之间通常还有网关层、负载均衡层等等。
随着 Spring Cloud Alibaba
的横空出世,以及 Spring Cloud Netflix
的没落,微服务技术选型已经发生重大改变。Netflix
解决方案中的五大组件:Eureka、Ribbon、Feign、Zuul、Config很可能都将退出历史舞台。Alibaba
解决方案中也包含了非常强大的微服务五大组件:Nacos、Dubbo、Sentinel、Seata、RocketMQ,其中Nacos可以替代Netflix
的 Eureka 和 Config,Dubbo 可以替代 Netflix
的Ribbon和Feign,就连Netflix
仅存的全村希望Zuul组件,也因为内部矛盾迟迟出不来Zuul2.0,Spring Cloud
官方最终“忍无可忍”自己搞了个网关组件Spring Cloud Gateway
。至此Netflix
基本全军覆没,可以说已经是GG思密达了(T﹏T)。
现在微服务技术选型中,服务间通信框架基本上就是在OpenFeign
和Dubbo
之间二选一,Dubbo
除了学习成本较高之外,无论是在性能、扩展性、集群容错、功能集方面都完爆OpenFeign
。
比较内容 | Dubbo | OpenFeign |
---|---|---|
网络传输 | TCP | HTTP |
序列化性能 | hession | json |
学习成本 | 较高 | 较低 |
稳定性 | 较高 | 较高 |
扩展性 | 较高 | 较低 |
集群容错 | 良好 | 一般 |
功能集 | 强大 | 完整 |
Dubbo整合SpringCloud
下面我们来学习一下如何使用Dubbo整合SpringCloud,创建三个微服务order-service
、user-service
和payment-service
,其中user-service
和order-service
相互依赖,paymnent-service
则同时依赖user-service
和order-service
,服务的注册和发现使用Nacos
。
如果读者朋友们对Nacos
还不了解可以先阅读下面的Nacos
系列文章:
Spring Cloud Alibaba 教程 | Nacos(一)
Spring Cloud Alibaba 教程 | Nacos(二)
Spring Cloud Alibaba 教程 | Nacos(三)
Spring Cloud Alibaba 教程 | Nacos(四)
Spring Cloud Alibaba 教程 | Nacos(五)
Spring Cloud Alibaba 教程 | Nacos(六)
本次整合样例中各组件的版本为:
组件 | 版本号 |
---|---|
spring-cloud | Hoxton.SR1 |
spring-boot | 2.2.2.RELEASE |
spring-cloud-alibaba | 2.2.0.RELEASE |
dubbo | 2.7.5 |
dubbo-spring-boot | 2.7.5 |
代码为红色方框部分,api结尾模块放置服务暴露的接口和实体类。
我们来看下boot-order-service
模块的pom.xml
文件内容:
<dependencies>
<!--远程服务接口包-->
<dependency>
<groupId>com.luke.dubbo</groupId>
<artifactId>boot-order-service-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.luke.dubbo</groupId>
<artifactId>boot-user-service-api</artifactId>
<version>1.0</version>
</dependency>
<!--boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<!-- Dubbo Spring Cloud Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- Spring Cloud Nacos Service Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
bootstrap.yml
文件内容:
server:
port: 8081
#Dubbo配置
dubbo:
scan:
base-packages: com.luke.cloud.order
#Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service
#即扫码远程接口实现类
consumer:
check: false #作为消费者时启动不检查
generic: false #是否缺省泛化接口,默认false
protocol:
name: dubbo #使用dubbo协议
# port: ${random.int[25000,65000]}
port: 18081 #使用固定端口
heartbeat: 3000 #长连接心跳间隔,用于帮助检测连接是否已经端口
registry:
address: spring-cloud://192.168.0.149 #挂载到 Spring Cloud 注册中心
cloud:
subscribed-services: boot-user-service #作为消费者订阅的服务,订阅多应用,使用 "," 分割
spring:
application:
name: boot-order-service #The default value of dubbo.application.name is ${spring.application.name}
main:
allow-bean-definition-overriding: true #后发现的bean会覆盖之前相同名称的bean
cloud:
nacos:
discovery:
server-addr: 192.168.0.149:8848 #nacos注册中心
config:
server-addr: 192.168.0.149:8848 #nacos配置中心
file-extension: yml
logging:
level:
root: info #日志级别
配置项都做了详细的注释说明,有两个需要注意的地方,第一个是建议将 dubbo.protocol.port
配置项写成固定值,不要使用随机值,否则服务间出现网络波动或者重启导致端口发生变化时会不断爆出重连失败异常(仍然不断试图重连之前的端口)。第二个是当服务即作为生产者又作为消费者时,需要将配置项 dubbo.consumer.check
置为 false
,关闭启动检查。
主类 BootOrderServiceApp
内容:
@EnableDiscoveryClient//开启注册中心客户端
@SpringBootApplication
public class BootOrderServiceApp {
public static void main(String[] args) {
SpringApplication.run(BootOrderServiceApp.class,args);
}
}
查看业务类 OrderBisServiceImpl
代码:
@Slf4j
@Service //spring的@Service
@org.apache.dubbo.config.
annotation.Service(interfaceClass
= RemoteOrderService.class)//Dubbo的@Service
public class OrderBisServiceImpl implements OrderBisService,RemoteOrderService {
@Reference //使用Dubbo的@Reference注解引用远程服务接口(依赖user-service服务接口api包)
RemoteUserService remoteUserService;
@Override
public String bizEcho(String message) {
log.info("bizEcho:{}",message);
return remoteUserService.echo(message);
}
@Override
public String echo(String message) {
log.info("echo:{}",message);
return "hello,"+message;
}
}
这里有个问题可以思考一下,对于远程接口 RemoteOrderService
,不仅是 order-service
服务向外暴露的远程接口,同时也可能是服务自身需要使用到的本地接口,所以 RemoteOrderService
同时又是 order-service
自身的业务接口类。
public interface RemoteOrderService {
String echo(String message);
}
使用 @Reference
注解RemoteUserService
之后,即可像使用本地接口一样使用它。Dubbo框架对用户完全屏蔽了底层的远程调用过程。
控制层 OrderController
代码:
@RestController
@RequestMapping("/order")
public class OrderController {
@Reference
RemoteUserService userService;
@Autowired
private OrderBisService orderBisService;
@GetMapping("/orderCallUser")
@ResponseBody
public String orderCallUser(@RequestParam("message") String message){
return userService.echo(message);
}
@GetMapping("/bizEcho")
@ResponseBody
public String bizEcho(@RequestParam("message") String message){
return orderBisService.bizEcho(message);
}
}
这部分代码比较简单,全部是 SpringMVC
相关的内容,不再展开说明。使用了 Dubbo
整合 SpringCloud
之后,服务间的调用使用了 Dubbo
协议,同时自身又可以向外暴露RESTful API
,通过网关路由之后向外提供 HTTP
远程调用服务,这是非常典型的微服务通信模型。
观察启动日志
其他的两个服务 user-service
和 payment-service
代码类似就不再展开讲解。下面我们分别启动这三个服务(启动顺序无所谓),观察一下他们的启动日志。
三个服务的TCP服务端口号分别为:
- order-service:18081
- user-service:18082
- payment-service:18083
根据前面介绍过的三个服务之间的依赖关系,我们可以从启动日志看到他们底层之间建立的TCP连接关系。
order-service
一共有三个连接,其中有两个连接的目标地址端口是18081
,分别是user-service
和payment-service
对order-service
发起的连接。第三个目标地址端口是18082
,是服务自身发起对order-service
的连接。
user-service
user-service
服务的依赖关系和 order-service
类似,前面一个是服务自身发起对 order-service
的连接,后面两个是 order-service
和 payment-service
发起对user-service
的连接。
payment-service
payment-service
服务依赖 user-service
和 order-service
,所以发起了目标地址端口为18081
和18082
的两个连接。
测试结果
1、请求地址:http://localhost:8081/order/orderCallUser?message=luke
2、请求地址:http://localhost:8082/user/userCallOrder?message=luke
3、请求地址:http://localhost:8083/payment/pay?message=666
4、请求地址:http://localhost:8081/order/bizEcho?message=xxx
测试结果达到预期,请求可以正常访问。
关注公众号回复”Dubbo“或者"dubbo"即可获取本样例工程下载地址。