Go 原生插件使用问题全解析

发布时间:2023-02-01 16:00

图片

文|丁飞(花名:路德 )

蚂蚁集团高级工程师

Go 原生插件使用问题全解析_第1张图片

深耕于 SOFAMesh 产品的商业化落地 主要方向为基于服务网格技术的系统架构升级方案设计与落地

本文 4394 字 阅读 10 分钟

|前言|

MOSN 作为蚂蚁集团在 ServiceMesh 解决方案中的数据面组件,从设计之初就考虑到了第三方的扩展开发需求。目前,MOSN 支持通过 gRPC、WASM、以及 Go 原生插件三种机制对其进行扩展。

我在主导设计和落地基于 Go 原生插件机制的扩展能力时遇到了很多问题,鉴于这方面的相关资料很少,因而就有了这个想法来做一个非常粗浅的总结,希望能对大家有所帮助。

注:本文只说问题和解决方案,不读代码,文章最后会给出核心源码的 checklist。

PART. 1--文章技术背景

一、运行时

通常而言,在计算机编程语言领域,“运行时”的概念和一些需要使用到 VM 的语言相关。程序的运行由两个部分组成:目标代码和“虚拟机”。比如最为典型的 JAVA,即 Java Class + JRE。

对于一些看似不需要“虚拟机”的编程语言,就不太会有“运行时”的概念,程序的运行只需要一个部分,即目标代码。但事实上,即使是 C/C++,也有“运行时”,即它所运行平台的 OS/Lib。

Go 也是一样,因为运行 Go 程序不需要前置部署类似于 JRE 的“运行时”,所以它看起来似乎跟“虚拟机”或者“运行时”没啥关系。但事实上,Go 语言的“运行时”被编译器编译成了二进制目标代码的一部分。

Go 原生插件使用问题全解析_第2张图片

图 1-1. Java 程序、runtime 和 OS 关系

Go 原生插件使用问题全解析_第3张图片

图 1-2. C/C++ 程序、runtime 和 OS 关系

Go 原生插件使用问题全解析_第4张图片

图 1-3. Go 程序、runtime 和 OS 关系

二、Go 原生插件机制

作为一个看起来更贴近 C/C++ 技术栈的 Go 语言来说,支持类似动态链接库的扩展一直是社区中较为强烈的诉求。

如图 1-5,Go 在标准库中专门提供了一个 plugin 包,作为插件的语言级编程界面,src/plugin 包的本质是使用 cgo 机制调用 unix 的标准接口:dlopen() 和 dlsym() 。因此,它给 C/C++ 背景的程序员一种“这题我会”的错觉。

Go 原生插件使用问题全解析_第5张图片

图 1-4. C/C++ 程序加载动态链接库

Go 原生插件使用问题全解析_第6张图片

图 1-5. Go 程序加载动态链接库

PART. 2--典型问题解决

很遗憾,与 C/C++ 技术栈相比,Go 的插件的产出物虽然也是一个动态链接库文件,但它对于插件的开发、使用有一系列很复杂的内置约束。更令人头大的是,Go 语言不但没有对这些约束进行系统性的介绍,甚至写了一些比较差的设计和实现,导致插件相关问题的排错非常反人类。

本章节重点跟大家一起看下,在开发、使用 Go 插件,主要是编译、加载插件的时候,最常见、但必须定位到 Go 标准库 (主要包括编译器、链接器、打包器和运行时部分) 源码才能完全弄明白的几个问题,及对应的解决方法。

简而言之,Go 的主程序在加载 plugin 时,会在“runtime”里对两者进行一堆约束检查,包括但不限于:

- go version 一致

- go path 一致

- go dependency 的交集一致

  • 代码一致
  • path 一致

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号