教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 使用golang进行kong限流插件开发

使用golang进行kong限流插件开发

发布时间:2022-01-05   编辑:jiaochengji.com
教程集为您提供使用golang进行kong限流插件开发等资源,欢迎您收藏本站,我们将为您提供最新的使用golang进行kong限流插件开发资源
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"/></svg>

个人博客原文地址:http://www.lampnick.com/php/950

<h3>rate limiting限流仓库地址</h3>

https://github.com/lampnick/kong-rate-limiting-golang

<h3>
前置条件</h3> <ol><li>获取编译基础镜像(Go插件是使用-buildmode=plugin标志编译的,该标志允许插件服务器动态加载它们。)</li></ol><pre><code>docker pull kong/go-plugin-tool:latest-centos-7 </code></pre> <ol start="2"><li>go-pluginserver可执行文件路径</li></ol><pre><code>默认路径:/usr/local/bin 自定义路径有两种方式: 1.环境变量增加go_pluginserver_exe 2.kong配置文件设置go_pluginserver_exe </code></pre> <ol start="3"><li>go_plugins_dir go插件目录</li></ol><pre><code>kong配置文件中设置go插件的路径,默认值为off,表明禁用go插件支持 </code></pre> <ol start="4"><li>将你编译好的go插件复制到go_plugins_dir</li><li>和lua插件开发一样,需要将你的go插件名称配置到plugins属性中,这样kong才会加载你的插件</li><li>允许你的go插件使用常规模式,可通过Admin API或者声明式配置文件管理</li></ol><h3>构建Go Plugin Server和你的go插件</h3>

go插件服务器( Go Plugin Server )是一个典型的go应用,可使用如下流程

<ol><li>初始化go.mod</li></ol><pre><code>Nick-Mac:kong-go-plugin nick$ go mod init kong-go-plugin go: creating new go.mod: module kong-go-plugin Nick-Mac:kong-go-plugin nick$ cat go.mod module kong-go-plugin go 1.13 </code></pre> <ol start="2"><li>获取Go Plugin Server</li></ol><pre><code>Nick-Mac:kong-go-plugin nick$ go get -d -v github.com/Kong/go-pluginserver go: downloading github.com/Kong/go-pluginserver v0.5.1 go: extracting github.com/Kong/go-pluginserver v0.5.1 go: downloading github.com/Kong/go-pdk v0.5.0 go: extracting github.com/Kong/go-pdk v0.5.0 Nick-Mac:kong-go-plugin nick$ cat go.mod module kong-go-plugin go 1.13 require github.com/Kong/go-pluginserver v0.5.1 // indirect </code></pre> <ol start="3"><li>构建Go Plugin Server,会在当前目录下生成go-pluginserver可执行文件</li></ol><pre><code>Nick-Mac:kong-go-plugin nick$ go build github.com/Kong/go-pluginserver go: finding github.com/Kong/go-pdk v0.5.0 Nick-Mac:kong-go-plugin nick$ ll total 29952 drwxr-xr-x 5 nick staff 160B 9 7 11:23 . drwxr-xr-x 9 nick staff 288B 9 7 11:14 .. -rwxr-xr-x 1 nick staff 15M 9 7 11:23 go-pluginserver -rw-r--r-- 1 nick staff 91B 9 7 11:20 go.mod -rw-r--r-- 1 nick staff 1.2K 9 7 11:20 go.sum </code></pre> <ol start="4"><li>接下来将构建一个go插件,克隆下面的示例仓库,使用使用-buildmode plugin 进行构建,会在当前目录生成一个.so文件</li></ol><pre><code>1.克隆 Nick-Mac:kong-go-plugin-example nick$ git clone https://github.com/Kong/go-plugins.git Cloning into 'go-plugins'... remote: Enumerating objects: 35, done. remote: Counting objects: 100% (35/35), done. remote: Compressing objects: 100% (29/29), done. remote: Total 35 (delta 13), reused 21 (delta 5), pack-reused 0 Unpacking objects: 100% (35/35), done. 2.切到示例目录 Nick-Mac:kong-go-plugin-example nick$ cd go-plugins/ 3.查看有哪些文件 Nick-Mac:go-plugins nick$ ll total 48 drwxr-xr-x 9 nick staff 288B 9 7 11:27 . drwxr-xr-x 3 nick staff 96B 9 7 11:27 .. drwxr-xr-x 12 nick staff 384B 9 7 11:27 .git -rw-r--r-- 1 nick staff 166B 9 7 11:27 Makefile -rw-r--r-- 1 nick staff 367B 9 7 11:27 README.md -rw-r--r-- 1 nick staff 536B 9 7 11:27 go-hello.go -rw-r--r-- 1 nick staff 1.2K 9 7 11:27 go-log.go -rw-r--r-- 1 nick staff 82B 9 7 11:27 go.mod -rw-r--r-- 1 nick staff 1.1K 9 7 11:27 go.sum 4.开始构建 Nick-Mac:go-plugins nick$ go build -buildmode plugin go-hello.go 5.查看文件多了一个go-hello.so Nick-Mac:go-plugins nick$ ll total 4960 drwxr-xr-x 10 nick staff 320B 9 7 11:30 . drwxr-xr-x 3 nick staff 96B 9 7 11:27 .. drwxr-xr-x 12 nick staff 384B 9 7 11:27 .git -rw-r--r-- 1 nick staff 166B 9 7 11:27 Makefile -rw-r--r-- 1 nick staff 367B 9 7 11:27 README.md -rw-r--r-- 1 nick staff 536B 9 7 11:27 go-hello.go -rw-r--r-- 1 nick staff 2.4M 9 7 11:30 go-hello.so -rw-r--r-- 1 nick staff 1.2K 9 7 11:27 go-log.go -rw-r--r-- 1 nick staff 82B 9 7 11:27 go.mod -rw-r--r-- 1 nick staff 1.1K 9 7 11:27 go.sum </code></pre> <h3>
环境一致性约束</h3> <ul><li>所有公共库需要版本一致 <ul><li>Kong/go-pdk</li><li>所有go库文件 (像fmt, rpc, reflect等)</li><li>操作系统库文件, 像libpthread, libc, ld-xxxx等</li></ul></li><li>go编译器版本完全一致</li><li>go环境变量,像<span class="katex--inline"><span class="katex"><span class="katex-mathml"> G O R O O T 、 GOROOT、 </span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"/><span class="mord mathdefault">G</span><span class="mord mathdefault" style="margin-right: 0.02778em;">O</span><span class="mord mathdefault" style="margin-right: 0.00773em;">R</span><span class="mord mathdefault" style="margin-right: 0.02778em;">O</span><span class="mord mathdefault" style="margin-right: 0.02778em;">O</span><span class="mord mathdefault" style="margin-right: 0.13889em;">T</span><span class="mord cjk_fallback">、</span></span></span></span></span>GOPATH等一致</li></ul>

