标签归档:Nginx

基于OpenResty 的 WEB 框架 Lor 安装初探

  • 项目介绍:
    • Lor是一个运行在OpenResty上的基于Lua编写的Web框架.
    • 路由采用Sinatra风格,Sinatra是Ruby小而精的web框架.
    • API基本采用了Express的思路和设计,Node.js跨界开发者可以很快上手.
    • 支持插件(middleware),路由可分组,路由匹配支持string/正则模式.
    • lor以后会保持核心足够精简,扩展功能依赖middleware来实现. lor本身也是基于middleware构建的.
    • 推荐使用lor作为HTTP API Server,lor也已支持session/cookie/html template等功能.
    • 框架简单示例项目lor-example
    • 框架全站示例项目openresty-china
  • 项目地址: https://github.com/sumory/lor
  • 文档地址: http://lor.sumory.com

安装lor框架

git clone https://github.com/sumory/lor
cd lor 
make install

此时可能会有报错如下:

/usr/bin/env: "resty": 没有那个文件或目录

原因为lor没有找到resty的执行目录,这个时候只需要找到resty的执行目录并软链过去即可:

sudo ln -s /usr/local/openresty/bin/resty /usr/bin/resty

框架自带一个示例项目,运行一下代码

lord new lor_demo

启动

然后就能在框架中看到lor_demo文件夹,执行如下命令

cd lor_demo
lord start

打开浏览器,输入http://localhost:8888/正常访问,即正常安装。

使用 konga 来管理微服务 API 网关 kong

微服务网关kong有比较多个后台管理面板,比如比较简单的kong-dashboard,还有konga,之前在初探kong的时候,使用的就是比较简单的kong-dashboard,很多功能都没有,而且最近由于kong官方更新比较频繁,1.0之后的kong-dashboard就已经不兼容了,频繁报错,所有今天我就来使用一下另一款kong的后台管理面板:konga

安装konga

在开始安装之前,需要准备的有:

  • 一个已经安装好的kong环境
  • Nodejs >= 8 (推荐8.11.3 LTS)
  • npm

关于这三者的安装,我这里就不赘述了,kong的安装可以在博客的相关文章查看。在做好准备工作之后,就开始安装:

安装npm依赖

$ git clone https://github.com/pantsel/konga.git
$ cd konga
$ npm i

在执行npm i之后,由于会引入很多的npm包,所以可能会有报错,比如我这里就遇到了一些权限问题,比如:

