解读golang plugin热更新尝试

 更新时间:2018年04月21日 10:44:25   转载 作者:呵大官人  
这篇文章主要介绍了解读golang plugin热更新尝试,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

当我们在使用php开发的时候,基本不需要关心热更新这件事的,因为PHP本身已经帮我处理好了,只需要提交代码,PHP重新解释一遍即可。而go则是静态语言,编译后得到的是直接被机器执行的,所有代码已经翻译成相对应的机器指令并且在运行时已经加载到内存,不能动态更新。那么如果想热更新就成了件麻烦的事,但是作为后端开发人员,很渴望支持这种功能,毕竟在线上能新增功能、修复bug客户端完全无感知是多么完美的事。

本文暂不讨论http这种无状态服务更新,网上能搜索到很多文章关于如何利用fd继承实现优雅重启。这里主要讨论使用golang 1.8新增的plugin来实现业务的更新,并且业务是类似游戏的有状态服务。官方文档中对plugin的描述比较简单,他可以动态的加载so和执行导出的方法,并且仅仅提供了两个方法:打开模块和提取符号,甚至连关闭都没有(-_-)。

一个程序包含两部分:数据和算法,那么既然是有状态服务,数据部分肯定不能动,那么热更就只能动算法部分了。这时我们需要一个容器,将这两部分隔离开,一方面是存储数据,另一方面要动态加载so。隔离了数据和算法,只要数据存在,我们就可以随意更新算法了。在开始编码之前,要先解决几个问题:

1、同一个so文件只会被打开一次

2、每个so有一个pluginpath用来标识是否重复,如果两个so文件不一样,但pluginpath一样还是会报错

3、不同so文件定义的结构体不能使用类型断言进行转换

对于上面的问题,有如下解决方案:

1、每次生成的so带一个版本号比如game.1001.so

2、编译的时候新增--ldflags="-pluginpath=xxx"参数

3、使用unsafe进行转换(下面还会有注意事项)

 代码地址:https://github.com/scgywx/myplugin

1、编译engine,这就是我们上面说的容器,他负责数据存储和so的加载与执行。

sh build.sh

2、编译第1个版本so(注意后面有个参数)

sh build_so.sh 1

3、将src/logic/main.go里面的modelVersion和modelName分别改成1002和game2(这里主要是测试两个版本的内容区别)

4、编译第2个版本so

sh build_so.sh 2

5、运行容器

./engine

6、浏览器输入127.0.0.1:12345/hello,会看到如下显示(这是使用的第一个版本so)

复制代码 代码如下:
hello test, this is golang plugin test!, version=1001, name=game1, oldversion=0, oldName=

7、浏览器输入127.0.0.1:12345/load?name=plugin2.so(这里输出done,就说明加载so成功了)

8、再次输入127.0.0.1:12345/hello,会看到如下显示。

复制代码 代码如下:
hello test, this is golang plugin test!, version=1002, name=game2, oldversion=1001, oldName=game1
 

到这里,我们的热更新效果已经达成,但是还是有一些限制

1、每个so不能单独保存数据,因为当另一个so加载后,前面so的数据是没办法访问到,并且由于so不能被关闭,可能会出现多个so引用同一个变量,gc没办法释放,所以需要透过容器来共享数据,那么我们就不能在模块内使用全局变量来保存数据。

2、go里面两个类型即使一样,也不能直接转换,所以两个so内定义的结构体也不能直接转换,要使用unsafe.Pointer来进行强转(见src/logic/main.go),既然是强转,那么两个版本的so使用的结构体定义就不能有区别,否则转换后数据可能会出现异常,也就是说热更新不能修改结构体。

 本文只是技术尝试,没有线上验证,还有多少坑还不知道,热更新不是必须,如若支持,便是好事。。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

相关文章

  • golang并发ping主机的方法

    golang并发ping主机的方法

    今天小编就为大家分享一篇golang并发ping主机的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-07-07
  • Go 中 slice 的 In 功能实现探索

    Go 中 slice 的 In 功能实现探索

    这篇文章主要介绍了Go 中 slice 的 In 功能实现探索,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • win7下配置GO语言环境 + eclipse配置GO开发

    win7下配置GO语言环境 + eclipse配置GO开发

    这篇文章主要介绍了win7下配置GO语言环境 + eclipse配置GO开发,需要的朋友可以参考下
    2014-10-10
  • golang通过context控制并发的应用场景实现

    golang通过context控制并发的应用场景实现

    这篇文章主要介绍了golang通过context控制并发的应用场景实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • go浮点数转字符串保留小数点后N位的完美解决方法

    go浮点数转字符串保留小数点后N位的完美解决方法

    这篇文章主要介绍了go浮点数转字符串保留小数点后N位解决办法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Go语言中使用gorm小结

    Go语言中使用gorm小结

    这篇文章主要给大家介绍了Go语言中如何使用gorm,文中介绍的很详细,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • Go语言结构体定义和使用方法

    Go语言结构体定义和使用方法

    这篇文章主要介绍了Go语言结构体定义和使用方法,以实例形式分析了Go语言中结构体的定义和使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • VSCode1.4 搭建Golang的开发调试环境(遇到很多问题)

    VSCode1.4 搭建Golang的开发调试环境(遇到很多问题)

    这篇文章主要介绍了VSCode1.4 搭建Golang的开发调试环境(遇到很多问题),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • go语言文件正则表达式搜索功能示例

    go语言文件正则表达式搜索功能示例

    这篇文章主要介绍了go语言文件正则表达式搜索功能,涉及Go语言文件目录的遍历及正则操作相关技巧,需要的朋友可以参考下
    2017-01-01
  • 使用Go语言实现微信公众平台

    使用Go语言实现微信公众平台

    这篇文章主要介绍了使用Go语言实现微信公众平台,虽然不是全部代码,但是也是给我们提供了一个非常好的思路,需要的朋友可以参考下
    2015-01-01

最新评论