典型的由于环境不一致出现的错误信息如下

<pre><code>failed to open plugin kong: plugin.Open("/path/go-plugins/go-hello"): plugin was built with a different version of package github.com/Kong/go-pdk/bridge </code></pre> <h3>
开发go插件</h3> <h6>go插件开发流程</h6> <ol><li>定义一个结构体类型保存配置文件</li></ol><pre><code>用lua写的插件通过schema来指定怎样读取和验证来自数据库和Admin API中的配置数据。由于GO是静态类型语言,都需要用配置结构体定义 type MyConfig struct { Path string //这里配置的会在konga添加插件时显示出来 Reopen bool } 公有属性将会被配置数据填充,如果希望在数据库中使用不同的名称,可以使用encoding/json加tag的方式 type MyConfig struct { Path string `json:my_file_path` Reopen bool `json:reopen` } </code></pre> <ol start="2"><li>使用New()创建一个实例</li></ol><pre><code>你的go插件必须定义一个名叫New的函数来创建这个类型的实例并返回一个interface{}类型 func New() interface{} { return &MyConfig{} } </code></pre> <ol start="3"><li>添加处理阶段方法</li></ol><pre><code>你可以在请求的生命周期的各个阶段实现自定义的逻辑。如在"access"阶段,定义一个名为Access的方法 func (conf *MyConfig) Access (kong *pdk.PDK) { ... } 你可以实现自定义逻辑的阶段方法有如下几种 Certificate Rewrite Access Preread Log </code></pre> <ol start="4"><li>编译go插件</li><li>将生成的.so文件放到go_plugins_dir定义的目录中</li></ol><h4>部署</h4> <ul><li>kong配置文件修改</li></ul><pre><code>plugins = bundled,nick-rate-limiting go_plugins_dir = /etc/kong/plugins go_pluginserver_exe = /usr/local/bin/go-pluginserver </code></pre> <ul><li>构建go-pluginserver</li></ul><pre><code>在go-pluginserver中执行go build github.com/Kong/go-pluginserver 会生成 go-pluginserver文件,复制到/usr/local/bin目录 </code></pre> <ul><li>编译go插件</li></ul><pre><code>go build -buildmode plugin custom-rate-limiting.go && cp custom-rate-limiting.so </code></pre> <ul><li>将生成的.so文件放到go_plugins_dir定义的目录中</li></ul><pre><code class="lang-.env hljs">cp custom-rate-limiting.so ../plugins/ </code></pre> <ul><li>重启kong</li></ul><pre><code>kong prepare && kong reload - 在konga中配置插件 - 测试请求是否正常,规则是否生效 </code></pre> <h3>问题</h3> <ul><li>kong start -c /etc/kong/kong.conf --vv时报错sh: /usr/local/bin/go-pluginserver: cannot execute binary file</li></ul><pre><code>由于在mac上交叉编译 解决方法: 直接在kong机器上编译go-pluginserver </code></pre> <ul><li>插件报错</li></ul><pre><code>2020/09/07 15:35:52 failed to open plugin go-hello: plugin.Open("/etc/kong/plugins/go-hello.so"): /etc/kong/plugins/go-hello.so: invalid ELF header nginx: [error] init_by_lua error: /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:481: bad argument #1 to 'ipairs' (table expected, got nil) stack traceback: [C]: in function 'ipairs' /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:481: in function 'get_plugin' /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:515: in function 'load_plugin' /usr/local/share/lua/5.1/kong/db/dao/plugins.lua:151: in function 'load_plugin_handler' /usr/local/share/lua/5.1/kong/db/dao/plugins.lua:227: in function 'load_plugin' /usr/local/share/lua/5.1/kong/db/dao/plugins.lua:275: in function 'load_plugin_schemas' /usr/local/share/lua/5.1/kong/init.lua:484: in function 'init' init_by_lua:3: in main chunk stack traceback: [C]: in function 'error' /usr/local/share/lua/5.1/kong/cmd/start.lua:75: in function 'cmd_exec' /usr/local/share/lua/5.1/kong/cmd/init.lua:88: in function </usr/local/share/lua/5.1/kong/cmd/init.lua:88> [C]: in function 'xpcall' /usr/local/share/lua/5.1/kong/cmd/init.lua:88: in function </usr/local/share/lua/5.1/kong/cmd/init.lua:45> /usr/local/bin/kong:9: in function 'file_gen' init_worker_by_lua:49: in function <init_worker_by_lua:47> [C]: in function 'xpcall' init_worker_by_lua:56: in function <init_worker_by_lua:54> 解决方案: 直接在kong机器上编译 </code></pre> <ul><li>访问报错:message: “An unexpected error occurred”</li></ul><pre><code>查看kong管理地址中错误日志路径 http://10.5.24.224:8001/ "nginx_err_logs": "/usr/local/kong/logs/error.log", tail -f /usr/local/kong/logs/error.log 日志报错如下 2020/09/07 16:21:22 [notice] 122415#0: *29 [kong] go.lua:97 go-pluginserver terminated: exit 0, context: ngx.timer 2020/09/07 16:21:22 [notice] 122415#0: *29 [kong] go.lua:86 Starting go-pluginserver, context: ngx.timer 2020/09/07 16:21:22 [crit] 122415#0: *29381 connect() to unix:/usr/local/kong/go_pluginserver.sock failed (2: No such file or directory), client: 10.5.216.251, server: kong, request: "GET /api/index.php?r=site/login-data HTTP/1.1", host: "hd.myscrm.cn:8000" 2020/09/07 16:21:22 [error] 122415#0: *29381 [kong] go.lua:140 [go-hello] trying to connect: no such file or directory, client: 10.5.216.251, server: kong, request: "GET /api/index.php?r=site/login-data HTTP/1.1", host: "hd.myscrm.cn:8000" 2020/09/07 16:21:22 [error] 122415#0: *29381 [kong] go.lua:429 [go-hello] starting instance: no such file or directory, client: 10.5.216.251, server: kong, request: "GET /api/index.php?r=site/login-data HTTP/1.1", host: "hd.myscrm.cn:8000" 2020/09/07 16:21:22 [error] 122415#0: *29381 lua coroutine: runtime error: /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:432: no such file or directory stack traceback: coroutine 0: [C]: in function 'error' /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:432: in function 'get_instance' /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:498: in function </usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:497> coroutine 1: [C]: in function 'resume' coroutine.wrap:21: in function <coroutine.wrap:21> /usr/local/share/lua/5.1/kong/init.lua:757: in function 'access' access_by_lua(nginx-kong.conf:87):2: in main chunk, client: 10.5.216.251, server: kong, request: "GET /api/index.php?r=site/login-data HTTP/1.1", host: "hd.myscrm.cn:8000" 2020/09/07 16:21:22 [error] 122415#0: *29381 [kong] init.lua:759 [go-hello] /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:432: no such file or directory, client: 10.5.216.251, server: kong, request: "GET /api/index.php?r=site/login-data HTTP/1.1", host: "hd.myscrm.cn:8000" </code></pre> <h3>相关截图</h3> <ul><li>

konga json配置

<pre><code>[{ "type": "header,query,body", "key": "orderId", "value": "orderId1,orderId2,orderId3" }, { "type": "query", "key": "username", "value": "nick,jack,star" }] </code></pre> </li><li>

konga 配置

</li><li>

postman 显示header

</li><li>

siege压测效果图

</li></ul> 到此这篇关于“使用golang进行kong限流插件开发”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
使用golang进行kong限流插件开发
golang微服务框架对比_最强开源微服务框架,全网独家整理
Golang 限流器的使用和实现
golang bufio.newscanner如何超时跳出_Golang微服务的熔断与限流
(三)go-kit服务接口限流
基于Jquery的文字自动截取(提供源代码)
golang 面试题(从基础到高级)
Golang多协程并发工作池
SQL2Struct:一款根据sql语句自动生成golang结构体的chrome插件
如何使用 Go 语言进行微服务开发

上一篇:初识 Go 语言 下一篇:golang的channel机制
[关闭]
~ ~