您可以使用Lua filter 引入自定义逻辑,但不能直接使用纯 Javascript 或 Python。此外,也许Wasm filter 可以满足您的需求,而不是 Lua 过滤器。我还没有测试它,它是实验性的,所以我不知道它是否适用于你的情况。
无论如何,以下示例是一个基本配置,用于展示您可以使用 Lua 过滤器做什么(envoy.filters.http.lua 部分)。它:
- 解析
path(类似于/something?param=1&other=xxx)
- 检索
param 字段
- 将其添加到用于路由匹配的标头 (
X-App) 中(param=1 会将流量重定向到集群 first 和 param=2 会将流量重定向到集群 second;其他值会将流量重定向到集群first 默认)
当然,这里我使用了一个 Lua 过滤器来允许你添加一些其他的自定义逻辑。
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "*"
routes:
- match:
prefix: "/"
headers:
- name: "X-App"
string_match: # with envoy < 1.22.0, use exact_match: "1" instead
exact: "1"
route:
cluster: first
- match:
prefix: "/"
headers:
- name: "X-App"
string_match: # with envoy < 1.22.0, use exact_match: "2" instead
exact: "2"
route:
cluster: second
- match: # default, if no headers
prefix: "/"
route:
cluster: first
http_filters:
- name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(request_handle)
path = request_handle:headers():get(":path")
param_value = string.match(path, '/.*[?&]param=([^&]+)')
if param_value then
request_handle:headers():add("X-App", param_value)
end
end
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: first
connect_timeout: 5s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: first
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: first
port_value: 5000
- name: second
connect_timeout: 5s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: second
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: second
port_value: 5000
您还可以使用随机数(此处为 50/50)进行一些金丝雀流量路由:
function envoy_on_request(request_handle)
math.randomseed(os.clock())
-- math.random() returns a number in [0;1)
if math.random() < 0.5 then
request_handle:headers():add("x-app", "1")
else
request_handle:headers():add("x-app", "2")
end
end
但请注意,Lua 在 Envoy 过滤器中使用时非常有限(我不确定,但看起来您无法安装外部包/模块),并且您可能无法查询数据库来制作您的路由决定。你应该看看 Wasm 过滤器,它可能适用于此。