文章目录
- 一、Dubbo简介
- 二、SSM项目整合Dubbo
- 1.生产者方配置
- 2.消费者方配置
- 三、Spring Boot 项目整合Dubbo
- 1.生产者方配置
- 2.消费者方配置
- 四、应用案例
- 五、Dubbo配置的优先级别
- 1. 方法级配置(Highest Priority)
- 2. 接口级配置
- 3. 消费者/提供者级配置
- 4. 全局配置
- 六、Dubbo超时时间和重试
- 七、设置本地存根
- 八、整合Hystrix
- 总结
一、Dubbo简介
Dubbo 是一个RPC(远程过程调用)
服务框架:
- 服务注册与发现:Dubbo 提供内置的注册中心(如 Zookeeper 等),服务提供者注册服务,消费者动态发现服务。
- 高效的远程调用:通过支持多种通信协议(默认 Dubbo 协议),实现快速、可靠的远程方法调用。
- 负载均衡:提供多种负载均衡策略,如随机、轮询、一致性哈希等,保证服务调用的高效性和稳定性。
- 服务治理:包括限流、降级、熔断、动态路由等功能,提升系统稳定性和灵活性。
- 扩展性强:采用模块化设计,用户可以根据需求定制和扩展功能。
Dubbo主要由以下五部分组成:
- Provider(服务提供者):提供服务的应用。
- Consumer(服务消费者):调用服务的应用。
- Registry(注册中心):管理服务的注册与发现。
- Monitor(监控中心):监控服务的调用性能。
- Protocol(协议层):定义服务调用的规则和数据传输方式。
常见的远程调用工具,除了Dubbo还有Open Feign,HttpClient等,那么Dubbo和Open Feign有什么区别?
- 框架定位和设计目标
Dubbo | OpenFeign |
---|---|
分布式服务框架,重点在 服务治理。 | 声明式 HTTP 客户端,主要关注 HTTP 调用。 |
提供端到端的解决方案,包括服务注册发现、负载均衡、服务路由、服务降级等。 | 偏重于与 REST API 的集成,通常依赖 Spring Cloud 生态提供更多功能。 |
支持多种通信协议(如 Dubbo 协议、HTTP、gRPC)。 | 仅支持基于 HTTP 的远程调用。 |
- 通信协议
Dubbo | OpenFeign |
---|---|
支持多种通信协议,默认采用高性能的 Dubbo 协议,基于二进制序列化,通信效率高。 | 仅支持 HTTP,通常基于 JSON 格式的数据交换,性能比二进制协议略低。 |
可以支持 TCP、HTTP、gRPC 等不同的底层传输协议。 | 依赖 HTTP 和 RESTful 风格,灵活性较低。 |
- 注册与发现
Dubbo | OpenFeign |
---|---|
通过注册中心(如 Zookeeper、Nacos)实现动态的服务注册与发现。 | 通常依赖 Spring Cloud 服务注册中心(如 Eureka、Consul)。 |
服务发现、路由完全由 Dubbo 框架管理。 | 需要依赖 Spring Cloud 相关组件完成服务发现。 |
- 负载均衡与服务治理
Dubbo | OpenFeign |
---|---|
内置多种负载均衡算法(如随机、轮询、一致性哈希)。 | 负载均衡通常依赖 Ribbon 或 Spring Cloud LoadBalancer。 |
提供丰富的服务治理功能,如熔断、限流、动态路由等。 | 通常通过 Hystrix、Resilience4j 等第三方库实现。 |
- 性能与适用场景
Dubbo | OpenFeign |
---|---|
性能高,适合 高并发、低延迟的场景(如 RPC 调用)。 | 易用性高,适合 跨服务的 RESTful 调用 场景。 |
偏向于大规模、高性能分布式系统。 | 偏向于 REST 风格 API 的微服务开发。 |
- 扩展性与生态
Dubbo | OpenFeign |
---|---|
自带强大的扩展能力,可以通过 SPI 自定义组件,如协议、序列化机制等。 | 集成简单,主要依赖 Spring Cloud 生态,与其他组件兼容性好。 |
社区活跃度较高,但主要适用于阿里系生态。 | 社区支持广泛,与 Spring Cloud 微服务结合更紧密。 |
二、SSM项目整合Dubbo
无论是生产者方,消费者方,首先加入依赖:
<!-- dubbo-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- zookeeper-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.10.0</version>
</dependency>
1.生产者方配置
resource
目录下编写provider.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:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
<dubbo:application name="user-service-provider"></dubbo:application>
<!-- 2、指定注册中心的位置 在本案例中使用的是zk,也可以使用其他的 -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
<!-- 3、指定通信规则(通信协议?通信端口) -->
<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
<!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<dubbo:service interface="com.atguigu.gmall.service.UserService"
ref="userServiceImpl01" timeout="1000" version="1.0.0">
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:service>
<!-- 服务的实现 -->
<bean id="userServiceImpl01" class="com.light.gmall.service.impl.UserServiceImpl"></bean>
<!--统一设置服务提供方的规则 -->
<dubbo:provider timeout="1000"></dubbo:provider>
<!-- 连接监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor>
</beans>
2.消费者方配置
<?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:dubbo="http://dubbo.apache.org/schema/dubbo"
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://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 扫描消费者的业务类,注册成bean放入容器-->
<context:component-scan base-package="com.light.gmall.service.impl"></context:component-scan>
<dubbo:application name="order-service-consumer"></dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!--声明需要调用的远程服务的接口;生成远程服务代理 -->
<dubbo:reference interface="com.atguigu.gmall.service.UserService"
id="userService" timeout="5000" retries="3" version="*">
</dubbo:reference>
<!-- 配置当前消费者的统一规则:所有的服务都不检查 -->
<dubbo:consumer check="false" timeout="5000"></dubbo:consumer>
<dubbo:monitor protocol="registry"></dubbo:monitor>
</beans>
三、Spring Boot 项目整合Dubbo
同样地,无论是生产者方,消费者方,首先加入依赖,并且启动类上加入@EnableDubbo
注解:
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
1.生产者方配置
dubbo.application.name=user-service-provider #指定当前服务/应用的名字
dubbo.registry.address=127.0.0.1:2181 #指定注册中心的位置
dubbo.registry.protocol=zookeeper #指定注册中心的类型
dubbo.protocol.name=dubbo # 指定通信协议
dubbo.protocol.port=20880 # 指定通信端口
dubbo.monitor.protocol=registry #连接监控中心
暴露服务可以通过@Service
注解实现,该注解是import com.alibaba.dubbo.config.annotation.Service
。并且只能加在类上。
2.消费者方配置
dubbo.application.name=boot-order-service-consumer # 指定当前服务/应用的名字
dubbo.registry.address=zookeeper://127.0.0.1:2181 # 指定注册中心
dubbo.monitor.protocol=registry #连接监控中心
调用生产者方暴露的类的方法,可以在注入目标类时加入@Reference
方法,并且可以指定负载均衡和超时时间等策略:
@Reference(loadbalance="random",timeout=1000) //dubbo直连
UserService userService;
四、应用案例
在本篇的应用中,将所有需要被远程调用的接口,抽取成一个独立的模块进行管理,消费者
和生产者
去依赖该模块:
生产者方:
@Service//暴露服务
@Component
public class UserServiceImpl implements UserService {
@HystrixCommand
@Override
public List<UserAddress> getUserAddressList(String userId) {
// TODO Auto-generated method stub
System.out.println("UserServiceImpl..3.....");
UserAddress address1 = new UserAddress(1, "xxxx", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "yyyy", "1", "王老师", "010-56253825", "N");
if(Math.random()>0.5) {
throw new RuntimeException();
}
return Arrays.asList(address1,address2);
}
}
消费者方:
@Controller
public class OrderController {
@Autowired
OrderService orderService;
@ResponseBody
@RequestMapping("/initOrder")
public List<UserAddress> initOrder(@RequestParam("uid")String userId) {
return orderService.initOrder(userId);
}
}
@Service
public class OrderServiceImpl implements OrderService {
//@Autowired
@Reference(loadbalance="random",timeout=1000) //dubbo直连
UserService userService;
@HystrixCommand(fallbackMethod="hello")
@Override
public List<UserAddress> initOrder(String userId) {
// TODO Auto-generated method stub
System.out.println("用户id:"+userId);
//1、查询用户的收货地址
return userService.getUserAddressList(userId);
}
}
启动Zookeeper和Dubbo-Admin,访问Controller层的路径:
登录Dubbo Admin也可以看到:
五、Dubbo配置的优先级别
总体原则:
环境变量或启动参数的优先级更高:
- 如果通过系统属性(如
-D
参数)或环境变量设置某些配置,它们会覆盖 XML 或注解中的设置。
动态配置的优先级更高:
- Dubbo Admin 提供的动态配置可以在运行时覆盖静态配置,优先级更高。
本地优先于远程:
- 如果本地和远程注册中心(如 Zookeeper)同时有配置,本地配置通常优先生效。
1. 方法级配置(Highest Priority)
- 方法级配置对单个方法生效,优先级最高。
- 主要用于对某些特殊方法的调用行为进行单独优化。
<dubbo:reference id="demoService" interface="com.example.DemoService">
<dubbo:method name="sayHello" timeout="3000" retries="2"/>
</dubbo:reference>
2. 接口级配置
- 通过
<dubbo:reference>
或<dubbo:service>
对整个接口的行为进行配置。 - 优先级低于方法级配置,但高于全局配置。
<dubbo:reference id="demoService" interface="com.example.DemoService" timeout="5000" retries="3"/>
3. 消费者/提供者级配置
- 分别通过
<dubbo:consumer>
或<dubbo:provider>
标签进行配置,针对消费者或提供者应用全局生效。 - 优先级低于接口级配置。
<dubbo:consumer timeout="6000" retries="1"/>
<dubbo:provider timeout="4000"/>
4. 全局配置
- 通过
<dubbo:application>
或<dubbo:registry>
等标签进行全局性配置。 - 优先级最低,提供默认值或全局设置。
<dubbo:application name="demoApplication"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
六、Dubbo超时时间和重试
在Spring Boot项目中,设置超时时间和重试次数,可以通过在服务消费端的 @DubboReference
注解中设置,优先级高于配置文件中的全局配置。
@Reference(loadbalance="random",timeout=1000,retries = 3) //dubbo直连
UserService userService;
可以在配置文件中全局设置:
dubbo:
consumer:
timeout: 5000 # 超时时间,单位为毫秒
retries: 2 # 重试次数
可以在配置文件中单个设置:
dubbo:
consumer:
services:
com.example.MyService:
retries: 1 # 针对某个服务的重试次数
timeout: 3000 # 指定服务的超时时间
上述两段配置是放在消费者方的,如果消费者没有设置,可以在生产者方设置:
dubbo:
provider:
timeout: 5000
retries: 2
如果需要更细粒度控制到接口中的方法级别,则可以:
dubbo:
consumer:
services:
com.example.MyService:
methods:
- name: method1
retries: 0 # method1 不重试
- name: method2
retries: 2 # method2 重试 2 次
演示接口超时:
目前在页面上是直接打印出了报错信息,后续可以通过引入Hystrix
引导到降级逻辑上。
七、设置本地存根
Dubbo 本地存根用于在消费端(Consumer)对服务进行代理或增强,常用于参数校验、缓存、限流等场景。
编写本地存根方法,和接口放在同一个包下:
public class UserServiceStub implements UserService{
private final UserService userService;
public UserServiceStub(UserService userService) {
this.userService = userService;
}
/**
* 按照用户id返回所有的收货地址
*
* @param userId
* @return
*/
@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("进入本地存根方法....");
return userService.getUserAddressList(userId);
}
}
在消费者方的@Reference
注解上加入stub = "存根类的全路径"
,重新访问接口:
八、整合Hystrix
在生产者方和消费者方同时引入依赖,并且在启动类上加入@EnableHystrix
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>
spring-cloud-starter-netflix-hystrix
</artifactId>
</dependency>
生产者方对外暴露的方法上加入@HystrixCommand
注解:
消费者方同样加上注解,并且指定触发降级后的逻辑:@HystrixCommand(fallbackMethod="hello")
,在本案例中,触发降级之后,会调用hello方法。
触发降级策略:
总结
本篇介绍了Dubbo在SSM项目,以及Spring Boot项目中的集成使用,以及配置文件的优先级,超时时间和重试机制等。此外还有负载均衡策略,如何保证高可用,在官方文档里都有提及,本篇不再赘述。
Dubbo官方文档