kratos 没更新grpc链接(consul 发现失效)

记一次kratos consul服务发现无效问题

问题描述

当我们微服务闲置一段时间后,目前有A 微服务监听 B微服务。当B服务重启后,A服务中的B服务地址并没有随之变更。我们使用的是 consul作为服务注册发现中心。

排查过程

由于我们设置了日志打印debug级别,因此当B服务重启后,A服务一定会打印 [resolver] update instances xxx 信息的,但目前我们没有看到该信息。所以我们就从其更新的入口来作为切入点。

  1. 所在文件 contrib/registry/consul/v2/registry.go
  2. 所在函数 func (r *Registry) resolve(ctx context.Context, ss *serviceSet) error
  3. 我们可以看到有以下这个逻辑来监听名字服务的变化定位问题函数
  4. 接着就是关键的了,按理说,这个goroutine 应该正常运行,那么服务变化才会实时获取到,所以出问题肯定是要闷获取服务列表又问题,要么就是ctx.Done导致这个goroutine退出了,从而不再更新服务了。
  5. 既然我们已经有两个方向可以查询了,那么就可以开始一个一个来看。
  6. 首先是服务列表更新失败请求,这种情况只需要打印下每次请求结果就行,如果说是因为consul版本问题导致了更新失败这个应该很容易重现出来。
  7. 那么另一种情况就是ctx 被cancel了,导致for循环的退出,这个怎么发现呢?这里就需要我们断电return函数,然后一直等待测试。其实该过程中我们踩了很多坑,譬如不断重启下游服务,不断发送grpc请求。一直没有复现,直到我们静静地就挂着,过了大概半小时就出现了。
  8. 结论:这个东西是由于grpc idle timeout触发了这个机制,我们通过代码跟中这个ctx,就会发现这个是被封装到discoveryResolver中的,而这个Resolver是被grpc的 ccResolverWrapper 触发的。如下
	ccr.serializer.Schedule(func(context.Context) {
		if ccr.resolver == nil {
			return
		}
		ccr.resolver.Close()
		ccr.resolver = nil
	})

当idle timeout 时候就会触发这个ccr.resolver.Close(),从而导致discoveryResolver 的close函数被触发,因此cancel就随即执行,后续的服务发现函数就自动退出了。

处理方式

既然这个是由于grpc idle机制触发,因此我们可以通过配置该超时机制来临时解决这个问题
kgrpc.WithOptions(grpc.WithIdleTimeout(24*time.Hour))

根本解决方式当然是靠 kratos官方来处理。但目前来看他们还没有把这个issue 合并,因此我们也只能先自行处理了。
issue地址 issue

好就说到这里,喜欢的点个关注哈。。。。。

  • 18
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值