SpringBoot上手整合Dubbo
- 一. Dubbo架构图
- 二. 搭建一个Common模块存放接口+实体类
- ①. UserAddress 实体类
- ②. 用户和订单接口
- 三. 搭建一个生产者Provider模块
- ①. pom.xml依赖导入
- ②. 用户实现类UserServiceImpl
- ③. 启动类上注解添加
- ④. 配置文件修改application.yml或者provider.xml配置文件
- ⑤. 启动provider服务进行测试
- 四. 搭建消费者Consumer模块
- ①. pom.xml配置文件
- ②. 订单的实现类OrderServiceImpl
- ③. 启动类上注解添加
- ④. 配置文件修改application.yml或者使用consumer.xml配置文件
- ⑤. Controller 接口编写
- ⑤. 启动consumer服务进行测试
- 五. Dubbo整合SpringBoot三种配置方式
- ①. 使用@DubboService(暴露服务),@DubboReference(引用服务)
- ②. 保留Dubbo 相关的xml配置文件
- ③. 使用 注解API的方式
- 六. 集群下dubbo负载均衡配置
- ①. Random LoadBalance 基于权重的随机负载均衡机制
- ②. RoundRobin LoadBalance 基于权重的轮询负载均衡机制
- ③. LeastActive LoadBalance最少活跃数负载均衡机制
- ④. ConsistentHash LoadBalance一致性hash 负载均衡机制
- 七. 整合hystrix,服务熔断与降级处理
- ①. 服务降级
- ②. 集群容错
- 1. Failfast Cluster
- 2. Failsafe Cluster
- 3. Failback Cluster
- 4. Forking Cluster
- 5. Broadcast Cluster
- ③. 整合hystrix
- 八. GitHub源码地址
一. Dubbo架构图
二. 搭建一个Common模块存放接口+实体类
①. UserAddress 实体类
package com.xizi.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserAddress implements Serializable {
private Integer id;
private String userAddress;
private String userId;
private String consignee;
private String phone;
private String isDefault;
}
②. 用户和订单接口
package com.xizi.service;
import com.xizi.pojo.UserAddress;
import java.util.List;
/**
* @author xizizzz
* @description: TODO
* @date 2021-7-21上午 09:41
*/
public interface UserService {
List<UserAddress> getUserAddressList(String userId);
}
package com.xizi.service;
import com.xizi.pojo.UserAddress;
import java.util.List;
/**
* @author xizizzz
* @description: TODO
* @date 2021-7-21上午 09:49
*/
public interface OrderService {
List<UserAddress> initOrder(String userId);
}
三. 搭建一个生产者Provider模块
①. pom.xml依赖导入
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.12</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.xizi</groupId>
<artifactId>service_common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
②. 用户实现类UserServiceImpl
@Service
@DubboService(timeout = 0) //暴露服务
public class UserServiceImpl implements UserService {
@HystrixCommand
@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("userService1.....");
UserAddress userAddress1 = new UserAddress(1, "江西南昌", "00000", "xizizzz", "15652211111", "1");
UserAddress userAddress2 = new UserAddress(2, "浙江杭州", "00001", "xizzz", "17911111111", "1");
if(Math.random()>0.5) {
throw new RuntimeException();
}
return Arrays.asList(userAddress1, userAddress2);
}
}
③. 启动类上注解添加
//@ImportResource(locations ="classpath:provider.xml") //第二种方式 使用dubbo xml配置文件
@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.xizi") //开启基于注解的dubbo
@EnableHystrix //开启服务容错
public class UserServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceProviderApplication.class, args);
}
}
④. 配置文件修改application.yml或者provider.xml配置文件
- 本地记得开启Zookeeper注册中心
server:
port: 9000
dubbo:
application:
name: user-service-provider
registry:
protocol: zookeeper
address: 127.0.0.1:2181
protocol:
name: dubbo
port: 20080
使用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="boot-user-service-provider"></dubbo:application>
<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<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.xizi.service.UserService"
ref="userServiceImpl01" timeout="1000" version="1.0.0">
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:service>
<!--统一设置服务提供方的规则 -->
<dubbo:provider timeout="1000"></dubbo:provider>
<!-- 服务的实现 -->
<bean id="userServiceImpl01" class="com.xizi.service.UserServiceImpl"></bean>
<!-- 连接监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor>
</beans>
⑤. 启动provider服务进行测试
四. 搭建消费者Consumer模块
①. pom.xml配置文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.12</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.xizi</groupId>
<artifactId>service_common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
②. 订单的实现类OrderServiceImpl
package com.xizi.service;
import com.alibaba.dubbo.config.annotation.Reference;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.xizi.pojo.UserAddress;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
* @author xizizzz
* @description: TODO
* @date 2021-7-21上午 09:50
*/
@Service
@DubboService
public class OrderServiceImpl implements OrderService{
@Reference(loadbalance="random",timeout=1000)
// @Autowired
UserService userService;
@HystrixCommand(fallbackMethod="hello")
@Override
public List<UserAddress> initOrder(String userId) {
System.out.println("用户id:"+userId);
//1、查询用户的收货地址
List<UserAddress> addressList = userService.getUserAddressList(userId);
for (UserAddress userAddress : addressList) {
System.out.println(userAddress.toString());
}
return addressList;
}
// 服务报错后置方法
public List<UserAddress> hello(String userId) {
return Arrays.asList(new UserAddress(10, "测试地址", "1", "测试", "测试", "Y"));
}
}
③. 启动类上注解添加
//@ImportResource(locations ="classpath:consumer.xml") //第二种方式 使用dubbo xml配置文件
@SpringBootApplication
@EnableDubbo
@EnableHystrix
public class UserServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceConsumerApplication.class, args);
}
}
④. 配置文件修改application.yml或者使用consumer.xml配置文件
server:
port: 9001
dubbo:
application:
name: order-service-consumer
registry:
protocol: zookeeper
address: 127.0.0.1:2181
protocol:
port: 20881
使用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://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">
<context:component-scan base-package="com.xizi.service"></context:component-scan>
<dubbo:application name="order-service-consumer"></dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!-- 配置本地存根-->
<!--声明需要调用的远程服务的接口;生成远程服务代理 -->
<!--
1)、精确优先 (方法级优先,接口级次之,全局配置再次之)
2)、消费者设置优先(如果级别一样,则消费方优先,提供方次之)
-->
<!-- timeout="0" 默认是1000ms-->
<!-- retries="":重试次数,不包含第一次调用,0代表不重试-->
<!-- 幂等(设置重试次数)【查询、删除、修改】、非幂等(不能设置重试次数)【新增】 -->
<dubbo:reference interface="com.xizi.service.UserService"
id="userService" timeout="5000" retries="3" version="*">
<!-- <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> -->
</dubbo:reference>
<!-- 配置当前消费者的统一规则:所有的服务都不检查 -->
<dubbo:consumer check="false" timeout="5000"></dubbo:consumer>
<dubbo:monitor protocol="registry"></dubbo:monitor>
<!-- <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor> -->
</beans>
⑤. Controller 接口编写
package com.xizi.controller;
import java.util.List;
import com.alibaba.dubbo.config.annotation.Reference;
import com.xizi.pojo.UserAddress;
import com.xizi.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class OrderController {
@Autowired
OrderService orderService;
@ResponseBody
@RequestMapping("/initOrder")
public List<UserAddress> initOrder(@RequestParam("uid")String userId) {
return orderService.initOrder(userId);
}
}
⑤. 启动consumer服务进行测试
五. Dubbo整合SpringBoot三种配置方式
①. 使用@DubboService(暴露服务),@DubboReference(引用服务)
②. 保留Dubbo 相关的xml配置文件
- 导入dubbo-starter,使用@ImportResource导入Dubbo的xml配置文件
③. 使用 注解API的方式
- 将每一个组件手动配置到容器中,让dubbo来扫描其他的组件
package com.xizi.config;
import java.util.ArrayList;
import java.util.List;
import com.xizi.service.UserService;
import org.springframework.context.annotation.Bean;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.MethodConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
//@Configuration 第三种方式 使用Config配置文件手动创建
public class MyDubboConfig {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("boot-user-service-provider");
return applicationConfig;
}
//<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("127.0.0.1:2181");
return registryConfig;
}
//<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20882);
return protocolConfig;
}
/**
*<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
public ServiceConfig<UserService> userServiceConfig(UserService userService){
ServiceConfig<UserService> serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(UserService.class);
serviceConfig.setRef(userService);
serviceConfig.setVersion("1.0.0");
//配置每一个method的信息
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("getUserAddressList");
methodConfig.setTimeout(1000);
//将method的设置关联到service配置中
List<MethodConfig> methods = new ArrayList<>();
methods.add(methodConfig);
serviceConfig.setMethods(methods);
//ProviderConfig
//MonitorConfig
return serviceConfig;
}
}
六. 集群下dubbo负载均衡配置
①. Random LoadBalance 基于权重的随机负载均衡机制
- 随机,按权重设置随机概率。 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
②. RoundRobin LoadBalance 基于权重的轮询负载均衡机制
- 轮循,按公约后的权重设置轮循比率。 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
③. LeastActive LoadBalance最少活跃数负载均衡机制
- 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
④. ConsistentHash LoadBalance一致性hash 负载均衡机制
- 一致性 Hash,相同参数的请求总是发到同一提供者。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
七. 整合hystrix,服务熔断与降级处理
①. 服务降级
- 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
②. 集群容错
- 在集群调用失败时,Dubbo 提供了多种容错方案。
1. Failfast Cluster
- 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
2. Failsafe Cluster
- 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
3. Failback Cluster
- 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
4. Forking Cluster
- 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
5. Broadcast Cluster
- 广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
③. 整合hystrix
- Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能
<!--hystrix服务治理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
https://github.com/xizizzz/Dubbo_Study