关于skynet_fly热更新实现细节

前言

由于几个月的时间里,断断续续发现一些问题,做了很多调整,与最初的版本已经有些许差异了,于是打算重新梳理一下热更的流程实现的细节。

实现思路

可以先看看这篇关于skynet_fly热更新实现

整体还是围绕容器管理员,容器客户端,可热更服务展开。

职责

  • 容器管理员 负责启动通知关闭通知更新
  • 容器客户端 负责注册访问监听服务切换记录需要访问回复是否需要访问
  • 可热更服务 负责记录来访检查安全退出

启动流程

容器管理员查看有没有旧服务,有的话通知关闭,然后启动新服务,通知更新(监听的容器客户端)更新地址。

访问流程

容器客户端 在加载代码阶段提供好注册表,在skynet.init启动阶段根据注册表启动多个监控循环进行注册访问监听地址更新,记录需要访问的地址。访问实例直接引用本地记录地址进行消息发送,根据访问实例提供的can_switch_func服务切换检查来决定是否进行服务切换记录需要访问的地址使用弱引用表记录,当没有任何访问实例引用时,说明不在需要访问该地址。当需要退出的可热更服务来询问是否需要访问它是,它就已经不在记录需要访问的表里了(回复是否需要访问)。

退出流程

可热更服务 在被通知关闭后会启动一个定时轮询任务做检查安全退出的流程,检查流程分为两步,1是调用本服务的check_exit函数,看本服务的工作结束没有,如果结束,再看条件2询问来访者是否还需要访问自己(记录来访的目的),当全部不需要了,确认服务可以退出。

流程图

细节展开

容器管理员

启动

因为热更过程中,假设A服务先热更,A服务有可能访问到旧的B服务(AB问题),所以容器管理员必须保证没有重入问题,我使用了skynet.queue来做保证。

通知关闭

通知旧服务关闭我分为了herald_exit预告退出,fix_exit确认退出,exit退出,check_exit检查退出,cancel_exit取消退出5个回调为什么要分这么细,肯定是有原因了,一开始只有一个exit的回调。

  • herald_exit 预告退出 由于有些服务需要退出前做一些处理,比如我实现的web_master_m/web_slave_m模块,web_master_m会监听一个端口,当web_master_m要热更时,旧服务需要先关闭监听端口,让新服务去监听。
  • fix_exit 确认退出 收到这个回调这个服务就要开始执行关闭前的一些安全处理了。(要注意,确认退出了,不代表没有新的服务访问你了,可能在watch的间隙拿到你的地址或者有常驻的访问对象)
  • cancel_exit取消退出 新服务启动失败了,比如热更web_master_m,调用start函数没有返回true,说明启动失败,这时候旧服务需要继续工作,保证健壮性。
  • check_exit 这个是确认退出以后会轮询到exit回调为止,如果当前服务还有任务没有完成,不应该返回true,或者不实现这个回调处理。
  • exit退出 表示已经进入退出销毁的倒计时,到这个阶段这个服务不应该还有任务(到这个阶段可以确定没有访问者了,除非你用原生的skynet.call或者send调用)。

通知更新

watch机制能保证容器客户端一直持有最新的地址信息。

容器客户端

  • 注册访问 为了解决迟到访问问题,访问服务之前要先注册contriner_client:register,确定服务启动好就知道需要访问哪些服务。比较特殊的情况是frpc_server集群服务,一开始并不知道需要访问哪些服务,就需要按照全部都访问的逻辑处理,但是可能存在服务不重启就新增模块的情况,就需要动态的去扩展,于是就新增了monitor_new监听新模块的流程,通过调用contriner_client:monitor_all()就可以监听所有热更服务的地址,用于解决这种情况。

特殊处理 因为普通的skynet服务不参与热更,所以它在什么时候注册访问可热更服务都可以,只是需要避免迟到访问问题,所有在服务启动好后就直接监听所有热更服务地址,就能很好的避免这个问题。

  • 监听 通过sub/pub机制保证一直能拿到新的地址。由于成为旧服务的时候,不能去访问新服务,此后不在更新服务地址。
  • 服务切换 服务切换由new生成的访问实例传入的can_switch_func控制,不传默认切换。使用者自己考量。
  • 记录需要访问 每次拿到服务地址都会用弱引用表记录,当该服务地址没有强引用时,弱引用也会清除。可以很方便的记录管理需要访问的服务。
  • 回复是否需要访问 判断是否在记录的访问地址中。

可热更服务

  • 记录来访 每个容器客户端都会注册访问,此时记录来访地址。注册为弱访问者的不记录(用与解决出现环访问的情况,应该总有一个占主导地方),应该尽量避免出现环访问。
  • 检查安全退出 会启动一个轮询定时器,调用check_exit确定可以退出,再询问所有访问者是否还需要访问,直到可以退出并且没有访问者需要访问时就可以安全退出了。

总结

重新梳理了一遍热更流程,目前最新的版本是最健全完善的版本。
skynetfly源码地址


关于skynet_fly热更新实现细节
https://huahua132.github.io/2023/12/03/skynet_fly_ss/reload/
作者
huahua132
发布于
2023年12月3日
许可协议