kong go 插件开发
<h2 id="introduction"><span>介绍</span></h2><p><span><span>在Kong 2.0之前,Lua是唯一支持编写Kong插件的语言,并且仍然是开发和扩展Kong的主要方法。</span><span>Go插件支持的新增功能使Kong用户可以进入Go生态系统。</span><span>例如,有些数据库(例如MS SQL Server)没有很好的Lua客户端库,但Go很好地支持了这些数据库。</span><span>Go插件可以直接访问此类服务器,而无需传递Kong的Lua代码。</span></span></p>
<h2 id="architecture">结构</h2>
<p><span><span>Go PDK完全基于用Go编写的单独过程。</span><span>您可以命名一个go-pluginserver作为Kong的启动进程,</span></span><span><span>并打开一个通讯通道以在它们之间传递事件和函数调用。</span><span>这意味着Go插件可以在真实的Go环境中运行,并且可以使用Go功能,例如goroutine,I / O,IPC等。</span></span></p>
<blockquote>
<p><span>注意:这也意味着对PDK函数的任何调用都必须转移到Kong流程中,然后再返回。</span></p>
</blockquote>
<p><span>Go插件是使用</span><code class="highlighter-rouge">-buildmode=plugin</code><span><span>标志</span><span>编译的,该</span><span>标志允许插件服务器动态加载它们。</span><span>为了遵守Go严格的链接兼容性检查,必须使用</span></span><code class="highlighter-rouge">kong/go-plugin-tool</code><span><span>Docker镜像</span><span>对其进行编译</span><span>,如下所述。</span></span></p>
<h2 id="prerequisites">前置条件</h2>
<p><span>使用Go插件:</span></p>
<ul>
<li><span>您需要可执行文件如</span><code class="highlighter-rouge">go-pluginserver</code><span><span>。</span><span>将其安装在中</span></span><code class="highlighter-rouge">/usr/local/bin/</code><span><span>。</span><span>如果要在其他任何地方使用,请将</span></span><code class="highlighter-rouge">go_pluginserver_exe变量名设置在</code><span><span>Kong配置文件中并且值是他的完整路径</span><span>。</span></span></li>
<li><span>将</span><code class="highlighter-rouge">go_plugins_dir</code><span><span>Kong配置文件中</span><span>的</span><span>变量</span><span>设置</span><span>为有效目录。</span><span>默认</span></span><code class="highlighter-rouge">"off"</code><span>值禁用Go支持。</span></li>
<li><span>将已编译的Go插件添加到上一步中指定的目录中。</span></li>
<li><span><span>通过管理API,数据库或声明性文件以通常方式添加插件设置。</span><span>通过其文件名(不带</span></span><code class="highlighter-rouge">.so</code><span><span>后缀)</span><span>引用插件</span><span>。</span></span></li>
</ul>
<p><span>编写自己的Go插件:</span></p>
<ul>
<li><span>具有Kong开发环境。</span></li>
<li><code class="highlighter-rouge">拥有kong/go-plugin-tool:<version> docker镜像</code><span>,</span><code class="highlighter-rouge"><version></code><span>应该是与kong相同的版本。</span></li>
</ul>
<h2 id="development"><span>发展历程</span></h2>
<h3 id="environment-consistency-constraints"><span>环境一致性约束</span></h3>
<p><span><span>Golang开发以较低的入门障碍和易于部署而闻名。</span><span>即使用Go编写的复杂程序也可以作为单个可执行文件分发,您可以将其复制到任何地方并直接运行。</span></span></p>
<p><span><span>为了实现这一点,编译器默认情况下会生成静态链接的可执行文件。</span><span>这种选择的一个重大缺点是,这使得扩展“完成的” Go程序非常困难。</span><span>有几种方法可以解决此限制,但是大多数方法都涉及某种形式的进程间通信。</span><span>由于语言和基本库都对此提供了很好的支持,因此通常这是一个很好的解决方案,但并非总是如此。</span></span></p>
<p><span><span>在其他语言中,为Kong选择的扩展策略很常见:插件是动态加载的模块。</span><span>为此,可执行文件和插件依赖于系统库,而不是生成完全静态的程序。</span></span></p>
<p><span><span>这是Golang中相对较新的功能,在工具和可部署性方面有一些粗略的优势。</span><span>特别是,加载的可执行文件(</span></span><code class="highlighter-rouge">go-pluginserver</code><span><span>在我们的例子中)和插件必须具有完全相同的链接行为</span><span>,这一点至关重要</span><span>。</span><span>这至少涉及:</span></span></p>
<ul>
<li><span>任何常用库的相同版本,包括:</span>
<ul>
<li><code class="highlighter-rouge">Kong/go-pdk</code></li>
<li><span>所有的标准库(比如</span><code class="highlighter-rouge">fmt</code><span>,</span><code class="highlighter-rouge">rpc</code><span>,</span><code class="highlighter-rouge">reflect</code><span>,等)</span></li>
<li><span>OS的库,例如</span><code class="highlighter-rouge">libpthread</code><span>,</span><code class="highlighter-rouge">libc</code><span>,</span><code class="highlighter-rouge">ld-xxxx</code><span>等。</span></li>
</ul>
</li>
<li><span>与Go编译器完全相同的版本。</span></li>
<li><span>相同的Go环境变量,例如</span><code class="highlighter-rouge">$GOROOT</code><span>和</span><code class="highlighter-rouge">$GOPATH</code></li>
</ul>
<p><span>公共库版本兼容性由</span><code class="highlighter-rouge">go.mod</code><span><span>依赖项管理</span><span>部分处理</span><span>,但这会在环境变量要求方面引入更复杂的问题。</span></span></p>
<p><span>例如,evironment变量</span><code class="highlighter-rouge">$GOPATH</code><span>是一个现实问题,不仅因为推荐的模式之一是</span><code class="highlighter-rouge">$HOME/go</code><span>,其中包括开发人员在其自己系统中的用户名,而且还因为生产构建(Dockerfile,构建脚本,CI / CD系统)很常见。使用非常不同的模式。</span></p>
<p><span>为了保证一致性,</span><code class="highlighter-rouge">kong/go-plugin-tool</code><span><span>用作Go编译器的包装。</span><span>Kong发行软件包和映像使用它来编译包含的软件包</span></span><code class="highlighter-rouge">go-pluginserver</code><span>。</span></p>
<h3 id="development-process"><span>开发过程</span></h3>
<p><span>要在Go中编写Kong插件,您需要:</span></p>
<ul>
<li><span>定义结构类型以保存配置。</span></li>
<li><span>编写一个</span><code class="highlighter-rouge">New()</code><span>函数来创建您的结构实例。</span></li>
<li><span>在该结构上添加方法以处理事件。</span></li>
<li><span>使用编译</span><code class="highlighter-rouge">docker run --rm -v $(pwd):/plugins kong/go-plugin-tool:<version> build <source></code><span>。</span></li>
<li><span>将生成的库(</span><code class="highlighter-rouge">.so</code><span>文件)放入</span><code class="highlighter-rouge">go_plugins_dir</code><span>目录中。</span></li>
</ul>
<p>注意<span>:这里是个demo,请查看https://github.com/Kong/go-plugins</span><span> 。</span></p>
<h3 id="configuration-structure"><span>配置结构</span></h3>
<p><span><span>用Lua编写的插件定义了一个架构,用来指定如何读取和验证来自数据存储区或Admin API的配置数据。</span><span>由于Go是一种静态类型语言,因此所有规范都是通过定义结构体来处理的。</span></span></p>
<div class="highlighter-rouge copy-code-snippet">
<div class="highlight">
<pre class="highlight"><code>type MyConfig struct {
Path string
Reopen bool
}
</code></pre>
</div>
</div>
<p><span><span>公共字段(即以大写字母开头的字段)将填充配置数据。</span><span>如果希望它们在数据存储区中使用其他名称,请添加在</span></span><code class="highlighter-rouge">encoding/json</code><span><span>包装</span><span>上定义的字段标签</span><span>:</span></span></p>
<div class="highlighter-rouge copy-code-snippet">
<div class="highlight">
<pre class="highlight"><code>type MyConfig struct {
Path string `json:my_file_path`
Reopen bool `json:reopen`
}
</code></pre>
</div>
</div>
<h3 id="new-constructor"><code class="highlighter-rouge">New()</code><span> 初始化</span></h3>
<p><span>您的插件必须定义一个名为New的函数,该函数创建此类型的实例并以形式返回</span><code class="highlighter-rouge">interface{}</code><span><span>。</span><span>在大多数情况下,就是这样:</span></span></p>
<div class="highlighter-rouge copy-code-snippet">
<div class="highlight">
<pre class="highlight"><code>func New() interface{} {
return &MyConfig{}
}
</code></pre>
</div>
</div>
<p><span>您可以向结构中添加更多字段,这些字段将被传递,但是不能保证配置实例的寿命或数量。</span></p>
<h3 id="handling-events"><span>处理事件</span></h3>
<p><span><span>要处理Kong事件,请在您的配置结构中定义相关方法。</span><span>例如,要处理“访问”事件,请定义如下函数:</span></span></p>
<div class="highlighter-rouge copy-code-snippet">
<div class="highlight">
<pre class="highlight"><code>func (conf *MyConfig) Access (kong *pdk.PDK) {
…
}
</code></pre>
</div>
</div>
<p><span>你可以定义事件的方法是</span><code class="highlighter-rouge">Certificate</code><span>,</span><code class="highlighter-rouge">Rewrite</code><span>,</span><code class="highlighter-rouge">Access</code><span>,</span><code class="highlighter-rouge">Preread</code><span>和 </span><code class="highlighter-rouge">Log</code><span><span>。</span><span>它们的签名都是相同的。</span></span></p>
<h2 id="go-pdk-package"><code class="highlighter-rouge">go-pdk</code><span> 包</span></h2>
<p><span>添加</span><code class="highlighter-rouge">"github.com/Kong/go-pdk"</code><span>到导入的程序包。</span><code class="highlighter-rouge">kong</code><span><span>事件处理程序方法上收到</span><span>的</span><span>指针是Go PDK函数的入口点。</span><span>这些功能大多数都与Lua PDK中的相应功能相同。</span></span></p>
<p><span><span>有关</span><span>Go PDK的参考文档,</span><span>请参见</span></span>go-pdk<span> godoc页面。</span></p><br><br>
来源:https://www.cnblogs.com/breg/p/13059797.html
頁:
[1]