likes
comments
collection
share

好家伙 灰度发布 还有这些需要注意的(下)

作者站长头像
站长
· 阅读数 48

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第n篇文章,点击查看活动详情

继之前 (好家伙, 灰度发布 还这么多细节) 文章出来,我在公司干完,今天自测,本来一切很正常,但是出现了一个问题,我感觉应该出一篇文章,补充下 之前的文章。

目的

把开发 灰度发布的时候 问题 说一下 给大家借鉴下,其实不是什么大问题,还是细节考虑的周全不

feign 返回404

背景信息

好家伙 灰度发布 还有这些需要注意的(下)

提示信息

Caused by: feign.FeignException$NotFound: [404 Not Found] during [GET] to [http://a-service/api/v1/xxx] [FeignCodeService#xxx(Integer)]: [<!DOCTYPE html><html><head lang=en><meta charset=UTF-8><title>页面不存在</title><style>\
* {\
margin: 0;\
padding: 0;\
box-sizing: border-box;\
}\
html... (10856 bytes)]\
at feign.FeignException.clientErrorStatus(FeignException.java:201)\
at feign.FeignException.errorStatus(FeignException.java:177)\
at feign.FeignException.errorStatus(FeignException.java:169)\
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92)\
at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96)\
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138)\
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89)\
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)\
at com.sun.proxy.$Proxy229.getNormalCode(Unknown Source)\
... 101 common frames omitted

请停一下 自己思考下可能是什么问题,再继续往下看

找问题

  1. 思考,我靠,不会是我的jar包有问题吧,把新引入的feign 包去掉,再测试下,我靠,还真好使了。。。看来是我们jar的问题
  2. 我们的代码看起来没问题啊,我自测也是通过了的,靠,这怎么办?
  3. 不行了,看了下 没看出来啊,我debug还不行么,发现最后报错是404,提示 页面不存在,页面不存在,可是我要的是json啊,到底调用到没,我去看了 a-service的日志,我靠,还真没进去。。。
  4. 是我发送的不对,我把feign 日志全开,看了下,a-service 怎么使用的是 file的ILoadBalancer
  5. debug 往前走,看看什么时候 从a-service 变为 file的,发现是有一个 rule ,他就是file的,是之前加载的
  6. 我把所有 rule 赋值的地方进行打断点,重启找下,发现是第一次进这个CustomRule的时候 初始化的,后面没动,等会,不会 之后的请求都是 用的之前的CustomRule 对象吧。。。。。看了下,还真是、、、小迷糊
  7. 那怎么每次都新建一个呢? @Scope("prototype")
  8. 测试下,好使了。。。。嗯嗯 还是当时忘了。。。行吧

什么玩意 网络断了之后,恢复网络 配置不一致了。。。

背景

因为涉及到配置文件的 数据一致性问题,我们这版使用了nacos的 grpc 保证长连接和 数据的一致性。。。结果我在测试网络隔离的情况的时候,出现了配置还是旧版,之后也恢复不了了。。。

现象

数据不一致,导致灰度失败

请停一下 自己思考下可能是什么问题,再继续往下看

解决办法

添加一个定时调度任务进行 定时校对

这里可能涉及线程池的创建

  1. 一定要创建 线程前缀名
  2. 一定把线程进行 统一管理

调用

DefaultScheduler scheduler = new DefaultScheduler("xxx-scheduler-");
scheduler.schedule("定时校对灰度nacos 配置", () -> loadGrayConfig(grayFileName),
    1800, 1800, TimeUnit.SECONDS);

这里我做的时候 设置的30分钟一次轮询,公共调度器 支持调度一次/多次 报错统一处理等等

我靠,怎么老是调度到同一个点

背景

因为我们重写了 负载均衡器,我是随机调用的,结果 老是调用到同一台服务器。这样容易造成 资源的浪费

 int i = new Random().nextInt(upServerByRelease.size());
  return upServerByRelease.get(i);

问题

2台a-service 服务器(0 1),结果请求总是到0 那台机器上

请停一下 自己思考下可能是什么问题,再继续往下看

解决

其实就是copy的 RoundRobinRule 改改就完事


/**
 * @author: xgf
 * @date: 2022/9/7 16:45
 */
public class RoundRobinRuleServiceImpl implements CustomGrayRibbonService {
    private static final boolean AVAILABLE_ONLY_SERVERS = true;
    private static final boolean ALL_SERVERS = false;
    private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);
    private AtomicInteger nextServerCyclicCounter;

    public RoundRobinRuleServiceImpl() {
        this.nextServerCyclicCounter = new AtomicInteger(0);
    }

    public RoundRobinRuleServiceImpl(ILoadBalancer lb) {
        this();
    }

    @Override
    public Server choose(List<Server> reachableServers, List<Server> allServers) {
        if (ObjectUtils.isEmpty(reachableServers)) {
            log.warn("no load balancer");
            return null;
        } else {
            Server server = null;
            int count = 0;

            while (true) {
                if (server == null && count++ < 10) {
                    int upCount = reachableServers.size();
                    int serverCount = allServers.size();
                    if (upCount != 0 && serverCount != 0) {
                        int nextServerIndex = this.incrementAndGetModulo(serverCount);
                        server = (Server) allServers.get(nextServerIndex);
                        if (server == null) {
                            Thread.yield();
                        } else {
                            if (server.isAlive() && server.isReadyToServe()) {
                                return server;
                            }

                            server = null;
                        }
                        continue;
                    }

                    log.warn("No up servers available from load balancer: " + reachableServers);
                    return null;
                }

                if (count >= 10) {
                    log.warn("No available alive servers after 10 tries from load balancer: " + reachableServers);
                }

                return server;
            }
        }
    }

    private int incrementAndGetModulo(int modulo) {
        int current;
        int next;
        do {
            current = this.nextServerCyclicCounter.get();
            next = (current + 1) % modulo;
        }
        while (!this.nextServerCyclicCounter.compareAndSet(current, next));

        return next;
    }
}

总结

上面这三个 就是没注意导致的问题,希望能帮助你

下节讲什么

  1. 做一个学习计划的 app 调研,可以联系我,提意见,成为我们体验官
  2. 会写 线程池系列的文章

这两个并行进行,我wx yuyezhiji