IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Dubbo降级&容错机制 -> 正文阅读

[Java知识库]Dubbo降级&容错机制

Dubbo降级&容错机制

在分布式环境中,由于所有的服务不在同一台服务器中,就涉及到服务之间的调用,而远程调用涉及到网络,网络是不可靠的,这就导致了有时候远程调用会失败,这时候就需要容错机制

而服务降级机制,是指在流量特别大的情况下,我们主动关闭一些不重要的服务,将资源向核心服务倾斜,被关闭的服务就会做服务降级

服务降级

服务降级就是我们将一些不重要的服务屏蔽掉,当有别的服务对被降级的服务发起远程调用时,不发起调用,而是执行本地的服务降级逻辑

首先我们构建一个提供者服务,用于获取用户的地址

@Service
@DubboService
@Slf4j
public class UserServiceImpl implements UserService {

    private static int count = 0;

    @Override
    public List<UserAddress> getUserAddressList() {
        UserAddress userAddress1 = new UserAddress(1, "HZ", "00000", "小王", "15652211111", "1");
        UserAddress userAddress2 = new UserAddress(2, "BJ", "00001", "小张", "17911111111", "1");
        return Arrays.asList(userAddress1, userAddress2);
    }

    @Override
    public UserAddress getUserAddress(String userId) {
        count++;
        log.info("调用次数:{},查询id:{}", count,userId);
        List<UserAddress> userAddressList = getUserAddressList();
        for (UserAddress userAddress : userAddressList) {
            if (userAddress.getUserId().equals(userId)) {
                return userAddress;
            }
        }
        return null;
    }
}

然后构建一个消费者服务,然后对提供者服务进行降级,不发起远程调用

我们只需要在@DubboReference注解的mock属性中,设置值为force:xxx,即可屏蔽提供者服务,可以设置具体的返回值,或者抛出的异常,或者mock实现的全路径,这里设置为返回一个null值

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(check = false, mock = "force:return null")
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

在消费者服务中创建一个接口,发起远程调用查询用户地址,可以看到直接就返回了一个null值,不会调用提供者服务

在这里插入图片描述

另外一种降级方法是实现具体的降级逻辑,自定义一个nock类,实现服务提供者的接口

@Slf4j
public class UserServiceMock implements UserService {
    @Override
    public List<UserAddress> getUserAddressList() {
        return null;
    }

    @Override
    public UserAddress getUserAddress(String userId) {
        log.info("服务降级");
        return null;
    }
}

然后在mock属性中使用force:前缀,并指定mock类的全路径名,就可以在每次调用时执行本地的mock逻辑

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(check = false, mock = "force:com.blackball.service.mock.UserServiceMock")
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

测试结果和设置返回null值相同,因为以上示例在mock逻辑中也返回了null值,不过在后台日志中输出了服务降级的日志

在这里插入图片描述

服务容错

服务容错和服务降级不同,容错是在调用失败的时候才执行容错逻辑,而服务降级则是屏蔽提供者,不执行远程调用,直接执行降级逻辑

我们只启动消费者服务,而不启动提供者服务,配置check属性为false跳过启动检查

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(check = false)
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

这时候如果发起远程调用,会因为远程调用失败而抛出异常

在这里插入图片描述

后台异常打印

在这里插入图片描述

配置容错,在mock属性中设置返回一个null值

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(check = false, mock = "return null")
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

再次调用,发现没有异常抛出,在调用失败之后返回了null值

在这里插入图片描述

也可以创建一个自定义mock类,实现提供者接口,作为容错逻辑

@Slf4j
public class UserServiceMock implements UserService {

    @Override
    public UserAddress getUserAddress(String userId) {
        log.error("远程调用失败");
        return null;
    }
}

在mock属性中设置mock类的全路径名

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(check = false, mock = "com.blackball.service.mock.UserServiceMock")
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

在发起远程调用失败之后就会执行容错逻辑,打印日志并返回null值

在这里插入图片描述

集群容错

集群容错,是指在有多个服务提供者组成一个集群时,调用失败时做出的行为

我们创建三个提供者服务,其中一号和二号服务在执行过程中阻塞3秒,三号服务正常执行,并且在每一个服务中后台日志打印调用的次数

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private static int count = 0;

    @Override
    public List<UserAddress> getUserAddressList() {
        UserAddress userAddress1 = new UserAddress(1, "HZ", "00000", "小王", "15652211111", "1");
        UserAddress userAddress2 = new UserAddress(2, "BJ", "00001", "小张", "17911111111", "1");
        return Arrays.asList(userAddress1, userAddress2);
    }

    @Override
    public UserAddress getUserAddress(String userId) {
        count++;
        log.info("1号提供者,调用次数:{},查询id:{}", count,userId);
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        List<UserAddress> userAddressList = getUserAddressList();
        for (UserAddress userAddress : userAddressList) {
            if (userAddress.getUserId().equals(userId)) {
                return userAddress;
            }
        }
        return null;
    }
}

然后在提供者服务中设置调用超时时间为1秒,这样就模拟类一号和二号服务调用超时,只有三号服务可以调用成功,方便测试集群容错行为

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(timeout = 1000)
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

失败重试

默认的集群容错行为是failover,也就是调用失败就随机选取其他服务重试,默认重试次数为两次,可以通过retries属性配置重试次数

快速失败

快速失败是指在远程调用失败的时候不会重试,直接抛出错误获取执行容错逻辑,配置cluster属性的值为failfast既可

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(timeout = 1000 , cluster = "failfast")
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

安全失败

配置cluster属性的值为failsafe,则使用安全失败,这时候如果远程调用失败不会报错,也不会重试,直接返回null值

定时重试

配置cluster属性的值为failback,则使用定时重试,如果远程调用失败则会定时重试,直到调用成功为止

并行请求

配置cluster属性的值为forking,则使用并行请求,每次进行远程调用时同时向多个提供者发起调用,只要有一个提供者返回结果则正常返回,默认并行请求两个提供者服务

并行请求个数可以通过parameters来配置

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(timeout = 1000,cluster = "forking", parameters = {"forks","3"})
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

或者在配置文件中使用以下配置来设置

dubbo:
  consumer:
    forks: 3

广播

配置cluster属性的值为broadcast,则使用广播,和并行请求不同,广播时只要有一个服务调用失败,则视为调用失败,抛出错误或者执行容错逻辑

可以通过parameters属性,配置广播过程中超过百分之几的服务调用失败,则中止调用,视为调用失败

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(timeout = 1000, cluster = "broadcast", parameters = {"broadcast.fail.percent", "50"})
    UserService userService;

    @Override
    public UserAddress initOrder(String userId) {
        return userService.getUserAddress(userId);
    }
}

在开发中,我们可以灵活配置集群容错的行为,以贴合实际业务需求,比如对于实时性高的服务,可以使用并行请求,但是会浪费网络带宽,在不重要的业务中,可以使用安全失败,在重要业务中,可以使用定时重试,在幂等业务中,可以使用快速失败

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:31:22  更:2021-07-25 11:33:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 -2025/3/4 2:00:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码