apisix源码分析-route的匹配(6)

apisix源码分析-route的匹配(6)

route 是如何匹配的?

Route 中主要包含三部分内容:匹配规则(比如 uri、host、remote_addr 等),插件配置(限流限速等)和上游信息,通过 init_worker 阶段对 etcd 的监控,route 节点的数据同步到了user_routes的变量中,默认执行 http/router/radixtree_uri.lua 匹配规则 ,还可以使用 radixtree_host_uriradixtree_uri_with_parameter 。通过实现 match(api_ctx) 方法实现查询替换。

在 apisix 中使用了 redixtree 来实现路由匹配、域名证书、admin route 的匹配。 redixtree 相关分析可以看相关的分析。通过存储不同的path,来实现不同的需求。

  • radixtree_uri

    paths = route.value.uris or route.value.uri,

    在radixtree_uri 中直接使用了uri,也就是直接使用了请求的路径部分在 redixtree 中做匹配

  • radixtree_host_uri

    建立了两层 redixtree 来做 route 查询,第一层使用域名作为 path 创建 redixtree 和ssl的域名查询相同)。在域名对应的 key 在创建 uri 的 redixtree。形成两层查询。

  • radixtree_uri_with_parameter (未实现)

access 的执行

当获取到匹配的 route 后,就可以得到 route、plugin、service 等信息。这些信息会存储在变量api_ctx 中

1
2
3
4
5
6
7
8
9
api_ctx.matched_route = route
api_ctx.conf_type = "route&service"
api_ctx.conf_version = route.modifiedIndex .. "&" .. service.modifiedIndex
api_ctx.conf_id = route.value.id .. "&" .. service.value.id
api_ctx.service_id = service.value.id
api_ctx.service_name = service.value.name

api_ctx.route_id = route.value.id
api_ctx.route_name = route.value.name

对于插件有两种,列表或者通过编排的。

当发现 route.value.script 不为空时,会执行通过编排生成的 lua 脚本。

为空时执行插件列表。在执行插件列表时执行了会执行如下代码:

1
2
3
4
5
6
7
8
9
10
11
plugin.run_plugin("rewrite", plugins, api_ctx)
if api_ctx.consumer then
...
route, changed = plugin.merge_consumer_route(
route,
api_ctx.consumer,
api_ctx
)
...
end
plugin.run_plugin("access", plugins, api_ctx)

在这里可以发现,apisix 的插件的 rewrite 和 access 都是在 openresty 的 access 阶段执行的

在配置的时候我们会有默认插件,Consumer 绑定的插件, Route 绑定的插件,Service 绑定的插件。只列出插件 merge 操作,根据插件优先级的说明,同样的插件只会有一份有效,相同的插件会做合并。Plugin 配置可直接绑定在 Route 上,也可以被绑定在 Service 或 Consumer上。而对于同一 个插件的配置,只能有一份是有效的,配置选择优先级总是 Consumer > Route > Service。在 access 执行过程中可以看到如下的合并过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if route.value.plugin_config_id then
...
route = plugin_config.merge(route, conf)
end
if route.value.service_id then
...
route = plugin.merge_service_route(service, route)
...
end
if api_ctx.consumer then
...
route, changed = plugin.merge_consumer_route(
route,
api_ctx.consumer,
api_ctx
)
...
end

apisix源码分析-route的匹配(6)

https://beixiu.net/apisix-source-6/

作者

张巍

发布于

2023-08-21

更新于

2023-08-21

许可协议

评论