在windows环境下搭建kong的插件开发环境

3,471 阅读5分钟

kong插件开发——debug环境搭建

目标

本教程基于Windows10系统,介绍如何搭建出可以在kong运行时进行debug ,获取上下文变量的IDE开发环境,提高kong插件开发效率。

准备

首先需要下载并安装如下软件:

GitBash是windows下的Unix shell,方便向Vagrant输入指令。

Vagrant用来管理VirtualBox,可以提供一个可配置、可移植和复用的软件环境。在这里主要是通过Kong官方提供的Kong-Vagrant镜像来自动化安装和配置Kong在VirtualBox中运行所需的完整环境。

ZeroBrane Studio是轻量型的lua语言开发IDE。

设置Vagrant Kong镜像

首先启动VirtualBox,然后最小化就可以了。

1,选择一个文件夹作为git下载目录,右键 —> Git Bash Here

企业微信截图_15832931507924.png

2,在GitBash中下载kong源码

git clone https://github.com/Mashape/kong

image-20200304114037872.png

3,下载Kong-Vagrant源码,完成后打开kong-vagrant文件夹

git clone https://github.com/Mashape/kong-vagrant
cd kong-vagrant/

4,设置挂载目录。在主机上新建一个文件夹用作挂载目录,比如我设置的挂载目录路径是C:\Users\91646\KongDebug\clone,这个路径需要转换成unix格式,转换之后是/c/Users/91646/KongDebug/clone

转换方式:在这个路径下打开GitBash,输入指令pwd即可获得。

这个文件夹会被挂载到Kong-Vagrant镜像中。

image-20200304120429975.png

启动Kong-Vagrant,同时设置挂载路径(/c/Users/91646/KongDebug/clone/换成上面自己实际设置的路径)

KONG_PATH=/c/Users/91646/KongDebug/clone/ vagrant up

此时挂载目录在虚拟机中的路径是/kong

5,用ssh进入Kong-Vagrant

vagrant ssh

image-20200304121809235.png

把Kong拷贝到主机

以下操作基于上面第5步,进入到vagrant之后。

将所有kong的lua文件从vagrant镜像复制到挂载的主机文件夹

sudo adduser $USER vboxsf
cp -r /usr/local/share/lua/5.1  /kong

重新定位vagrant 中kong的lua文件,链接到挂载的主机文件夹

sudo -i
cd /usr/local/share/lua
mv 5.1 5.1.old
ln -s /kong/5.1 .

现在,vagrant镜像上的目录/usr/local/share/lua/5.1指向其在宿主机上的副本。宿主机上副本的更改也将影响Kong-Vagrant的安装。

此时宿主机上挂载目录下已有/5.1文件夹

image-20200304144426948.png

虚拟机上/kong文件夹下也有/5.1文件夹

image-20200304144701310.png

宿主机上C:\Users\91646\KongDebug\clone=虚拟机上/kong

由于ZeroBrane Studio只能调试一个源文件树(项目位置)中的文件,因此我们需要将kong切入点复制到已挂载的lua源码树上

mkdir /kong/5.1/bin
cp /usr/local/bin/kong /kong/5.1/bin

将kong配置文件复制到相同的位置

cp /usr/local/lib/luarocks/rocks-5.1/kong/2.0.1-0/kong.conf.default /kong/5.1/bin

#生成kong.yml配置文件,方便之后无数据库部署
kong config -c kong.conf init
#同样拷贝kong.yml到相同位置
cp kong.yml /kong/5.1/bin

在Vagrant 镜像中安装ZeroBrane Studio

继续在vagrant镜像中下载ZeroBrane Studio

https://download.zerobrane.com/ZeroBraneStudioEduPack-1.20-linux.sh

安装

sh ZeroBraneStudioEduPack-1.20-linux.sh

会看到一些与GUI安装相关的错误消息,可以忽略这些错误消息,因为我们仅对/opt/zbstudio/lualibs中远程调试所需的lua/so文件感兴趣。

用ZeroBrane Studio打开Kong Plugin

在宿主机上打开ZeroBrane Studio打开C:\Users\91646\KongDebug\clone\5.1

image-20200304145648083.png

在plugin中新建helloworld文件夹,相当于新建了一个名为hellowordld的插件。在helloworld文件夹下新建handler.lua和schema.lua

image-20200304150022295.png

代码如下

handler.lua

package.path = package.path .. ";/opt/zbstudio/lualibs/?/?.lua;/opt/zbstudio/lualibs/?.lua"
package.path = package.path .. ";/opt/zbstudio/lualibs/bin/linux/x64/?.so;/opt/zbstudio/bin/linux/x64/clibs/?.so"

local BasePlugin = require "kong.plugins.base_plugin"

local CustomHandler = BasePlugin:extend()

local resultAns = ">>插件开始运行了\n"

CustomHandler.VERSION = "1.0.0"
CustomHandler.PRIORITY = 10

function CustomHandler:new()
    CustomHandler.super.new(self, "helloworld")
