Ribbon 实例检查策略(健康检查)

本文介绍了在一个采用Eureka+Gateway微服务架构的环境中,如何处理因网络问题导致的请求失败。当Gateway到某微服务节点间的网络出现问题时,由于Eureka仍认为该服务健康,因此不会自动下线。解决方案是通过自定义Ribbon的IPing接口实现健康检查策略,具体做法是发送HTTP请求到微服务的/actuator/info接口,根据响应状态码判断服务是否可用。配置完成后,Ribbon将根据检查结果决定是否将请求转发到有问题的微服务节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

首先简单描述下大概的背景,我们的微服务架构采用的是 eureka + gateway,eureka 和 gateway 以及其他微服务都是以容器的方式部署在 K8s 中。最近,出现了一个问题,gateway 所在节点到某微服务所在节点的网络出现了问题,导致请求失败,错误信息如下:

2022-06-30 11:22:58.059[WARN ]reactor.netty.http.client.HttpClientConnect:  299-[id: 0x2add3421, L:/172.22.20.49:37826 - R:172.22.9.118/172.22.9.118:21004] The connection observed an error
io.netty.channel.unix.Errors$NativeIoException: syscall:read(..) failed: Connection reset by peer
        at io.netty.channel.unix.FileDescriptor.readAddress(..)(Unknown Source)

注:这里的 L:/172.22.20.49:37826 为 gateway 所在节点,R:172.22.9.118/172.22.9.118:21004 为微服务所在节点

问题的示意图如下:
图1
从上图,我们看到当客户端访问「 微服务1」的时候,通过 ribbon 将请求转发到「微服务1-2」上。由于网络原因(「gateway所在节点」「微服务1-2 所在节点」 的网络)导致请求无法送达,造成请求失败。

二、解决方案

也许有的同学会问,Eureka 不是应该下掉「微服务1-2」这个节点吗?让我们仔细想一下,Eureka 能够正常接收到来自「微服务1-2」的心跳,所以,对 Eureka 来说「微服务1-2」是健康的,既然是健康的节点,那不被下掉就是必然的了。

所以,想从 Eureka 入手解决这个问题,看样子是行不通啦(因为 Eureka 和 微服务1-2 都是正常的),那该如何是好呢?!

Ribbon 作为 「客户端负载均衡」,不但给我们提供了丰富的负载均衡策略。同时也提供了实例检查策略,也就是对客户端本地存储的服务列表中的实例进行健康检查(我们可以通过实现 com.netflix.loadbalancer.IPing 来自定义检查策略)。

如此看来,Ribbon 的实例检查 能够很好的解决我们上边提到的问题了!!!

三、方案实施

下面说下具体的方案实施(两步搞定)

1、自定义实例检查策略

通过对接口 com.netflix.loadbalancer.IPing 的实现,如下图:
在这里插入图片描述
代码如下:

import com.netflix.loadbalancer.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: cab5
 * @Date: 2022/7/13 15:27
 * @Description: 自定义 ribbon 的对微服务的健康检查
 */
@Slf4j
public class HealthChecker implements IPing {
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public boolean isAlive(Server server) {
        String url = "http://" + server.getId() + "/actuator/info";
        try {
            ResponseEntity<String> heath = restTemplate.getForEntity(url, String.class);
            if (heath.getStatusCode() == HttpStatus.OK) {
                log.info("ping " + url + " success and response is " + heath.getBody());
                return true;
            }
            log.info("ping " + url + " error(status code = " + heath.getStatusCode() + ") and response is " + heath.getBody());
            return false;
        } catch (Exception e) {
            log.error("ping " + url + " failed", e);
            return false;
        }
    }
}

主要逻辑是通过调用微服务的 /actuator/info 接口,判断返回的状态码是否为 200。这里的 /actuator/info 接口是微服务引入 spring-boot-starter-actuator 得到的。

2、配置自定义检查策略

通过代码的方式将「步骤一」中的 HealthChecker 进行配置,如下:

import com.netflix.loadbalancer.IPing;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: cab5
 * @Date: 2022/7/13 15:24
 * @Description:
 */
@Configuration
public class GatewayConfig {
    /**
     * ribbon 健康检查
     * @return
     */
    @Bean
    public IPing iPing() {
        return new HealthChecker();
    }
}

OK,大功告成!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cab5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值