SpringCloud gateway监听 nacos服务列表变更事件 刷新负载均衡缓存 服务平滑上下线 AnnotatedConnectException Connection refused

文章讲述了在SpringCloudGateway中,当Kubernetes服务缩容导致服务下线时,如何通过监听Nacos服务列表变更事件来及时刷新负载均衡缓存,避免访问已下线服务引发的错误。作者提供了具体代码示例,包括如何引入Nacos客户端依赖和实现Nacos服务变更监听器。
摘要由CSDN通过智能技术生成

SpringCloud gateway监听 nacos服务列表变更事件 刷新负载均衡缓存 服务平滑上下线

一、报错

io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused:

二、原因

系k8s缩容,集群中一个服务下线,而gateway感知存在延迟,访问了已经下线的服务ip导致报错。

三、分析

  1. 原理是在gateway服务中添加一个监听器,监听nacos服务列表变更事件,当服务列表变更时调用负载均衡缓存刷新接口即可。
  2. gateway有两种负载均衡模式(ribbon,bl),由于没有配置
    spring.cloud.loadbalancer.ribbon.enabled=false
    默认使用的是ribbon

解决

  1. 确保gateway项目引入了nacos客户端依赖,因为需要用到com.alibaba.nacos.client.naming.event.InstancesChangeEvent,注意版本问题,低版本的客户端没有这个类。
		<dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.4.1</version>
        </dependency>
  1. 添加监听器
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Optional;

@Component
@Slf4j
public class NacosInstancesChangeEventListener extends Subscriber<InstancesChangeEvent> {

    @Resource
    private SpringClientFactory springClientFactory;

    @PostConstruct
    public void init() {
        // 注册当前自定义的订阅者以获取通知
        NotifyCenter.registerSubscriber(this);
    }

    @Override
    public void onEvent(InstancesChangeEvent event) {

        log.info("nacos实例变更事件:{}", JSONUtil.toJsonStr(event));

        String serviceName = event.getServiceName();

        // serviceName 格式为 groupName@@name
        String split = Constants.SERVICE_INFO_SPLITER;
        if (serviceName.contains(split)) {
            serviceName = serviceName.substring(serviceName.indexOf(split) + split.length());
        }

        log.info("{}服务实例变更", serviceName);

        ILoadBalancer lb = springClientFactory.getLoadBalancer(serviceName);
        if(ObjectUtil.isNotEmpty(lb)){
            log.info("当前负载均衡缓存服务列表:{}",JSONUtil.toJsonStr(lb.getAllServers()));
            log.info("======更新服务列表开始=====");
            // 手动更新服务列表
            // 如果自定义负载均衡方式则将默认的 ZoneAwareLoadBalancer 替换为自己的实现即可
            Optional.ofNullable(lb)
                    .ifPresent(loadBalancer -> ((ZoneAwareLoadBalancer<?>) loadBalancer).updateListOfServers());
            log.info("======更新服务列表结束=====");
            log.info("更新后的负载均衡缓存列表:{}",JSONUtil.toJsonStr(lb.getAllServers()));
        }


    }

    @Override
    public Class<? extends Event> subscribeType() {
        return InstancesChangeEvent.class;
    }
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值