end
function CustomHandler:access(config)
    require('mobdebug').start("10.118.35.121", 8172)
    CustomHandler.super.access(self)
    resultAns = resultAns .. ">>>>>>>执行:access阶段开始\n输出嵌入的内容(请求在还未到达上游服务器):\n"
    resultAns = resultAns .. "kong.version:\t" .. kong.version .. "\n"
    resultAns = resultAns .. "kong.client.get_ip():\t" .. kong.client.get_ip() .. "\n"
    resultAns = resultAns .. "kong.request.get_scheme():\t" .. kong.request.get_scheme() .. "\n"
    resultAns = resultAns .. "kong.request.get_host():\t" .. kong.request.get_host() .. "\n"
    resultAns = resultAns .. "kong.request.get_port()\t:" .. kong.request.get_port() .. "\n"
    resultAns = resultAns .. "kong.request.get_http_version():\t" .. kong.request.get_http_version() .. "\n"
    resultAns = resultAns .. "kong.request.get_method():\t" .. kong.request.get_method() .. "\n"
    resultAns = resultAns .. "kong.request.get_path():\t" .. kong.request.get_path() .. "\n"
    resultAns = resultAns .. "<<<<<<<执行access阶段结束 \n"

    return kong.response.exit(
            200,
            resultAns,
            {
                ["Content-Type"] = "application/json",
                ["WWW-Authenticate"] = "Basic"
            }
    )
end

return CustomHandler

schema.lua

local typedefs = require "kong.db.schema.typedefs"
return {
  name = "helloworld",
  fields = {
      {
          consumer = typedefs.no_consumer
      },
      {
          config = {
              type = "record",
              fields = {
                  -- 这里的username, 会显示在插件配置页
                  {
                      username = {
                          type = "array",
                          elements = {type = "string"},
                          default = {}                            
                      }
                  }
              }
          }
      }
  }
}

宿主机上C:\Users\91646\KongDebug\clone\5.1\bin\文件夹下的kong.conf.default改名为kong.conf

并且修改其中配置,这是kong的启动配置文件

……
#取消注释,修改为无数据库模式启动
database = off 
#加载刚才创建的helloworld插件
plugins = bundled, helloworld

修改同文件夹下的kong.yml如下,kong.yml相当于kong在无数据库模式启动下的配置加载来源

# ------------------------------------------------------------------------------
# This is an example file to get you started with using
# declarative configuration in Kong.
# ------------------------------------------------------------------------------

# Metadata fields start with an underscore (_)
# Fields that do not start with an underscore represent Kong entities and attributes

# _format_version is mandatory,
# it specifies the minimum version of Kong that supports the format

_format_version: "1.1"

# Each Kong entity (core entity or custom entity introduced by a plugin)
# can be listed in the top-level as an array of objects:

services:
- name: example-service
  host: loaclhost
  port: 8000
  path: /
  # Entities can store tags as metadata
  # tags:
  # - example
  # Entities that have a foreign-key relationship can be nested:
  # routes:
  # - name: Mockbin-route
  #   paths:
  #   - /mockbin
  plugins:
  - name: helloworld
# - name: another-service
#   url: https://example.org

routes:
- name: route1
  # Relationships can also be specified between top-level entities,
  # either by name or by id
  service: example-service
  hosts: ["localhost"]
  paths:
  - /index
  # methods: [GET,POST]


# consumers:
# - username: example-user
#   # Custom entities from plugin can also be specified
#   # If they specify a foreign-key relationshp, they can also be nested
#   keyauth_credentials:
#   - key: my-key
#   plugins:
#   - name: rate-limiting
#     _comment: "these are default rate-limits for user example-user"
#     config:
#       policy: local
#       second: 5
#       hour: 10000

# When an entity has multiple foreign-key relationships
# (e.g. a plugin matching on both consumer and service)
# it must be specified as a top-level entity, and not through
# nesting.

# plugins:
# - name: rate-limiting
#   consumer: example-user
#   service: another-service
#   _comment: "example-user is extra limited when using another-service"
#   config:
#     hour: 2
#   # tags are for your organization only and have no meaning for Kong:
#   tags:
#   - extra_limits
#   - my_tag

在vagrant镜像启动kong

cd /kong/5.1/bin/
kong start -c kong.conf
注:如果启动kong以后,通过postman调用报错:"no Route matched with those values",原因是未加载到kong.yml,可以手动加载配置:
命令:http :8001/config config=@kong.yml

image.png

在宿主机上的ZeroBrane Studio中启动Start Debugger Server,并在需要的地方打上断点

image-20200304150920675.png

在宿主机上的postman中向虚拟机上的kong发送一个get请求,可以看到请求一直卡住了

image-20200304151918452.png

宿主机上的ZeroBrane Studio已经入断点所在行,并且Remote Console窗口已出现

image-20200304151641353.png

在Remote Console输入kong的PDK提供的上下文变量,按住Enter来显示

image-20200304152510509.png

参考

lua-programming.blogspot.com/2015/12/how…

docs.konghq.com/2.0.x/db-le…