Golang Go语言中k8s里同一个服务开启了多个副本,如何退出特定副本中的协程?

Golang Go语言中k8s里同一个服务开启了多个副本,如何退出特定副本中的协程?

业务场景

该服务是执行多个数据收集任务,每个任务起一个协程,用户取消正在运行的任务,协程退出。

遇到的问题

不知道这个任务运行在哪个副本当中,k8s 服务存在负载均衡。

5 回复

我猜一下你的问题:现在需要停止一个程序里的一个协程,但是这个程序部署在多个副本上。你希望通过 api 来触发停止逻辑,但是因为负载均衡导致 api 请求可能被负载到任意副本上去,而被负载的副本上可能并没有你想要停止的那个协程。

如果是这种问题,有两种情况。
一、如果你程序的存储是用的文件或者内存,那么只能让负载均衡采用哈希算法,保证创建任务的请求和停止任务的请求路由到同一个副本上。
二、如果你的程序用的是其他中心化存储如 mysql 或消息队列。这种情况应该将任务的创建流程和任务的消费流程分离开,创建任务后任务在哪个副本运行记录到数据库中,停止时先去数据库查询,然后标记停止。消费端 watch 到停止标记进行停止。(大概思路供参考,具体情况要看技术选型而定)

更多关于Golang Go语言中k8s里同一个服务开启了多个副本,如何退出特定副本中的协程?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


argo workflow

  1. 协程需要有一个 uuid 并关联任务 uuid
    2. 需要再起一个 manager 协程用来管理干活的 worker 协程
    3. ( 2 选 1 ) manager 轮询 db 拉需要关闭的协程的 uuid
    3. ( 2 选 1 ) manager 订阅事件(需要额外中间件支撑)获得需要关闭的协程的 uuid

感谢大家的方案,我准备采用全副本订阅 mq 然后终止协程这个方案

在Golang中操作Kubernetes(k8s)集群中的特定副本以退出协程,是一个涉及多个领域的复杂问题。直接退出特定副本中的协程通常不是推荐的做法,因为这违反了分布式系统和微服务设计中的一些基本原则,比如状态共享和独立部署。不过,如果你确实有这样的需求,可以考虑以下方案:

  1. 信号机制

    • 可以在应用中实现一个信号监听机制,通过Kubernetes的ConfigMap或环境变量来传递需要退出的副本标识。
    • 当该副本接收到特定信号时,可以通过内部的逻辑来停止或退出特定的协程。
  2. 领导选举

    • 使用领导选举模式,只让一个副本(领导者)执行特定操作,其他副本(跟随者)则不执行。
    • 如果需要停止某个协程,可以重新选举领导者,并让新的领导者通知旧领导者停止协程。
  3. 服务网格和流量管理

    • 使用Istio等服务网格工具,可以精确控制流量路由到特定副本。
    • 虽然这不能直接停止协程,但可以通过重定向流量来间接实现类似效果。
  4. 日志和监控

    • 使用Prometheus和Grafana等监控工具,跟踪协程的状态和性能。
    • 如果发现特定副本的协程出现问题,可以通过Kubernetes的滚动更新或Pod删除来重新部署该副本。

总之,直接退出特定副本中的协程是不推荐的,更好的做法是通过信号、领导选举、流量管理或监控日志等间接手段来实现需求。

回到顶部