Apisix 插件开发 w3c-baggage
APISIX 是一款高性能可扩展的云原生网关:Opentelemetry 是当前 CNCF 除 k8s 外最火爆的项目,已经成为可观测性相关链路、日志、指标的数据采集行业标准,各大云厂商和中间件都已经集成。希望 用户id、灰度标签等信息在服务间无感地进行传递。
·
背景
APISIX 官网:APISIX 是一款高性能可扩展的云原生网关
OpenTelemetry 官网:Opentelemetry 是当前 CNCF 除 k8s 外最火爆的项目,已经成为可观测性相关链路、日志、指标的数据采集行业标准,各大云厂商和中间件都已经集成。
需求
希望 用户id、灰度标签等信息在服务间无感地进行传递。
思路
Opentelemetry 提供了上下文全链路透传的能力,其传输格式见通用 w3c-baggage 协议
简单来说就是对 http 请求增加 baggage 请求头,baggage 的大概格式如下
baggage: userId=alice,isProduction=false
下面我们要做的就是在网关进行流量染色,根据 token 或者其他信息增加对应的 baggage 请求头,由于 apisix 中没有现成的插件因此需要自己开发一个。
插件功能非常简单如下图所示
实现
1 准备工作
1.1 熟悉官方文档
- 插件 apisix 的插件核心流程 https://apisix.apache.org/zh/docs/apisix/architecture-design/apisix/
- 查看 apisix 官方提供的插件扩展文档 https://apisix.apache.org/zh/docs/apisix/plugin-develop/ 了解大概需要做什么
- 首先确定插件名为:w3c-baggage
1.2 下载 apisix 源码
git clone https://github.com/apache/apisix
仓库里有很多插件可以供我们参考
在 plugins 目录下创建 w3c-baggage.lua 文件
1.3 开发环境准备
由于是云原生网关,我们本地没有 k8s 集群的话就通过 docker 去搭建容器环境
https://apisix.apache.org/zh/docs/apisix/installation-guide/
git clone https://github.com/apache/apisix-docker.git
cd apisix-docker/example
- 启动服务
- docker-compose up -d
2 插件开发
- schema 中的 properties 支持实时生效,可以在 apisix dashboard 上动态配置
- _M 为一些原信息,我选择优先级比 opentelemetry 和 skywalking 小一点
- rewrite 为核心修改请求头逻辑,在官网插件市场中找功能相似的插件进行参考,我找到的是 forword-auth 插件,修改后代码如下
local ngx = ngx
local ipairs = ipairs
local core = require("apisix.core")
local http = require("resty.http")
local schema = {
type = "object",
properties = {
url = {
type = "string",
description = "上下文服务提取上下文接口地址"
},
request_headers = {
type = "array",
default = {},
items = { type = "string" },
description = "需要由客户端转发到上下文服务的请求头"
},
timeout = {
type = "integer",
minimum = 1,
maximum = 60000,
default = 3000,
description = "timeout in milliseconds",
},
keepalive = {
type = "boolean",
default = true
},
keepalive_timeout = {
type = "integer",
minimum = 1000,
default = 60000
},
keepalive_pool = {
type = "integer",
minimum = 1,
default = 5
},
}
}
local plugin_name = "w3c-baggage"
local _M = {
version = 0.1,
priority = 12008,
name = plugin_name,
schema = schema,
metadata_schema = metadata_schema,
}
function _M.check_schema(conf, schema_type)
return core.schema.check(schema, conf)
end
function _M.rewrite(conf, ctx)
local request_body = {
url = ngx.var.host .. ngx.var.request_uri,
headers = {}
}
-- append headers that need to be get from the client request header
if #conf.request_headers > 0 then
for _, header in ipairs(conf.request_headers) do
if not request_body.headers[header] then
request_body.headers[header] = core.request.header(ctx, header)
end
end
end
local params = {
method = "POST",
headers = {
["Content-Type"] = "application/json",
},
body = core.json.encode(request_body),
keepalive = conf.keepalive,
}
if conf.keepalive then
params.keepalive_timeout = conf.keepalive_timeout
params.keepalive_pool = conf.keepalive_pool
end
local httpc = http.new()
httpc:set_timeout(conf.timeout)
local res, err = httpc:request_uri(conf.url, params)
if not res then
core.log.error("w3c-baggage error: ", err)
return
end
if not res.body or res.status ~= 200 then
return
end
core.request.set_header(ctx, "baggage", res.body)
end
return _M
3 插件部署调试
- 修改 docker-compose.yml 将 w3c-baggage.lua 文件映射到容器 /usr/local/apisix/apisix/plugins/w3c-baggage.lua
- 查看默认配置插件信息
- docker-compose exec apisix cat /usr/local/apisix/conf/config-default.yaml
- 修改 vi apisix_conf/config.yaml,复制 config-default.yaml 中的 plugins 列表,并增加 w3c-baggage(插件名)
- 重启 apisix
- docker-compose stop apisix
- docker-compose up -d
- 检查脚本内容
- docker-compose exec apisix cat /usr/local/apisix/apisix/plugins/w3c-baggage.lua
- 观察日志,看有没有错误
- docker-compose logs apisix
- 导出插件 schema.json
- docker-compose exec apisix curl 127.0.0.1:9092/v1/schema > schema.json
- 修改 docker-compose.yml,将刚才导出的 schema.json 挂载到容器 /usr/local/apisix-dashboard/conf/schema.json
- 重启 apisix-dashboard
- docker-compose stop apisix-dashboard
- docker-compose up -d
- 进入 apisix dashboard 配置插件生效
- 启动上下文服务,发起请求调试
更多推荐
已为社区贡献2条内容
所有评论(0)