文章目录
- 一、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.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsdhttp://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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsdhttp://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
注解:
java"> <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
方法,并且可以指定负载均衡和超时时间等策略:
java"> @Reference(loadbalance="random",timeout=1000) //dubbo直连UserService userService;
四、应用案例
在本篇的应用中,将所有需要被远程调用的接口,抽取成一个独立的模块进行管理,消费者
和生产者
去依赖该模块:
生产者方:
java">@Service//暴露服务
@Component
public class UserServiceImpl implements UserService {@HystrixCommand@Overridepublic List<UserAddress> getUserAddressList(String userId) {// TODO Auto-generated method stubSystem.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);}}
消费者方:
java">@Controller
public class OrderController {@AutowiredOrderService orderService;@ResponseBody@RequestMapping("/initOrder")public List<UserAddress> initOrder(@RequestParam("uid")String userId) {return orderService.initOrder(userId);}}
java">@Service
public class OrderServiceImpl implements OrderService {//@Autowired@Reference(loadbalance="random",timeout=1000) //dubbo直连UserService userService;@HystrixCommand(fallbackMethod="hello")@Overridepublic List<UserAddress> initOrder(String userId) {// TODO Auto-generated method stubSystem.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 id="demoService" interface="com.example.DemoService" timeout="5000" retries="3"/>
3. 消费者/提供者级配置
<dubbo:consumer timeout="6000" retries="1"/>
<dubbo:provider timeout="4000"/>
4. 全局配置
<dubbo:application name="demoApplication"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
六、Dubbo超时时间和重试
在Spring Boot项目中,设置超时时间和重试次数,可以通过在服务消费端的 @DubboReference
注解中设置,优先级高于配置文件中的全局配置。
java"> @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: 5000retries: 2
如果需要更细粒度控制到接口中的方法级别,则可以:
dubbo:consumer:services:com.example.MyService:methods:- name: method1retries: 0 # method1 不重试- name: method2retries: 2 # method2 重试 2 次
演示接口超时:
目前在页面上是直接打印出了报错信息,后续可以通过引入Hystrix
引导到降级逻辑上。
七、设置本地存根
Dubbo 本地存根用于在消费端(Consumer)对服务进行代理或增强,常用于参数校验、缓存、限流等场景。
编写本地存根方法,和接口放在同一个包下:
java">public class UserServiceStub implements UserService{private final UserService userService;public UserServiceStub(UserService userService) {this.userService = userService;}/*** 按照用户id返回所有的收货地址** @param userId* @return*/@Overridepublic List<UserAddress> getUserAddressList(String userId) {System.out.println("进入本地存根方法....");return userService.getUserAddressList(userId);}
}
在消费者方的@Reference
注解上加入stub = "存根类的全路径"
,重新访问接口:
八、整合Hystrix
在生产者方和消费者方同时引入依赖,并且在启动类上加入@EnableHystrix
java"> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
生产者方对外暴露的方法上加入@HystrixCommand
注解:
消费者方同样加上注解,并且指定触发降级后的逻辑:@HystrixCommand(fallbackMethod="hello")
,在本案例中,触发降级之后,会调用hello方法。
触发降级策略:
总结
本篇介绍了Dubbo在SSM项目,以及Spring Boot项目中的集成使用,以及配置文件的优先级,超时时间和重试机制等。此外还有负载均衡策略,如何保证高可用,在官方文档里都有提及,本篇不再赘述。
Dubbo官方文档