Unable to save binary /home/qianyugang/soft/konga/node_modules/node-sass/vendor/linux-x64-64 : { Error: EACCES: permission denied, mkdir '/home/thinkpad/soft/konga/node_modules/node-sass/vendor'

如果出现了如上错误,可以把最后一个命令修改为

sudo npm i --unsafe-perm=true --allow-root

执行之后,可能会提示:

bower bootstrap-switch extra-resolution Unnecessary resolution: bootstrap-switch#~3.3.4
added 69 packages from 77 contributors and audited 3120 packages in 4.654s
found 275 vulnerabilities (125 low, 24 moderate, 126 high)
  run `npm audit fix` to fix them, or `npm audit` for details

意思是有一些包没有执行好,那么我们就按照它的提示执行一下:

sudo npm audit fix --unsafe-perm=true --allow-root

基本就可以解决npm依赖包的问题了。总之这里是有可能出现各种各样的npm问题,依次解决即可。

初始化数据库

npm的依赖都安装完成之后,就需要复制一下konga目录下的.env_example文件

cp .env_example env

然后把其中的一些配置项目都填写上去。具体的配置项可以查看 https://github.com/pantsel/konga#environment-variables 。这里就主要把以下三项配置好:

DB_ADAPTER=postgres
PORT=1337
DB_URI=postgresql://kong_user:kong_pass@localhost:5432/konga

注意这个DB_URI一定要填写完整,这里的数据库我用的是postgres,konga其实还支持mysql,mongo等多种数据库,这里就不赘述了。配置完成之后,需要登上你自己的postgres数据库,然后执行如下命令新建数据库:

CREATE DATABASE "konga" WITH ENCODING='UTF8';

新建了数据库之后,,执行如下命令,来初始化数据库:

node ./bin/konga.js prepare --adapter postgres --uri postgresql://kong_user:kong_pass@localhost:5432/konga

出现如下提示之后,数据库这一块就完成:

Preparing database...
debug: Hook:api_health_checks:process() called
debug: Hook:health_checks:process() called
debug: Hook:start-scheduled-snapshots:process() called
debug: Hook:upstream_health_checks:process() called
debug: Hook:user_events_hook:process() called
debug: Seeding User...
debug: User seed planted
debug: Seeding Kongnode...
debug: Kongnode seed planted
debug: Seeding Emailtransport...
debug: Emailtransport seed planted
debug: Database migrations completed!

启动konga

执行如下命令:

npm start

看到如下小帆船的图,成功启动


   Sails              <|    .-..-.
   v0.12.14            |\
                      /|.\
                     / || \
                   ,'  |'  \
                .-'.-==|/_--'
                `--'-------' 
   __---___--___---___--___---___--___
 ____---___--___---___--___---___--___-__

最后,打开浏览器输入http://localhost:1337/,就可以进入konga的管理界面了。会出现一个让你注册的界面,注册登录一下,然后配置一下kong的admin-api链接,大功告成,打完收工。

微服务 API 网关 Kong 中文文档发布

由于项目的原因,最近的几个月一直在学习微服务的API网关 Kong ,在这里做一个简单介绍,是一个云原生,高效,可扩展的分布式 API 网关。 自 2015 年在 github 开源后,广泛受到关注,目前已收获 1.68w+ 的 star,其核心价值在于高性能和可扩展性。由于对项目的积极维护,Kong被广泛用于从初创公司到全球5000强以及政府机构的生产中。从技术角度来说,Kong是基于Openresty的一个莹莹,Openresty是基于Nginx的,使用的语言是Lua。

所以在学习过程中,首要是需要看官方文档,由于项目比较新,所以暂时没有中文文档,我就想着,反正文档总是要全部看一遍的,不如自己翻译一份好了,于是乎就有了这个项目:Kong的文档中文版。欢迎大家star&fork。

由于自己不是英语专业,而且主要目的是学习Kong,所以采用的是人工+机翻结合的方式,如果有遇到翻译的不够通顺,或者对于翻译的语句有歧义的地方,麻烦一定点击官网英文文档https://docs.konghq.com/ 查看,并且欢迎提 PR 提修改意见。另,由于kong的文档本身也在不断增加和完善当中,如果有遇到没有即使更新翻译的状况欢迎提issue,我会不断补充的。

todo:

  • 目前文档中的超链接都是链接的英文原文,后续会慢慢改成中文内链。
  • 会在每一页文档里面附上单独的英文原文链接,以便做对照。
  • 会添加kong自带的插件文档。

本文档是基于 https://docs.konghq.com/1.1.x/ 1.1.x 版本,目前官网已经更新至 1.2.x 版本,如果使用的最新版本,请查看 https://docs.konghq.com 并注意差别。

Lua OpenResty 使用 protobuf 和 rabbitmq AMQP 发送和接收消息

项目中有个需求,需要使用Google的protobuf作为压缩协议,然后使用rabbitmq AMQP来发送和接收消息,在研究使用这两个工具中,遇到了有一些坑,之前有写了两篇来介绍分别使用,《 在 lua 中使用 protobuf》和《Lua OpenResty 使用rabbitmq AMQP协议发送和接收消息》 ,这里我们来结合使用一下,然后顺便解决一下lua的相关库的使用问题。

protobuf 相关步骤

1.安装 protoc

首先安装依赖库

sudo apt-get install autoconf automake libtool curl make g++ unzip

下载、解压安装包

curl -L -o protobuf-all-3.6.1.tar.gz  https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protobuf-all-3.6.1.tar.gz
tar -xzvf protobuf-all-3.6.1.tar.gz

进入安装包安装

cd protobuf-all-3.6.1
./configure
make
make check
sudo make install
sudo ldconfig

最后检查是否安装成功

$ protoc --version
libprotoc 3.6.1

2.生成pb文件

需要定义你自己的标准proto文件 xxx.proto 文件(可能不止一个文件,不止一个目录),定义好了之后,使用protoc命令生成.pb文件,命令如下:

protoc --proto_path=proto --descriptor_set_out=common.pb proto/xxxx/*.proto proto/xxxxx/*.proto

其中 --proto_path 参数是你的proto文件目录,--descriptor_set_out 是你需要输出.pb文件的目录,后面几个参数就是具体要引入的.proto文件。这里需要注意的是,有时候会有多个proto文件并且多目录import的情况,这个时候,就需要在参数中都体现出来(命令的最后两个参数),这条命令是把所有的 .proto 文件生成了一个 common.pb 文件方便引入。注意这个common.pb的路径,后面需要用到。

3.安装lua的protobuf库

这里我们使用的是lua-protobuf库。 lua-protobuf实际上是一个纯C的protobuf协议实现,和对应的Lua绑定。

项目地址:https://github.com/starwing/lua-protobuf

可以使用 luarocks 安装lua-protobuf

luarocks install lua-protobuf

如果没有安装 luarocks 可以安装一下luarocks。

rabbitmq AMQP 相关步骤

1.安装第三方库

如果想要在openresty中使用AMQP协议发送和接收消息的话,需要使用到一个第三方库。地址为:https://github.com/4mig4/lua-amqp 。这里你会发现,这个库和《Lua OpenResty 使用rabbitmq AMQP协议发送和接收消息》文章中介绍使用的库不一样,确实是的,因为在使用过程中我发现,之前的那个库还有一些功能不完善,这里使用的这个库是作者fork了之前的那个项目,并改进了里面许多功能。所以最终我选用了这个库来开发。

安装方式为,使用luarocks安装,由于这个库没有push到https://luarocks.org/ 仓库当中,所以我们需要使用到其中的声明文件安装。把项目clone下来之后,找到这个文件 amqp-1.0-4.rockspec 这个文件,然后执行:

luarocks build amqp-1.0-4.rockspec

这里直接执行,可能会报错,报错信息为unrecognized filename extension,意思是识别不了文件格式之类的,这里需要把这个文件中的

source = {
   url = "https://github.com/4mig4/lua-amqp.git",
   tag = "",
}

修改为:

source = {
   url = "https://github.com/4mig4/lua-amqp",
   tag = "",
}

然后继续执行,执行完成之后,就可以在/usr/local/share/lua/5.1目录中看到这个第三方库了,如果整理的文件夹名字不是amqp,而是一个amqp加版本号,可以手动直接把文件夹修改为amqp即可。到此第三方库安装完成。

在使用过程中,我发现一个问题,作者在fork了项目之后,增加了CQUEUES, NGX.SOCKET, SOCKET一些通讯协议功能,但是我本地环境直接运行会报错,查看了一些源码,发现是我的本地环境的cqueues支持有点问题,而作者把这个作为最优先的协议,那么我就把源码文件https://github.com/4mig4/lua-amqp/blob/master/amqp/init.lua 中的local use_cqueues = true改为local use_cqueues = false,即关闭cqueues来使用了。

发送和接收消息

假设你的proto结构体是这样的:

syntax = "proto3";
package aa.bb;
message EventEnvelope {
  string id = 1; 
  int64 created_ts = 2; 
  string server_hash = 3;
  int64 happened_ts = 4; 
  oneof body {
    aa.bb.LoggedOut logged_out = 1501;
  }
message LoggedOut {
  int64 union_id = 1;
  string app_key = 2;
}

发送消息

local function send_pb()

    -- 引入pb库
    local pb   = require "pb"
    -- 加载pb文件
    assert(pb.loadfile("xxxxx/common.pb"))

    -- 这里是你需要发送的pb消息,注意这里是支持嵌套的,如果你的protobuf文件里面有one of,可以直接使用多层嵌套
    -- 这里就根据你自己protobuf结构来就好
    local data    = {
        created_ts  = ngx.now() * 1000,
        server_hash = 'localhost',
        happened_ts = ngx.now() * 1000,
        id          = 8376548368364,
        logged_out  = {
            union_id = 123455666,
            app_key  = xxxxxxxx
        }
    }

    -- 生成需要发送的消息,这个消息是proto压缩之后的,这个`EventEnvelope` 就是最外层的结构体
    local messages = assert(pb.encode("aa.bb.EventEnvelope", data))

    -- 引入amqp第三方库
    local amqp        = require "amqp"

    -- 里面的一些参数就不再赘述了,都是rabbitmq的一些参数
    local ctx = amqp.new({
        role        = "publisher",
        exchange    = "exchangexxxx",
        ssl         = false,
        user        = "guest",
        password    = "guest",
        auto_delete = false,
        routing_key = "routing_keyxxxxx",
        passive     = true,
        no_ack      = true,
        no_wait     = false,
    })
    ctx:connect("127.0.0.1", port)
    ctx:setup()
    local ok, err = ctx:publish(messages)
    if not ok then
        ngx.log(ngx.ERR, "[ -- rabbitmq send failed : -- ] " .. err)
    else
        ngx.log(ngx.ERR, "[ -- rabbitmq send success ]")
    end
end

send_pb("this is a message")

接收消息

可以新建一个consume_queue.lua文件,然后如下代码:


-- 依旧是引入
local amqp            = require "amqp"
local pb              = require "pb"

-- 这里是回调函数
local function consume_local(f)
    print(f) -- 这里就是消息的所有信息,里面包含了properties ,body,frame等信息 
    print(f.body) -- 这里就是消息的主体

       -- 加载pb文件
    assert(pb.loadfile("xxxxx/common.pb"))
    -- 解析消息
    local data = assert(pb.decode("aa.bb.EventEnvelope", f.body))
    print(data) 

end

local amqp        = require "amqp"

local ctx = amqp.new({
    role        = "consumer",
    queue       = "eventbus1", -- 这里可以自定义
    exchange    = "exchangexxxx",
    ssl         = false,
    user        = "guest",
    password    = "guest",
    no_wait     = false,
    routing_key = "routing_keyxxxxx",
    auto_delete = false, -- 是否自动删除消息
    no_ack      = true,
    exclusive   = false, -- 是否为排他队列
    callback    = consume_local, -- 回调函数
    durable     = true,
    passive     = false,
    type        = "topic"

})

ctx:connect("127.0.0.1", port)

local ok, err = ctx:consume()

执行命令开始消费消息

/usr/local/openresty/bin/resty consume_queue.lua

微服务 API 网关 Kong 代理中文文档

原文链接: https://docs.konghq.com/1.1.x/proxy/ (不能保证所有的翻译都是准确无误的,所有如有翻译的不准确或错误之处,请一定记得查看原文,并欢迎留言指出)。

代理

简介

在本文档中,我们将通过详细解释其路由功能和内部工作原理,来了解Kong的代理功能。

Kong公开了几个可以通过两个配置属性调整的接口:

  • proxy_listen:它定义了一个地址/端口列表,Kong将接受来自客户端的公共流量并将其代理到您的上游服务(默认为8000)。
  • admin_listen:它还定义了一个地址和端口列表,但是这些应该被限制为仅由管理员访问,因为它们暴露了Kong的配置功能:Admin API(默认为8001)。

注意:从1.0.0开始,API实体已被删除。本文档将介绍使用新路由和服务实体进行代理。
如果您使用的是0.12或更低版本,请参阅本文档的旧版本。

相关术语

  • client:指下游 downstream 客户向Kong的代理端口发出请求。
  • upstream service:指位于Kong后面的您自己的 API/service ,转发客户端请求。
  • Service:顾名思义,服务实体是每个上游服务的抽象。比如说服务可以是数据转换微服务,一个计费API等。
  • Route:这是指Kong Routes实体。路由是进入Kong的入口点,并定义要匹配的请求的规则,并路由到给定的服务。
  • Plugin:这指的是Kong“插件”,它们是在代理生命周期中运行的业务逻辑。可以通过Admin API配置插件 – 全局(所有传入流量)或特定路由和服务。

概览

从高层次的角度来看,Kong在其配置的代理端口上监听HTTP流量(默认情况下为80008443)。Kong将根据您配置的路由评估任何传入的HTTP请求,并尝试查找匹配的路由。如果给定的请求与特定Route的规则匹配,Kong将处理代理请求。由于每个Route都链接到一个Service,因此Kong将运行您在Route及其相关服务上配置的插件,然后在上游代理请求。

您可以通过Kong的Admin API管理Routes。Routes 的机 hostspsths methods 属性定义用于匹配传入HTTP请求的规则。

如果Kong收到的请求无法与任何已配置的路由匹配(或者如果没有配置路由),它将响应:

HTTP/1.1 404 Not Found
Content-Type: application/json
Server: kong/<x.x.x>

{
    "message": "no route and no Service found with those values"
}

提醒:如何配置服务

配置服务快速入门指南介绍了如何通过[Admin API]配置Kong。

通过向Admin API发送HTTP请求来向Kong添加服务:

curl -i -X POST http://localhost:8001/services/ \
    -d 'name=foo-service' \
    -d 'url=http://foo-service.com'
HTTP/1.1 201 Created
...

{
    "connect_timeout": 60000,
    "created_at": 1515537771,
    "host": "foo-service.com",
    "id": "d54da06c-d69f-4910-8896-915c63c270cd",
    "name": "foo-service",
    "path": "/",
    "port": 80,
    "protocol": "http",
    "read_timeout": 60000,
    "retries": 5,
    "updated_at": 1515537771,
    "write_timeout": 60000
}

该请求指示Kong注册一个名为“foo-service”的服务,该服务指向http://foo-service.com(上游)。

注意:url参数是一个简化参数,用于一次性添加protocolhostportpath

现在,为了通过Kong向这个服务发送流量,我们需要指定一个Route,它作为Kong的入口点:

curl -i -X POST http://localhost:8001/routes/ \
    -d 'hosts[]=example.com' \
    -d 'paths[]=/foo' \
    -d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd'
HTTP/1.1 201 Created
...

{
    "created_at": 1515539858,
    "hosts": [
        "example.com"
    ],
    "id": "ee794195-6783-4056-a5cc-a7e0fde88c81",
    "methods": null,
    "paths": [
        "/foo"
    ],
    "preserve_host": false,
    "priority": 0,
    "protocols": [
        "http",
        "https"
    ],
    "service": {
        "id": "d54da06c-d69f-4910-8896-915c63c270cd"
    },
    "strip_path": true,
    "updated_at": 1515539858
}

我们现在已经配置了一个Route来匹配与给定hostpath匹配的传入请求,并将它们转发到我们配置的foo-service,从而将此流量代理到http://foo-service.com

路由和匹配功能

现在让我们讨论Kong如何匹配针对路由的已配置hostpathmethods属性(或字段)的请求。请注意,所有这三个字段都是可选的,但必须至少指定其中一个。

对于匹配路线的请求:

  • 请求必须包含所有已配置的字段
  • 请求中的字段值必须至少与其中一个配置值匹配(当字段配置接受一个或多个值时,请求只需要其中一个值被视为匹配)

我们来看几个例子。考虑如下配置的路由:

{
    "hosts": ["example.com", "foo-service.com"],
    "paths": ["/foo", "/bar"],
    "methods": ["GET"]
}

与此Route匹配的一些可能请求如下所示:

GET /foo HTTP/1.1
Host: example.com
GET /bar HTTP/1.1
Host: foo-service.com
GET /foo/hello/world HTTP/1.1
Host: example.com

所有这三个请求都满足路径定义中设置的所有条件。但是,以下请求与配置的条件不匹配:

GET / HTTP/1.1
Host: example.com
POST /foo HTTP/1.1
Host: example.com
GET /foo HTTP/1.1
Host: foo.com

所有这三个请求仅满足两个配置条件。第一个请求的路径不匹配配置的路径,第二个请求的HTTP方法和第三个请求的host头也均不匹配。

现在我们了解了hosts, paths, 和 methods属性如何协同工作,让我们分别来看每个属性。

host 请求头

基于其host header 来路由请求是通过Kong代理流量的最直接方式,特别是因为这是HTTP host header 的预期用途。Kong可以通过Route实体的hosts字段轻松完成。

hosts接受多个值,在通过Admin API指定它们时必须以逗号分隔:

hosts接受多个值,这些值很容易在JSON有效负载中表示:

curl -i -X POST http://localhost:8001/routes/ \
    -H 'Content-Type: application/json' \
    -d '{"hosts":["example.com", "foo-service.com"]}'
HTTP/1.1 201 Created
...

但由于Admin API还支持form-urlencoded内容类型,因此您可以通过[]表示法指定数组:

curl -i -X POST http://localhost:8001/routes/ \
    -d 'hosts[]=example.com' \
    -d 'hosts[]=foo-service.com'
HTTP/1.1 201 Created
...

要满足此Route的hosts条件,来自客户端的任何传入请求现在必须将其Host header 设置为以下之一:

Host: example.com

或者

Host: foo-service.com

使用通配符主机名

为了提供灵活性,Kong允许您在hosts字段中指定带通配符的主机名。通配符主机名允许任何匹配的host满足条件,从而匹配给定的Route。

通配符主机名必须在域的最左侧或最右侧标签中仅包含一个星号。例子:

  • *.example.com将匹配诸如a.example.com  x.y.example.com
  • example.* 将匹配诸如example.com  example.org

一个完整的例子如下所示:

{
    "hosts": ["*.example.com", "service.com"]
}

将允许以下请求匹配此路由:

GET / HTTP/1.1
Host: an.example.com
GET / HTTP/1.1
Host: service.com

preserve_host属性

代理时,Kong的默认行为是将上游请求的主机头设置为服务主机中指定的hostpreserve_host字段接受一个布尔标志,指示Kong不要这样做。

例如,当preserve_host属性未更改且Route配置如下:

{
    "hosts": ["service.com"],
    "service": {
        "id": "..."
    }
}

client对Kong的可能请求可能是:

GET / HTTP/1.1
Host: service.com

Kong将从Service的主机属性中提取Host头值,并将发送以下上游请求:

GET / HTTP/1.1
Host: <my-service-host.com>

但是,通过使用preserve_host=true配置Route:

{
    "hosts": ["service.com"],
    "preserve_host": true,
    "service": {
        "id": "..."
    }
}

并假设来自客户的相同请求:

GET / HTTP/1.1
Host: service.com

Kong将根据客户端请求保留Host,并将发送以下上游请求:

GET / HTTP/1.1
Host: service.com

请求路径

路由匹配的另一种方式是通过请求路径。 要满足此路由条件,客户端请求的路径必须以paths属性的值之一为前缀。 例如,使用如下配置的Route:

{
    "paths": ["/service", "/hello/world"]
}

以下请求将被匹配:

GET /service HTTP/1.1
Host: example.com
GET /service/resource?param=value HTTP/1.1
Host: example.com
GET /hello/world/resource HTTP/1.1
Host: anything.com

对于这些请求中的每一个,Kong检测到其URL路径以路由的paths之一为前缀。默认情况下,Kong会在不更改URL路径的情况下代理上游请求。

使用路径前缀进行代理时,首先评估最长路径。这允许您定义两个具有两个路径的Routes:/service/service/resource,并确保前者不会“遮蔽”后者。

在路径中使用正则表达式

Kong通过PCRE(Perl兼容正则表达式)支持Route的路径字段的正则表达式模式匹配。您可以同时将路径作为前缀和正则表达式分配给Route。例如,如果我们考虑以下Route:

{
    "paths": ["/users/\d+/profile", "/following"]
}

此Route将匹配以下请求:

GET /following HTTP/1.1
Host: ...
GET /users/123/profile HTTP/1.1
Host: ...

使用PCRE标志(PCRE_ANCHORED)评估提供的正则表达式,这意味着它们将被约束为在路径中的第一个匹配点(root/character)匹配。

评估顺序

如前所述,Kong按长度评估前缀路径:首先评估最长前缀路径。 但是,Kong将根据路由的regex_priority属性从最高优先级到最低优先级来评估正则表达式路径。这意味着考虑以下Routes:

[
    {
        "paths": ["/status/\d+"],
        "regex_priority": 0
    },
    {
        "paths": ["/version/\d+/status/\d+"],
        "regex_priority": 6
    },
    {
        "paths": ["/version"],
    },
    {
        "paths": ["/version/any/"],
    }
]

在这种情况下,Kong将按以下顺序评估针对以下定义的URI的传入请求:

  1. /version/any/
  2. /version
  3. /version/\d+/status/\d+
  4. /status/\d+

始终在正则表达式路径之前评估前缀路径。

像往常一样,请求仍然必须匹配Route的机hostsmethods属性,并且Kong将遍历您的Routes,直到找到匹配最多规则的路由(请参阅[路由优先级] [代理路由优先级])。

捕获组

也支持正则的捕获组,匹配的组将从路径中提取并可用于插件使用。 如果我们考虑以下正则表达式:

/version/(?<version>\d+)/users/(?<user>\S+)

以及以下请求路径:

/version/1/users/john

Kong会将请求路径视为匹配,如果匹配整个Route(考虑hostsmethods字段),则可以从ngx.ctx变量中的插件获取提取的捕获组:

local router_matches = ngx.ctx.router_matches

-- router_matches.uri_captures is:
-- { "1", "john", version = "1", user = "john" }
规避特殊字符

接下来,值得注意的是,根据RFC 3986,在正则表达式中找到的字符通常是保留字符,因此应该是百分比编码(URL编码)。通过Admin API配置具有正则表达式路径的路由时,请务必在必要时对您的有效负载进行URL编码。例如,使用curl并使用application/x-www-form-urlencodeMIME类型:

curl -i -X POST http://localhost:8001/routes \
    --data-urlencode 'uris[]=/status/\d+'
HTTP/1.1 201 Created
...

请注意,curl不会自动对您的有效负载进行URL编码,并注意使用--data-urlencode,它可以防止Kong的Admin API对+字符进行URL解码,并将其解码为一个空的“。

strip_path属性

可能需要指定路径前缀以匹配路由,但不将其包括在上游请求中。为此,请通过配置如下所示的Route来使用strip_path布尔属性:

{
    "paths": ["/service"],
    "strip_path": true,
    "service": {
        "id": "..."
    }
}

启用此标志会指示Kong在匹配此路由并继续代理服务时,不应在上游请求的URL中包含URL路径的匹配部分。例如,以下客户端对上述路由的请求:

GET /service/path/to/resource HTTP/1.1
Host: ...

将导致Kong发送以下上游请求:

GET /path/to/resource HTTP/1.1
Host: ...

同样,如果在启用了strip_path的Route上定义了正则表达式路径,则将剥离整个请求URL匹配序列。 例:

{
    "paths": ["/version/\d+/service"],
    "strip_path": true,
    "service": {
        "id": "..."
    }
}

以下HTTP请求与提供的正则表达式路径匹配:

GET /version/1/service/path/to/resource HTTP/1.1
Host: ...

请求HTTP方法

methods字段允许根据HTTP方法匹配请求。它接受多个值。其默认值为空(HTTP方法不用于路由)。 以下路由允许通过GETHEAD进行路由:

{
    "methods": ["GET", "HEAD"],
    "service": {
        "id": "..."
    }
}

这样的Route将符合以下要求:

GET / HTTP/1.1
Host: ...
HEAD /resource HTTP/1.1
Host: ...

但它与POSTDELETE请求不匹配。在路由上配置插件时,这允许更多粒度。例如,可以想象两个指向同一服务的路由:一个具有无限制的未经身份验证的GET请求,另一个仅允许经过身份验证和速率限制的POST请求(通过将身份验证和速率限制插件应用于此类请求)。

匹配优先事项

Route可以基于其hosts, paths, 和 methods字段定义匹配规则。要使Kong匹配到路由的传入请求,必须满足所有现有字段。 但是,通过允许两个或多个路由配置包含相同值的字段,Kong允许相当大的灵活性 – 当发生这种情况时,Kong应用优先级规则。

规则是:在评估请求时,Kong将首先尝试匹配具有最多规则的路由。

例如,如果两个路由配置如下:

{
    "hosts": ["example.com"],
    "service": {
        "id": "..."
    }
},
{
    "hosts": ["example.com"],
    "methods": ["POST"],
    "service": {
        "id": "..."
    }
}

第二个Route有一个hosts字段和一个methods字段,因此它将首先由Kong评估。通过这样做,我们避免了第一个用于第二个路径的“阴影”调用。

因此,此请求将匹配第一个Route

GET / HTTP/1.1
Host: example.com

这个请求将匹配第二个:

POST / HTTP/1.1
Host: example.com

遵循这个逻辑,如果要使用hosts字段,methods字段和uris字段配置第三个Route,它将首先由Kong评估。

代理行为

上面的代理规则详细说明了Kong如何将传入请求转发到您的上游服务。下面,我们详细说明Kong与HTTP请求与注册路由匹配的时间与请求的实际转发之间内部发生的情况。

1.负载均衡

Kong实现负载平衡功能,以跨上游服务实例池分发代理请求。

您可以通过查看负载平衡来查找有关配置负载平衡的更多信息

2.插件执行

Kong可通过“插件”进行扩展,这些“插件”将自己挂载在代理请求的请求/响应生命周期中。插件可以在您的环境中执行各种操作 和/或 在代理请求上进行转换。

可以将插件配置为全局(针对所有代理流量)或特定 Routes 和 Services运行。 在这两种情况下,您都必须通过Admin API创建插件配置

一旦路由匹配(及其关联的服务实体),Kong将运行与这些实体中的任何一个相关联的插件。在路由上配置的插件在服务上配置的插件之前运行,否则,通常的插件关联规则适用。

这些配置的插件将运行其access阶段,您可以在插件开发指南中找到更多相关信息。

3.代理和上游超时

一旦Kong执行了所有必要的逻辑(包括插件),它就可以将请求转发给您的上游服务。这是通过Nginx的ngx_http_proxy_module完成的。 您可以通过以下服务属性为Kong和给定上游之间的连接配置所需的超时:

  • upstream_connect_timeout:以毫秒为单位定义建立与上游服务的连接的超时。默认为60000
  • upstream_send_timeout:以毫秒为单位定义用于向上游服务发送请求的两个连续写入操作之间的超时。默认为60000
  • upstream_read_timeout:以毫秒为单位定义用于接收来自上游服务的请求的两个连续读取操作之间的超时。默认为60000

Kong将通过 HTTP/1.1 发送请求,并设置以下headers:

  • Host: <your_upstream_host>,如前文所述。
  • Connection: keep-alive,允许重用上游连接。
  • X-Real-IP: <remote_addr>,其中$remote_addr是ngx_http_core_module提供的名称相同的变量。请注意,$remote_addr可能被ngx_http_realip_module覆盖。
  • X-Forwarded-For: <address>,其中<address>是由附加到具有相同名称的请求标头的ngx_http_realip_module提供的$realip_remote_addr的内容。
  • X-Forwarded-Proto: <protocol>,其中<protocol>是客户端使用的协议。在$realip_remote_addr是可信地址之一的情况下,如果提供,则转发具有相同名称的请求头。否则,将使用ngx_http_core_module提供的$scheme变量的值。
  • X-Forwarded-Host: <host>,其中<host>是客户端发送的主机名。在$realip_remote_addr是可信地址之一的情况下,如果提供,则转发具有相同名称的请求头。否则,将使用ngx_http_core_module提供的$host变量的值。
  • X-Forwarded-Port: <port>,其中<port>是接受请求的服务器的端口。在$realip_remote_addr是可信地址之一的情况下,如果提供,则转发具有相同名称的请求头。否则,将使用ngx_http_core_module提供的$server_port变量的值。

所有其他请求headers都由Kong转发。

使用WebSocket协议时会出现一个例外。如果是这样,Kong将设置以下标头以允许升级客户端和上游服务之间的协议:

  • Connection: Upgrade
  • Upgrade: websocket

有关此主题的更多信息,请参见[Proxy WebSocket流量] [proxy-websocket]部分。

4.错误和重试

每当代理期间发生错误时,Kong将使用底层的Nginx重试机制将请求传递给下一个上游。

这里有两个可配置元素:

  1. 重试次数:可以使用retries属性为每个服务配置。有关详细信息,请参阅Admin API
  2. 究竟是什么构成错误:这里Kong使用Nginx默认值,这意味着在与服务器建立连接,向其传递请求或读取响应头时发生错误或超时。

第二个选项基于Nginx的proxy_next_upstream指令。此选项不能通过Kong直接配置,但可以使用自定义Nginx配置添加。有关详细信息,请参阅配置参考。

5.响应

Kong接收来自上游服务的响应,并以流方式将其发送回下游客户端。此时,Kong将执行添加到 Route 和/或 Service 的后续插件,这些插件在header_filter阶段实现一个钩子。

一旦执行了所有已注册插件的header_filter阶段,Kong将添加以下headers,并将完整的headers发送到客户端:

  • Via: kong/x.x.x,其中x.x.x是正在使用的Kong版本。
  • X-Kong-Proxy-Latency: <latency>,其中latency是Kong收到客户端请求和向上游服务发送请求之间的时间(以毫秒为单位)。
  • X-Kong-Upstream-Latency: <latency>,其中latency是Kong等待上游服务响应的第一个字节的时间(以毫秒为单位)。

将标题发送到客户端后,Kong将开始为实现body_filter钩子的 Route和/或Service 执行已注册的插件。由于Nginx的流媒体特性,可以多次调用此钩子。由这样的body_filter挂钩成功处理的上游响应的每个块被发送回客户端。您可以在插件开发指南中找到有关body_filter钩子的更多信息。

配置一个备用路由

作为Kong的代理功能提供的灵活性的实际用例和示例,让我们尝试实现“后备路线”,因此,为了避免Kong响应HTTP 404,“找不到路由”,我们可以捕获这些请求并将它们代理到特殊的上游服务,或者向它应用插件(例如,这样的插件可以使用不同的状态代码或响应终止请求,而不代理请求)。

以下是此类后备路由的示例:

{
    "paths": ["/"],
    "service": {
        "id": "..."
    }
}

正如您所猜测的,任何向Kong发出的HTTP请求实际上都会匹配此Route,因为所有URI都以根字符/为前缀。正如我们从[请求路径] [代理请求路径]部分所知,最长的URL路径首先由Kong评估,因此/路径最终将由Kong最后评估,并有效地提供“后备”路由,仅作为最后的手段。

为路由配置SSL

Kong提供了一种基于每个连接动态提供SSL证书的方法。SSL证书由核心直接处理,并可通过Admin API进行配置。通过TLS连接到Kong的客户端必须支持服务器名称指示扩展才能使用此功能。

SSL证书由Kong Admin API中的两个资源处理:

  • /certificates,存储您的密钥和证书。
  • /snis,将注册证书与Server Name 指示相关联。

您可以在Admin API参考中找到这两种资源的文档。

以下是在给定路由上配置SSL证书的方法:首先,通过Admin API上传您的SSL证书和密钥:

curl -i -X POST http://localhost:8001/certificates \
    -F "cert=@/path/to/cert.pem" \
    -F "key=@/path/to/cert.key" \
    -F "snis=ssl-example.com,other-ssl-example.com"
HTTP/1.1 201 Created
...

snis表单参数是糖参数,直接插入SNI并将上传的证书与其关联。

您现在必须在Kong内注册以下Route。 为方便起见,我们仅使用Hos header 匹配对此Route的请求:

curl -i -X POST http://localhost:8001/routes \
    -d 'hosts=ssl-example.com,other-ssl-example.com' \
    -d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd'
HTTP/1.1 201 Created
...

您现在可以期望Kong通过HTTPS提供路由:

curl -i https://localhost:8443/ \
  -H "Host: ssl-example.com"
HTTP/1.1 200 OK
...

建立连接并协商SSL握手时,如果您的客户端发送ssl-example.com作为SNI扩展的一部分,Kong将提供先前配置的cert.pem证书。

限制客户端协议(HTTP/HTTPS/TCP/TLS)

路由具有protocols属性,以限制他们应该侦听的客户端协议。此属性接受一组值,可以是“http”“https”“tcp”“tls”

具有httphttps的路由将接受两种协议中的流量。

{
    "hosts": ["..."],
    "paths": ["..."],
    "methods": ["..."],
    "protocols": ["http", "https"],
    "service": {
        "id": "..."
    }
}

未指定任何协议具有相同的效果,因为路由默认为[“http”,“https”]

但是,仅使用https的路由接受通过HTTPS的流量。如果以前从受信任的IP发生SSL终止,它也会接受未加密的流量。当请求来自trusted_ip中的一个配置的IP并且如果设置了X-Forwarded-Proto:https header时,SSL终止被认为是有效的:

{
    "hosts": ["..."],
    "paths": ["..."],
    "methods": ["..."],
    "protocols": ["https"],
    "service": {
        "id": "..."
    }
}

如果上述路由与请求匹配,但该请求是纯文本而没有有效的先前SSL终止,则Kong响应:

HTTP/1.1 426 Upgrade Required
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: Upgrade
Upgrade: TLS/1.2, HTTP/1.1
Server: kong/x.y.z

{"message":"Please use HTTPS protocol"}

从Kong 1.0开始,可以使用protocols属性中的“tcp”为原始TCP(不一定是HTTP)连接创建路由:

{
    "hosts": ["..."],
    "paths": ["..."],
    "methods": ["..."],
    "protocols": ["tcp"],
    "service": {
        "id": "..."
    }
}

同样,我们可以使用“tls”值创建接受原始TLS流量(不一定是HTTPS)的路由:

{
    "hosts": ["..."],
    "paths": ["..."],
    "methods": ["..."],
    "protocols": ["tls"],
    "service": {
        "id": "..."
    }
}

仅具有TLS的路由仅接受通过TLS的流量。 也可以同时接受TCP和TLS:

{
    "hosts": ["..."],
    "paths": ["..."],
    "methods": ["..."],
    "protocols": ["tcp", "tls"],
    "service": {
        "id": "..."
    }
}

代理WebSocket流量

由于底层的Nginx实现,Kong支持WebSocket流量。如果希望通过Kong在客户端和上游服务之间建立WebSocket连接,则必须建立WebSocket握手。这是通过HTTP升级机制完成的。这是您的客户要求对Kong的看法:

GET / HTTP/1.1
Connection: Upgrade
Host: my-websocket-api.com
Upgrade: WebSocket

这将使Kong将ConnectionUpgrade header 转发到您的上游服务,而不是由于标准HTTP代理的逐跳特性而将其解除。

WebSocket和TLS

Kong将在其各自的httphttps端口接受wswss连接。要从客户端强制执行TLS连接,请将Route的protocols属性设置为https

将 Service 设置为指向上游WebSocket服务时,应仔细选择要在Kong和上游之间使用的协议。如果要使用TLS(wss),则必须使用服务protocol属性中的https协议和正确的端口(通常为443)定义上游WebSocket服务。要在没有TLS(ws)的情况下进行连接,则应在协议中使用http协议和端口(通常为80)。

如果您希望Kong终止SSL/TLS,您只能从客户端接受wss,而是通过纯文本或ws代理上游服务。

结论

通过本指南,我们希望您了解Kong的基础代理机制,从请求如何匹配路由到其关联的服务,到如何允许使用WebSocket协议或设置动态SSL证书。

该网站是开源的,可以在 https://github.com/Kong/docs.konghq.com 找到。 如果您还没有,我们建议您还阅读负载平衡参考,因为它与我们刚刚介绍的主题密切相关。

在 lua 中使用 protobuf

安装protobuf

具体步骤可以参考官方文档https://github.com/protocolbuffers/protobuf/blob/master/src/README.md

这里只列出一些其中比较的重要的步骤。

先安装一些依赖的库

sudo apt-get install autoconf automake libtool curl make g++ unzip

然后下载需要的安装包

curl -L -o protobuf-all-3.6.1.tar.gz  https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protobuf-all-3.6.1.tar.gz

接着解压

tar -xzvf protobuf-all-3.6.1.tar.gz

解压完成后进目录

cd protobuf-all-3.6.1

执行安装命令

./configure
make
make check
sudo make install
sudo ldconfig

最后检查是否安装成功

$ protoc --version
libprotoc 3.6.1

安装lua-protobuf

lua-protobuf 实际上是一个纯C的protobuf协议实现,和对应的Lua绑定。

项目地址:https://github.com/starwing/lua-protobuf

可以使用 luarocks 安装lua-protobuf

luarocks install lua-protobuf

如果没有安装 luarocks 可以安装一下luarocks。

使用prortobuf

首先,需要定义你自己的标准proto文件 xxx.proto 文件(可能不止一个文件,不止一个目录),定义好了之后,使用protoc生成pb文件,命令如下:

protoc --proto_path=proto --descriptor_set_out=common.pb proto/xxxx/*.proto proto/xxxxx/*.proto

这里需要注意的是,有时候会有多个proto文件并且多目录import的情况,这个时候,就需要在参数中都体现出来(命令的最后两个参数),这条命令是把所有的 .proto 文件生成了一个 common.pb 文件方便引入。

最后就可以在lua代码中如下使用

-- 引入pb库
local pb = require "pb"

-- load pb文件
assert(pb.loadfile "common.pb" )

-- lua table data
local data = {
    aaa = 123456,
    bbb = "bbbbb"
}

-- 把一个lua table数据encode成二进制文件
local bytes = assert(pb.encode("dd01.account", data))
print(pb.tohex(bytes))

-- 把一个二进制文件decode为lua table
local data2 = assert(pb.decode("dd01.account", bytes))
print(cjson_encode(data2))

如果能看到正常打印出来,说明就成功了。

参考链接

微服务 API 网关 Kong 插件开发 – 插件配置

原文地址:https://docs.konghq.com/1.1.x/plugin-development/plugin-configuration/(不能保证所有的翻译都是准确无误的,所有如有翻译的不准确或错误之处,请一定记得查看原文,并欢迎留言指出)。

简介

大多数情况下,您的插件可以配置为满足您的所有用户需求。当插件被执行的时候,您的插件的配置存储在Kong的数据存储区中,以检索它并将其传递给handler.lua方法。

配置由Kong中的Lua表组成,我们称之为 schema。它包含用户在通过Admin API启用插件时将设置的键/值属性。Kong为您提供了一种验证用户插件配置的方法。

当用户向Admin API发出请求以启用或更新给定Service,Route和/或Consumer上的插件时,将根据您的架构schema插件的配置。

例如,用户执行以下请求:

$ curl -X POST http://kong:8001/services/<service-name-or-id>/plugins/ \
    -d "name=my-custom-plugin" \
    -d "config.foo=bar"

如果配置对象的所有config都根据您的模式有效,则API将返回201 Created,并且插件将与其配置一起存储在数据库中(在这种情况下为{foo =“bar”})。如果配置无效,Admin API将返回400 Bad Request和相应的错误消息。

模块

kong.plugins.<plugin_name>.schema

schema.lua规范

此模块将返回一个Lua表,其中包含将定义用户以后如何配置插件的属性的属性。 可用的属性是:

属性名称 Lua type 默认值 描述
no_consumer Boolen false 如果为true,则无法将此插件应用于特定的Consumer。此插件必须仅应用于服务和路由。例如:身份验证插件。
fields Table {} 你插件的schema,可用属性及其规则的键/值表。
self_check Function nil 如果要在接受插件配置之前执行任何自定义验证,则要实现的功能。

self_check函数必须按如下方式实现:

-- @param `schema` 描述插件配置的架构(规则)的表。
-- @param `config` 当前插件配置的键/值表。
-- @param `dao` DAO的一个实例 (查看 DAO 章节).
-- @param `is_updating` 一个布尔值,指示是否在更新的上下文中执行此检查。
-- @return `valid` 一个布尔值,指示插件的配置是否有效。
-- @return `error` 一个 DAO 错误 (查看 DAO 章节)

以下是一个可能的schema.lua文件的示例:

return {
  no_consumer = true, -- 此插件仅适用于服务或路由,
  fields = {
    -- 在此处描述您的插件配置架构。
  },
  self_check = function(schema, plugin_t, dao, is_updating)
    -- 执行任何自定义验证
    return true
  end
}

描述您的配置schema

schema.lua文件的fields自选描述了插件配置的schema。它是一个灵活的键/值表,其中每个键都是插件的有效配置属性,每个键都是一个描述该属性规则的表。例如:

 fields = {
    some_string = {type = "string", required = true},
    some_boolean = {type = "boolean", default = false},
    some_array = {type = "array", enum = {"GET", "POST", "PUT", "DELETE"}}
  }

以下是属性的规则列表:

规则 LUA TYPE(S) 可使用的值 描述
type string “id”, “number”, “boolean”, “string”, 
“table”, “array”, “url”, “timestamp”
验证属性的类型。
required boolean 默认值:false。
如果为true,则该属性必须存在于配置中。
unique boolean 默认值:false。
如果为true,则该值必须是唯一的(请参阅下面的注释)。
default any 如果未在配置中指定该属性,则将该属性设置为给定值。
immutable boolean 默认值:false。
如果为true,则在创建插件配置后将不允许更新该属性。
enum table 属性的可接受值列表。不接受此列表中未包含的任何值。
regex string 用于验证属性值的正则表达式。
schema table 如果属性的类型是table,则定义用于验证这些子属性的模式。
func function 用于对属性执行任何自定义验证的函数。请参阅后面的示例,了解其参数和返回值。
  • type:将转换从请求参数中检索的值。如果类型不是本机Lua类型之一,则会对其执行自定义验证:
    • id:必须是string
    • timestamp:必须是nember
    • uri:必须是有效的URL
    • array:必须是整数索引表(相当于Lua中的数组)。在Admin API中,可以通过在请求的正文中使用不同值的属性键的多次来发送这样的数组,或者通过单个body参数以逗号分隔。
  • unique:此属性对插件配置没有意义,但在插件需要在数据存储区中存储自定义实体时使用。
  • schema:如果您需要对嵌套属性进行深化验证,则此字段允许您创建嵌套模式。模式验证是递归的。任何级别的嵌套都是有效的,但请记住,这会影响插件的可用性。
  • 附加到配置对象但schema中不存在的任何属性也将使所述配置无效。

例子

key-auth插件的schema.lua文件定义了API密钥的可接受参数名称的默认列表,以及默认设置为false的布尔值:

-- schema.lua
return {
  no_consumer = true,
  fields = {
    key_names = {type = "array", required = true, default = {"apikey"}},
    hide_credentials = {type = "boolean", default = false}
  }
}

于是,当在handler.lua中实现插件的access()函数并且用户使用默认值启用插件时,您可以如下:

-- handler.lua
local BasePlugin = require "kong.plugins.base_plugin"
local CustomHandler = BasePlugin:extend()

function CustomHandler:new()
  CustomHandler.super.new(self, "my-custom-plugin")
end

function CustomHandler:access(config)
  CustomHandler.super.access(self)

  kong.log.inspect(config.key_names)        -- {"apikey"}
  kong.log.inspect(config.hide_credentials) -- false
end

return CustomHandler

请注意,上面的示例使用插件开发工具包(PDK)kong.log.inspect函数将这些值打印到Kong日志中。

一个更复杂的示例,可用于最终日志记录插件:

-- schema.lua

local function server_port(given_value, given_config)
  -- 自定义验证
  if given_value > 65534 then
    return false, "port value too high"
  end

  -- 如果环境是“开发”,8080将是默认端口
  if given_config.environment == "development" then
    return true, nil, {port = 8080}
  end
end

return {
  fields = {
    environment = {type = "string", required = true, enum = {"production", "development"}}
    server = {
      type = "table",
      schema = {
        fields = {
          host = {type = "url", default = "http://example.com"},
          port = {type = "number", func = server_port, default = 80}
        }
      }
    }
  }
}

这样的配置将允许用户将配置发布到您的插件,如下所示:

curl -X POST http://kong:8001/services/<service-name-or-id>/plugins \
    -d "name=my-custom-plugin" \
    -d "config.environment=development" \
    -d "config.server.host=http://localhost"

以下内容将在handler.lua中提供:

-- handler.lua
local BasePlugin = require "kong.plugins.base_plugin"
local CustomHandler = BasePlugin:extend()

function CustomHandler:new()
  CustomHandler.super.new(self, "my-custom-plugin")
end

function CustomHandler:access(config)
  CustomHandler.super.access(self)

  kong.log.inspect(config.environment) -- "development"
  kong.log.inspect(config.server.host) -- "http://localhost"
  kong.log.inspect(config.server.port) -- 8080
end

return CustomHandler

您还可以在Key-Auth插件源代码中查看schema的真实示例。

微服务 API 网关 Kong 插件开发 – 安装/卸载插件

原文地址:https://docs.konghq.com/1.1.x/plugin-development/entities-cache/ (不能保证所有的翻译都是准确无误的,所有如有翻译的不准确或错误之处,请一定记得查看原文,并欢迎留言指出)。

介绍

Kong的自定义插件由Lua源文件组成,这些源文件需要位于每个Kong节点的文件系统中。本指南将为您提供逐步说明,使Kong节点了解您的自定义插件。这些步骤应该应用于Kong集群中的每个节点,以确保每个节点上都有自定义插件。

打包源

您可以使用常规打包策略(例如tar),也可以使用LuaRocks包管理器为您执行此操作。我们推荐使用LuaRocks,因为它在使用其中一个官方分发包时与Kong一起安装。

使用LuaRocks时,您必须创建一个rockspec文件,用来指定包的内容。有关示例,请参阅Kong插件模板,有关该格式的更多信息,请参阅有关rockspecs的LuaRocks文档

使用以下命令打包你的rock(来自插件仓库):

# install it locally (based on the `.rockspec` in the current directory)
$ luarocks make

# 打包已安装的rock
$ luarocks pack <plugin-name> <version>

假设你的插件rockspec的名字为kong-plugin-myPlugin-0.1.0-1.rockspec,上面就会变成:

$ luarocks pack kong-plugin-myPlugin 0.1.0-1

LuaRocks pack命令现在已经创建了一个.rock文件(这只是一个包含安装rock所需内容的zip文件)。

如果您不使用或不能使用LuaRocks,则使用tar将插件所包含的.lua文件打包到.tar.gz存档中。 如果目标系统上有LuaRocks,也可以包含.rockspec文件。

该插件的内容应该接近以下内容:

$ tree <plugin-name>
<plugin-name>
├── INSTALL.txt
├── README.md
├── kong
│   └── plugins
│       └── <plugin-name>
│           ├── handler.lua
│           └── schema.lua
└── <plugin-name>-<version>.rockspec

安装插件

要使Kong节点能够使用自定义插件,必须在主机的文件系统上安装自定义插件的Lua源。有多种方法:通过LuaRocks,或手动。 选择一个,然后跳转到第3部分。

  1. 来自新建的’rock’的LuaRocks。
    .rock文件是一个自包含的软件包,可以在本地安装,也可以从远程服务器安装。
    如果您的系统中安装了luarocks实用程序(如果使用其中一个官方安装包,可能就是这种情况),您可以在LuaRocks树(LuaRocks安装Lua模块的目录)中安装“rock”。
    它可以通过以下方式安装:

     $ luarocks install <rock-filename>
    

    文件名可以是本地名称,或任何支持的方法。
    例如:http://myrepository.lan/rocks/myplugin-0.1.0-1.all.rock

  2. 从源档案中通过LuaRocks安装。 如果您的系统中安装了luarocks实用程序(如果使用其中一个官方安装包,可能就是这种情况),您可以在LuaRocks树(LuaRocks安装Lua模块的目录)中安装Lua源代码。
    您可以通过将当前目录更改为提取的存档来实现,其中rockspec文件是:

     $ cd <plugin-name>
    

    然后运行以下命令:

     $ luarocks make
    

    这将在系统的LuaRocks树中的kong/plugins/<plugin-name>中安装Lua源代码,其中所有的Kong源都已存在。

  3. 手动
    安装插件源的一种更保守的方法是避免“污染”LuaRocks树,而是将Kong指向包含它们的目录。
    这是通过调整Kong配置的lua_package_path属性来完成的。如果你熟悉它,那么这个属性是Lua VM的LUA_PATH变量的别名。
    这些属性包含以分号分隔的目录列表,用于搜索Lua源。它应该在您的Kong配置文件中设置如下:

     lua_package_path = /<path-to-plugin-location>/?.lua;
    

    继续:
    4./<path-to-plugin-location>是包含提取的存档的目录的路径。它应该是归档中kong目录的位置。
    5.?是一个占位符,将被kong.plugins替换。<plugin-name>当Kong将尝试加载你的插件。
    6.;;“默认Lua路径”的占位符。不要改变它。
    例如:
    插件位于文件系统上,使处理程序文件为:

     /usr/local/custom/kong/plugins/<something>/handler.lua
    

    kong目录的位置是:/usr/local/custom,因此正确的路径设置将是:

     lua_package_path = /usr/local/custom/?.lua;;
    

    多个插件:

    如果您希望以这种方式安装两个或更多自定义插件,可以将变量设置为:

      lua_package_path = /path/to/plugin1/?.lua;/path/to/plugin2/?.lua;;
    
     7.`;`是目录之间的分隔符。
     8.`;;`仍然意味着“默认的Lua路径”。
    

    注意:您还可以通过其等效的环境变量KONG_LUA_PACKAGE_PATH设置此属性。

提醒:无论您使用哪种方法来安装插件的源,您仍必须为Kong群集中的每个节点执行此操作。

加载插件

您现在必须将自定义插件的名称添加到Kong配置中的插件列表中(在每个Kong节点上):

plugins = bundled,<plugin-name>

或者,如果您不想包含默认捆绑的插件:

plugins = <plugin-name>

或者

plugins = plugin1,plugin2

注意:您还可以通过其等效的环境变量KONG_PLUGINS来设置此属性。 提醒:不要忘记更新Kong群集中每个节点的plugins指令。 提醒:插件重启后会生效:

kong restart

但是,如果你想在kong永不停止时应用插件,你可以使用:

kong prepare
kong reload

验证加载插件

你现在应该能够毫无问题地启动Kong。 请参阅自定义插件有关如何在服务,路由或消费者实体上启用/配置插件的说明。

为确保您的插件由Kong加载,您可以使用调试日志级别启动Kong:

log_level = debug

或者

KONG_LOG_LEVEL=debug

然后,您应该看到正在加载的每个插件的以下日志:

[debug] Loading plugin <plugin-name>

删除插件

完全删除插件有三个步骤。

  1. 从您的Kong Service或Route配置中删除插件。确保它不再适用于全局,也不适用于任何服务,路由或使用者。对于整个Kong集群,只需执行一次,不需要重新启动/重新加载。此步骤本身将使插件不再使用。但它仍然可用,仍然可以重新应用插件。
  2. plugins指令中删除插件(在每个Kong节点上)。确保在执行此操作之前已完成步骤1。在此步骤之后,任何人都无法将插件重新应用于任何Kong Service,Route,Consumer甚至全局。此步骤需要重新启动/重新加载Kong节点才能生效。
  3. 要彻底删除插件,请从每个Kong节点中删除与插件相关的文件。在删除文件之前,请确保已完成步骤2,包括重新启动/重新加载Kong。如果你使用LuaRocks来安装插件,你可以使用luarocks remove <plugin-name>来删除它。

分发插件

这样做的首选方法是使用LuaRocks,Lua模块的包管理器。它称这些模块为“rocks”。 您的模块不必存在于Kong存储库中,但如果您希望维护Kong设置,则可能就是这样。

通过在rockspec文件中定义模块(及其最终依赖项),您可以通过LuaRocks在您的平台上安装这些模块。

您也可以在LuaRocks上传模块并将其提供给所有人!

有关示例,请参阅Kong插件模板,有关该格式的更多信息,请参阅有关rockspecs的LuaRocks文档

故障排除

由于以下几个原因,配置错误的自定义插件可能无法启动:

  • “plugin is in use but not enabled” -> 您从另一个节点配置了一个自定义插件,并且该插件配置在数据库中,但您尝试启动的当前节点在其plugins指令中没有它。要解决此问题,请将插件的名称添加到节点的plugins指令中。
  • “plugin is enabled but not installed” -> 插件的名称出现在plugins指令中,但是Kong无法从文件系统加载handler.lua源文件。要解决此问题,请确保正确设置lua_package_path指令以加载此插件的Lua源。
  • “no configuration schema found for plugin” -> 插件已在plugins指令中安装,但是Kong无法从文件系统加载schema.lua源文件。要解决此问题,请确保schema.lua文件与插件的handler.lua文件一起存在。

微服务 API 网关 Kong 命令行中文文档

原文链接: https://docs.konghq.com/1.0.x/cli/
(如有翻译的不准确或错误之处,欢迎留言指出)

介绍

提供的CLI(命令行界面Command Line Interface)允许启动,停止和管理Kong实例。CLI可以管理本地节点(如在当前计算机上)。

如果您还没有使用,我们建议您阅读配置参考

通用标志参数

所有命令都将一组特殊的可选标志作为参数:

  • --help:打印此命令的帮助信息
  • --v:启用详细模式
  • --vv:启用调试模式(很多输出)

可用命令

kong check

Usage: kong check <conf>

检查给定Kong配置文件的有效性。

<conf> (default /etc/kong/kong.conf) 配置文件

kong health

Usage: kong health [OPTIONS]

验证Kong 的服务组件是否正常运行

Options:
 -p,--prefix      (可选参数) Kong运行位置的前缀

kong migrations

Usage: kong migrations COMMAND [OPTIONS]

管理数据库迁移。

可用的命令如下:
  bootstrap                         引导数据库并运行全部迁移(初始化)。

  up                                运行新迁移。

  finish                            完成正在等待中的迁移命令,在执行`up`后。

  list                              列出已执行的迁移。

  reset                             重置数据库。

Options(可选):
 -y,--yes                           假设提示“yes”,并运行非交互模式

 -q,--quiet                         忽略所有输出

 -f,--force                         依旧执行迁移,即使数据库报告已经执行过了。

 --db-timeout     (default 60)      超时时间,以秒为单位,所有数据库操作通用(包括Cassandra的schema consensus)。

 --lock-timeout   (default 60)      超时时间,以秒为单位, 节点等待领导节点迁移完成。

 -c,--conf        (optional string) 配置文件。

kong prepare

此命令用来准备Kong前缀文件夹及其子文件夹和文件。

Usage: kong prepare [OPTIONS]

在配置的前缀目录中准备Kong前缀。这个命令可以用于从nginx二进制文件启动Kong而不使用`kong start`命令。

Example usage:
  kong migrations up
  kong prepare -p /usr/local/kong -c kong.conf
  nginx -p /usr/local/kong -c /usr/local/kong/nginx.conf

Options:
  -c,--conf       (optional string) 配置文件
  -p,--prefix     (optional string) 覆盖前缀目录
  --nginx-conf    (optional string) 自定义Nginx配置模板

kong quit

Usage: kong quit [OPTIONS]

优雅地退出一个正在运行的Kong节点(Nginx和其他节点)在给定的前缀目录中配置的服务。

此命令将会向Nginx发送SIGQUIT信号,表示全部请求将在关闭之前完成处理。
如果达到超时延迟,则该节点将被强制执行停止(SIGTERM)

Options:
 -p,--prefix      (optional string) kong正在运行的前缀
 -t,--timeout     (default 10) 强制停止前的超时

kong reload

Usage: kong reload [OPTIONS]

重新加载Kong节点(并启动其他已配置的服务)在给定的前缀目录中。

此命令将HUP信号发送到Nginx,它将生成workers(告知account配置变更),当他们处理完成当前的请求后就停止旧的。

Options:
  -c,--conf       (optional string) 配置文件
  -p,--prefix     (optional string) 覆盖前缀目录
  --nginx-conf    (optional string) 自定义Nginx配置模板

kong restart

Usage: kong restart [OPTIONS]

重新启动Kong节点(以及其他配置的服务,如Serf)在给定的前缀目录中。

这个命令相当于同时执行`kong stop`和`kong start`。

Options:
 -c,--conf        (optional string)   配置文件
 -p,--prefix      (optional string)   Kong运行的前缀
 --nginx-conf     (optional string)   自定义Nginx配置模板
 --run-migrations (optional boolean)  可选地在DB上运行迁移
 --db-timeout     (default 60)
 --lock-timeout   (default 60)

kong start

Usage: kong start [OPTIONS]

在配置中启动Kong(Nginx和其他配置的服务)。

Options:
 -c,--conf        (optional string)   配置文件。

 -p,--prefix      (optional string)   覆盖前缀目录。

 --nginx-conf     (optional string)   自定义Nginx配置模板。

 --run-migrations (optional boolean)  在开始之前运行迁移。

 --db-timeout     (default 60)      超时时间,以秒为单位,所有数据库操作通用(包括Cassandra的schema consensus)。

 --lock-timeout   (default 60)      超时时间,以秒为单位, 节点等待领导节点迁移完成。

kong stop

Usage: kong stop [OPTIONS]

停止给定的正在运行的Kong节点(Nginx和其他已配置的服务)在指定的前缀目录。

此命令将SIGTERM信号发送到Nginx。

Options:
 -p,--prefix      (optional string) Kong运行的前缀

kong version

Usage: kong version [OPTIONS]

打印kong的版本。
使用-a选项,将打印所有底层依赖项的版本。

Options:
 -a,--all         获取所有依赖项的版本

微服务 API 网关 Kong 1.0.0 升级指南

原文地址:https://docs.konghq.com/1.0.x/upgrading/#2-deprecation-notices (不能保证所有的翻译都是准确无误的,所有如有翻译的不准确或错误之处,请一定记得查看原文,并欢迎留言指出)。

注意:以下是1.0.x的升级指南。 如果您要升级到Kong的早期版本,请阅读Kong repo中的UPGRADE.md文件。

本指南将告知您在升级时应了解的重大更改,并指导您完成正确的步骤,以便在不同的升级方案中获得不需要停止服务的迁移。

升级到 1.0.0

此版本(1.0.0) 是Kong的主要版本,包括许多新功能以及重大变化。
这个版本中引入了新的插件架构格式,Admin API 终端的更改,数据库迁移,Nginx配置更改以及已删除的配置属性。
在此版本中,将删除 API 及其相关的Admin API 终端。
本节将重点介绍在升级之前需要注意的重大更改,并将介绍建议的升级路径。我们建议您查阅完整的1.0.0更新日志,以获取更改和新功能的完整列表。

1.突破性修改

依赖

  • 所需的OpenResty版本是1.13.6.2,但是对于完整的功能集,包括具有相互TLS的流路由和服务网格功能,您需要Kong的openresty-patches
  • 所需的最低OpenSSL版本为1.1.1。如果您手动构建,请确保使用相同的OpenSSL版本编译所有依赖项(包括LuaRocks模块)。如果您从我们的某个分发包中安装Kong,则不会受此更改的影响。

配置

  • 删除了custom_plugins 指令(自0.14.0起不推荐使用)。请改用plugin,您不仅可以使用插件来启用自定义插件,还可以禁用自带的捆绑插件。
  • cassandra_lb_policy的默认值从Round Robin更改为Request Round Robin
  • Kong为其流路由生成了一个新的模板文件nginx-kong-stream.conf,该文件包含在其顶级Nginx配置文件的stream块中。如果您使用自定义Nginx配置并希望使用流路由,则可以使用kong prepare生成此文件。
  • Nginx配置文件已更改,这意味着如果使用自定义模板,则需要更新它:
diff --git a/kong/templates/nginx_kong.lua b/kong/templates/nginx_kong.lua
index d4e416bc..8f268ffd 100644
--- a/kong/templates/nginx_kong.lua
+++ b/kong/templates/nginx_kong.lua
@@ -66,7 +66,9 @@ upstream kong_upstream {
     balancer_by_lua_block {
         Kong.balancer()
     }
+> if upstream_keepalive > 0 then
     keepalive $;
+> end
 }

 server {
@@ -85,7 +87,7 @@ server {
 > if proxy_ssl_enabled then
     ssl_certificate $;
     ssl_certificate_key $;
-    ssl_protocols TLSv1.1 TLSv1.2;
+    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
     ssl_certificate_by_lua_block {
         Kong.ssl_certificate()
     }
@@ -200,7 +202,7 @@ server {
 > if admin_ssl_enabled then
     ssl_certificate $;
     ssl_certificate_key $;
-    ssl_protocols TLSv1.1 TLSv1.2;
+    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

     ssl_session_cache shared:SSL:10m;
     ssl_session_timeout 10m;

核心

  • 将删除API实体和相关概念,例如/apis终端。自0.13.0起,这些已被弃用。而是使用Routes配置终端,Services以配置上游服务。
  • 删除旧的DAO实现(kong.dao),其中包括旧的模式验证库。这对插件开发人员有影响,如下所示。
    • 转换为新DAO实现的最后剩余实体是Plugins,Upstreams和Targets。这会对下面列出的Admin API产生影响。

插件

kong 1.0.0标志着插件开发套件(PDK)1.0.0版的推出。与版本0.14相比,PDK没有进行重大更改,但现在可以删除一些可能由自定义插件使用的较旧的非PDK功能。

  • 插件现在使用新DAO实现引入的新模式格式,用于插件模式(在schema.lua中)和自定义DAO实体(daos.lua)。为了简化插件的转换,1.0中的插件加载器包含了一个为schema.lua的自动转换器,对于许多插件来说应该足够了(在1.0.0rc1中,我们的自带捆绑插件使用了自动转换器;它们们现在使用的是新格式)。
    • 如果您在schema.lua中使用旧格式的插件无法加载,请检查自动转换器生成的消息的错误日志。如果无法自动转换字段,则可以通过向格式的字段表转换添加new_type条目来逐步转换模式文件。例如,请参阅1.0.0rc1中的key-auth架构new_type注释被Kong 0.x忽略。
    • 如果您的自定义插件使用自定义DAO对象(如果它包含daos.lua文件),则需要将其转换为新格式。代码也需要相应调整,用kong.db代替singletons.daokong.dao的使用(注意,这个模块暴露了与旧DAO实现不同的API)。
  • 现已删除了在0.14.0中由PDK替换其功能的ome Kong模块:
    • kong.tools.ip:改为用PDK中的kong.ip
    • kong.tools.public:由PDK的各种功能取代。
    • kong.tools.responses:由PDK中的kong.response.exit取代。您可能还使用kong.log.err来记录内部服务器错误。
  • kong.api.crud_helpers模块已被删除。如果需要自定义自动生成的终端,请使用kong.api.endpoints

Admin API

  • 删除API实体后,将删除/apis终端;因此,接受api_id的其他终端不再这样做。请改用Routes和Services。
  • 现在,所有实体终端都使用新的Admin API实现。这意味着他们的请求和响应现在使用相同的语法,该语法已在终端(例如/routes/services)中使用。
    • 所有端点现在使用相同的语法将其他实体作为/routes引用(例如,“service”:{“id”:“...”}而不是“service_id”:“...”),包括请求和响应。
      • 此更改会影响/plugins以及特定于插件的终端。
    • 数组类型的值不再指定为以逗号分隔的列表。必须将其指定为JSON数组或使用新Admin API实现的url-formencoded数组表示法支持的各种格式(a[1]=x&a[2]=y, a[]=x&a[]=y, a=x&a=y
      • 此更改会影响/upstreams终端的属性。
    • 更新终端的错误响应使用新的标准化格式。
    • 由于被移动到新的Admin API实现,支持PUT的所有终端都使用适当的语义。
    • 有关更多详细信息,请参阅Admin API参考

2.弃用通知

此版本中没有弃用通知。

3.建议的升级路径

初步检查

如果您的群集运行的版本低于0.14,则需要先升级到0.14.1。不支持从0.14之前的群集直接升级到Kong 1.0。如果您仍然使用已弃用的API实体来配置终端和上游服务(通过/apis),而不是使用路由Routes(通过’/routes’)和服务Service(通过/services),现在是时候这样做了。如果您在数据存储区中使用/apis配置了任何实体,则kong 1.0将拒绝运行迁移。创建等效的路由和服务并删除您的API。请注意,Kong不会自动执行此操作,因为为每个API创建一对路由和服务这样天真的操作将错过路由和服务带来的改进点;路由和服务的理想映射取决于您的微服务架构。

如果您使用除与Kong自带捆绑的插件以外的其他插件,请确保在升级之前它们与Kong 1.0兼容。有关插件兼容性的信息,请参阅上面有关插件的部分。

从0.14开始逐步迁移

Kong 1.0引入了一个新的,改进的迁移框架。它支持无停机,蓝/绿迁移模型,可从0.14.x升级。完整迁移现在分为两个步骤,这两个步骤通过命令kong migrations upkong migrations finish完成。

对于从0.14群集到1.0群集的无停机时间迁移,我们建议采用以下一系列步骤:

  • 第一步:下载1.0,并将其配置为指向与0.14群集相同的数据存储。执行kong migrations up
  • 第二步:现在,0.14和1.0节点都可以在同一数据存储上同时运行。开始配置1.0节点,但是先不要使用其Admin API。更好的操作是向0.14节点发出Admin API请求。
  • 第三步:逐渐将流量从0.14节点转移到1.0集群中。监控您的流量,确保一切顺利。
  • 第四步:当您的流量完全迁移到1.0群集时,停用0.14节点。
  • 第五步:从1.0集群中,运行:kong migrations finish。从现在开始,将无法再启动指向同一数据存储区的0.14个节点。仅在您确信迁移成功时才运行此命令。从现在开始,您可以安全地向1.0节点发出Admin API请求。

在任何一步,您都可以运行kong migrations list来获取迁移状态的报告。它将列出是否缺少迁移,如果有待处理的迁移(已经在kong迁移步骤中启动,之后需要在kong迁移完成步骤中完成)或者是否有新的迁移可用。流程的状态代码也会相应更改:

  • 0 - 迁移是最新的
  • 1 - 检查迁移状态失败(例如数据库已关闭)
  • 3 - 数据库需要引导:你应该运行kong migrations bootstrap来安装在新的数据存储上。
  • 4 - 有待处理的迁移:一旦您的旧群集被解除,您应该运行kong迁移完成(上面的步骤5)。
  • 5 - 有新的迁移:您应该开始迁移序列(从上面的步骤1开始)。

从1.0 Release Candidates迁移

该过程与上面列出的0.14升级过程相同,但在第1步中,您应该运行kong migrations --force。

补丁版本的升级路径

同一次要版本的Kong的当前或未来补丁版本之间的升级没有迁移(例如1.0.0到1.0.1,1.0.1到1.0.4等)。

假设Kong已在您的系统上运行,请从任何可用的安装方法获取最新版本并继续安装它,覆盖以前的安装。

如果您计划对配置进行修改,那么这是一个好时机。然后,运行迁移以升级数据库模式

$ kong migrations up [-c configuration_file]

如果命令成功,并且没有运行迁移(没有输出),那么您只需要重新加载Kong

$ kong reload [-c configuration_file]

提醒:kong reload利用ngnix的reload来无缝启动一个新的worker。在那些旧worker被终止之前接管旧的worker。通过这种方式,Kong将通过新配置提供新请求,而不会丢弃现有的服务连接。

在新数据存储上安装1.0

为了在新的数据存储上安装,Kong 1.0引入了kong migrations bootstrap命令。可以运行以下命令从新数据存储区准备新的1.0集群:

$ kong migrations bootstrap [-c config]
$ kong start [-c config]

微服务 API 网关 Kong 插件开发套件PDK 中文文档

原文地址:https://docs.konghq.com/1.0.x/pdk/(不能保证所有的翻译都是准确无误的,所有如有翻译的不准确或错误之处,请一定记得查看原文,并欢迎留言指出)。

插件开发工具包 Plugin Development Kit(或“PDK”)是一组Lua函数和变量,插件可以使用这些函数和变量来实现自己的逻辑。PDK是一个语义版本的组件,最初在Kong 0.14.0中发布。PDK将保证从1.0.0版本开始向前兼容。

截至本版本,PDK尚未达到1.0.0,但插件作者已经可以依赖它来使用安全可靠的方式进行请求、响应或者做一些核心组件。

可以从kong全局变量访问插件开发工具包,并在此表下命名各种功能,例如kong.requestkong.log等…

kong.version

一个可以直观阅读的字符串,包含当前正在运行的节点的版本号。

用法

print(kong.version) -- "0.14.0"
Back to TOC

kong.version_num

表示当前运行节点的版本号的整数,用于比较和特征存在检查。

用法

if kong.version_num < 13000 then -- 000.130.00 -> 0.13.0
  -- no support for Routes & Services
end

kong.pdk_major_version

表示当前PDK主要版本的数字(例如1)。 对于作为PDK用户的特征存在检查或向后兼容行为很有用。

用法

if kong.pdk_version_num < 2 then
  -- PDK is below version 2
end
Back to TOC

kong.pdk_version

一个可以直观阅读的字符串,包含当前PDK的版本号。

用法

print(kong.pdk_version) -- "1.0.0"

kong.configuration

包含当前Kong节点配置的只读表,基于配置文件和环境变量。 有关详细信息,请参阅kong.conf.default。 该文件中以逗号分隔的列表将被提升为此表中的字符串数组。

用法

print(kong.configuration.prefix) -- "/usr/local/kong"
-- this table is read-only; the following throws an error:
kong.configuration.prefix = "foo"

kong.db

Kong的DAO实例(kong.db模块)。 包含各种实体的访问者对象。

用法

kong.db.services:insert()
kong.db.routes:select()

将来可以提供有关此DAO和新模式定义的更全面的文档。

kong.dns

Kong的DNS解析器实例,来自lua-resty-dns-c模块的客户端对象。 注意:此模块的使用目前保留给核心或高级用户。

kong.worker_events

Kong的IPC模块实例,用于来自lua-resty-worker-events模块的员工间通信。 注意:此模块的使用目前保留给核心或高级用户。

kong.cluster_events

用于节点间通信的Kong的集群事件模块的实例。 注意:此模块的使用目前保留给核心或高级用户。 回到TOC

kong.cache

来自kong.cache模块的Kong数据库缓存对象的实例。 注意:此模块的使用目前保留给核心或高级用户。

微服务 API 网关 Kong Route 中文文档

原文地址:https://docs.konghq.com/1.0.x/admin-api/#route-object (不能保证所有的翻译都是准确无误的,所有如有翻译的不准确或错误之处,请一定记得查看原文,并欢迎留言指出)。

route 路由

路由实体定义规则以匹配客户端请求。每个Route与一个服务相关联,一个服务可能有多个与之关联的路由。匹配给定路由的每个请求都将代理到其关联的服务。
Routes 和 Services 的组合(以及它们之间的关注点分离)提供了一种强大的路由机制,通过它可以在 Kong 中定义细粒度的入口点,从而导致基础架构的不同上游服务。

{
    "id": "173a6cee-90d1-40a7-89cf-0329eca780a6",
    "created_at": 1422386534,
    "updated_at": 1422386534,
    "name": "my-route",
    "protocols": ["http", "https"],
    "methods": ["GET", "POST"],
    "hosts": ["example.com", "foo.test"],
    "paths": ["/foo", "/bar"],Service 服务
    "regex_priority": 0,
    "strip_path": true,
    "preserve_host": false,
    "service": {"id":"f5a9c0ca-bdbb-490f-8928-2ca95836239a"}
}

添加 route

创建一个route

POST:/routes

创建与特定服务关联的路由

POST:/services/{service name or id}/routes
参数 描述
service name or id 
required
应与新创建的路由关联的服务的唯一标识符或名称属性。

请求体

参数 描述
name 
optional
Route 名称
protocols 此路由应允许的协议列表。设置为[“https”]时,将通过请求升级到HTTPS来回答HTTP请求。默认为[“http”,“https”]
methods 
semi-optional
与此Route匹配的HTTP方法列表。使用http或https协议时,必须至少设置一个hosts, paths, or methods
hosts 
semi-optional
与此路由匹配的域名列表。使用httphttps协议时,必须至少设置一个hosts, paths, 或者 methods。使用表单编码时,符号是hosts [] = example.com&hosts [] = foo.test。使用JSON,使用Array。
paths 
semi-optional
与此路由匹配的路径列表。使用httphttps协议时,必须至少设置一个必须至少设置一个hosts, paths, 或者methods。使用表单编码时,符号是paths [] = / foo&paths [] = / bar。使用JSON,使用数组。
regex_priority
optional
用于选择哪条路由解析给定请求的数字,当多条路由同时使用正则表达式匹配时。当两条路径匹配路径并具有相同的regex_priority时,将使用较旧的路径(最低的created_at)。请注意,非正则表达式路由的优先级不同(较长的非正则表达式路由在较短的路由之前匹配)。默认为0
strip_path 
optional
通过其中一条path匹配Route时,从上游请求URL中删除匹配的前缀。默认为true
preserve_host 
optional
通过其中一个主机域名匹配Route时,请使用上游请求标头中的请求主机头。如果设置为false,则上游主机头将是服务主机的头。
snis 
semi-optional
使用流路由时与此路由匹配的SNI列表。使用tcptls协议时,必须至少设置一个snissourcesdestinations PUT
sources 
semi-optional
使用流路由时与此路由匹配的传入连接的IP源列表。每个条目都是一个对象,其字段为“ip”(可选地为CIDR范围表示法)和/或“port”。使用tcptls协议时,必须至少设置一个snissourcesdestinations
destinations 
semi-optional
使用流路由时,与此路由匹配的传入连接的IP目标列表。每个条目都是一个对象,其字段为“ip”(可选地为CIDR范围表示法)和/或“port”。使用tcptls协议时,必须至少设置一个snissourcesdestinations
service 此路由所关联的服务。这是Route代理流量的地方,使用表单encode。表示法是service.id = <service_id>。使用JSON,使用“service”:{“id”:“<service_id>”}

响应

HTTP 201 Created
{
    "id": "173a6cee-90d1-40a7-89cf-0329eca780a6",
    "created_at": 1422386534,
    "updated_at": 1422386534,
    "name": "my-route",
    "protocols": ["http", "https"],
    "methods": ["GET", "POST"],
    "hosts": ["example.com", "foo.test"],
    "paths": ["/foo", "/bar"],
    "regex_priority": 0,
    "strip_path": true,
    "preserve_host": false,
    "service": {"id":"f5a9c0ca-bdbb-490f-8928-2ca95836239a"}
}

路由列表

所有路由列表

GET:/routes

列出与特定服务关联的路由列表

GET:/services/{service name or id}/routes
参数 描述
service name or id 
required
要检索其路由的服务的唯一标识符或name属性。仅列出与指定服务关联的路由。

响应

HTTP 200 OK
{
"data": [{
    "id": "885a0392-ef1b-4de3-aacf-af3f1697ce2c",
    "created_at": 1422386534,
    "updated_at": 1422386534,
    "name": "my-route",
    "protocols": ["http", "https"],
    "methods": ["GET", "POST"],
    "hosts": ["example.com", "foo.test"],
    "paths": ["/foo", "/bar"],
    "regex_priority": 0,
    "strip_path": true,
    "preserve_host": false,
    "service": {"id":"a3395f66-2af6-4c79-bea2-1b6933764f80"}
}, {
    "id": "4fe14415-73d5-4f00-9fbc-c72a0fccfcb2",
    "created_at": 1422386534,
    "updated_at": 1422386534,
    "name": "my-route",
    "protocols": ["tcp", "tls"],
    "regex_priority": 0,
    "strip_path": true,
    "preserve_host": false,
    "snis": ["foo.test", "example.com"],
    "sources": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}],
    "destinations": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}],
    "service": {"id":"ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6"}
}],

    "next": "http://localhost:8001/routes?offset=6378122c-a0a1-438d-a5c6-efabae9fb969"
}

查询路由

查询路由

GET:/routes/{name or id}
参数 描述
service name or id 
required
要检索其路由的服务的唯一标识符或name属性。仅列出与指定服务关联的路由。

查询与特定插件关联的路由

GET:/plugins/{plugin id}/route
参数 描述
plugin id 
required
与要更新的路由关联的插件的唯一标识符。

响应

HTTP 200 OK
{
    "id": "173a6cee-90d1-40a7-89cf-0329eca780a6",
    "created_at": 1422386534,
    "updated_at": 1422386534,
    "name": "my-route",
    "protocols": ["http", "https"],
    "methods": ["GET", "POST"],
    "hosts": ["example.com", "foo.test"],
    "paths": ["/foo", "/bar"],
    "regex_priority": 0,
    "strip_path": true,
    "preserve_host": false,
    "service": {"id":"f5a9c0ca-bdbb-490f-8928-2ca95836239a"}
}

PUT

更新路由

更新路由

PATCH:/routes/{name or id}
参数 描述
name or id 
required
唯一标识符或要更新的路由的名称。

更新与特定插件关联的路由

PATCH:/plugins/{plugin id}/route
参数 描述
plugin id 
required
与要更新的路由关联的插件的唯一标识符。

请求体

参数 描述
name 
optional
Route 名称
protocols 此路由应允许的协议列表。设置为[“https”]时,将通过请求升级到HTTPS来回答HTTP请求。默认为[“http”,“https”]
methods 
semi-optional
与此Route匹配的HTTP方法列表。使用http或https协议时,必须至少设置一个hosts, paths, or methods
hosts 
semi-optional
与此路由匹配的域名列表。使用httphttps协议时,必须至少设置一个hosts, paths, 或者 methods。使用表单编码时,符号是hosts [] = example.com&hosts [] = foo.test。使用JSON,使用Array。
paths 
semi-optional
与此路由匹配的路径列表。使用httphttps协议时,必须至少设置一个必须至少设置一个hosts, paths, 或者methods。使用表单编码时,符号是paths [] = / foo&paths [] = / bar。使用JSON,使用数组。
regex_priority
optional
用于选择哪条路由解析给定请求的数字,当多条路由同时使用正则表达式匹配时。当两条路径匹配路径并具有相同的regex_priority时,将使用较旧的路径(最低的created_at)。请注意,非正则表达式路由的优先级不同(较长的非正则表达式路由在较短的路由之前匹配)。默认为0
strip_path 
optional
通过其中一条path匹配Route时,从上游请求URL中删除匹配的前缀。默认为true
preserve_host 
optional
通过其中一个主机域名匹配Route时,请使用上游请求标头中的请求主机头。如果设置为false,则上游主机头将是服务主机的头。
snis 
semi-optional
使用流路由时与此路由匹配的SNI列表。使用tcptls协议时,必须至少设置一个snissourcesdestinations
sources 
semi-optional
使用流路由时与此路由匹配的传入连接的IP源列表。每个条目都是一个对象,其字段为“ip”(可选地为CIDR范围表示法)和/或“port”。使用tcptls协议时,必须至少设置一个snissourcesdestinations
destinations 
semi-optional
使用流路由时,与此路由匹配的传入连接的IP目标列表。每个条目都是一个对象,其字段为“ip”(可选地为CIDR范围表示法)和/或“port”。使用tcptls协议时,必须至少设置一个snissourcesdestinations
service 此路由所关联的服务。这是Route代理流量的地方,使用表单encode。表示法是service.id = <service_id>。使用JSON,使用“service”:{“id”:“<service_id>”}

响应

HTTP 200 OK
{
    "id": "173a6cee-90d1-40a7-89cf-0329eca780a6",
    "created_at": 1422386534,
    "updated_at": 1422386534,
    "name": "my-route",
    "protocols": ["http", "https"],
    "methods": ["GET", "POST"],
    "hosts": ["example.com", "foo.test"],
    "paths": ["/foo", "/bar"],
    "regex_priority": 0,
    "strip_path": true,
    "preserve_host": false,
    "service": {"id":"f5a9c0ca-bdbb-490f-8928-2ca95836239a"}
}
参数 描述
plugin id 
required
与要更新的路由关联的插件的唯一标识符。

更新或创建路由

更新或创建一个路由

PUT:/routes/{name or id}
| 参数 | 描述 |
| ---- | ---- |
| `name or id` <br> ** required ** | 要创建或更新的路由的唯一标识符或名称。 |

创建或更新与特定插件关联的路由

PUT:/plugins/{plugin id}/route
参数 描述
plugin id 
required
与要更新的路由关联的插件的唯一标识符。

请求体

参数 描述
name 
optional
Route 名称
protocols 此路由应允许的协议列表。设置为[“https”]时,将通过请求升级到HTTPS来回答HTTP请求。默认为[“http”,“https”]
methods 
semi-optional
与此Route匹配的HTTP方法列表。使用http或https协议时,必须至少设置一个hosts, paths, or methods
hosts 
semi-optional
与此路由匹配的域名列表。使用httphttps协议时,必须至少设置一个hosts, paths, 或者 methods。使用表单编码时,符号是hosts [] = example.com&hosts [] = foo.test。使用JSON,使用Array。
paths 
semi-optional
与此路由匹配的路径列表。使用httphttps协议时,必须至少设置一个必须至少设置一个hosts, paths, 或者methods。使用表单编码时,符号是paths [] = / foo&paths [] = / bar。使用JSON,使用数组。
regex_priority
optional
用于选择哪条路由解析给定请求的数字,当多条路由同时使用正则表达式匹配时。当两条路径匹配路径并具有相同的regex_priority时,将使用较旧的路径(最低的created_at)。请注意,非正则表达式路由的优先级不同(较长的非正则表达式路由在较短的路由之前匹配)。默认为0
strip_path 
optional
通过其中一条path匹配Route时,从上游请求URL中删除匹配的前缀。默认为true
preserve_host 
optional
通过其中一个主机域名匹配Route时,请使用上游请求标头中的请求主机头。如果设置为false,则上游主机头将是服务主机的头。
snis 
semi-optional
使用流路由时与此路由匹配的SNI列表。使用tcptls协议时,必须至少设置一个snissourcesdestinations
sources 
semi-optional
使用流路由时与此路由匹配的传入连接的IP源列表。每个条目都是一个对象,其字段为“ip”(可选地为CIDR范围表示法)和/或“port”。使用tcptls协议时,必须至少设置一个snissourcesdestinations
destinations 
semi-optional
使用流路由时,与此路由匹配的传入连接的IP目标列表。每个条目都是一个对象,其字段为“ip”(可选地为CIDR范围表示法)和/或“port”。使用tcptls协议时,必须至少设置一个snissourcesdestinations
service 此路由所关联的服务。这是Route代理流量的地方,使用表单encode。表示法是service.id = <service_id>。使用JSON,使用“service”:{“id”:“<service_id>”}

使用请求提中指定的参数插入(或替换)请求资源下的路由。Route将通过nameid属性进行标识。
nameid属性具有UUID的结构时,插入/替换的Route将由其id标识。否则将通过其name识别。
在创建新路由而不指定id(既不在URL中也不在主体中)时,它将自动生成。
请注意,不允许在URL中指定name,在请求正文中指定其他名称。

响应

HTTP 201 Created or HTTP 200 OK

参考 POST 和 PATCH 的响应。

删除路由

删除一个路由

DELETE:/routes/{name or id}
| 参数 | 描述 |
| ---- | ---- |
| `name or id` <br> ** required ** | 要删除的路由的唯一标识符或名称。 |

响应

HTTP 204 No Content