apisix源码分析-初始化过程(3)
init
init 对应到 openresty 的 init_by_lua_block
和init_worker_by_lua_block
的阶段
init_by_lua_block
所做的不多,执行 apisix.http_init(args)
,args 里面传入了 dns_resolver 配置的参数,比如使用docker-compose 启动传入的127.0.0.11 。
1 | local dns_resolver = { "127.0.0.11", } |
在init 过程中:
1 | -- dns 发现设置: args["dns_resolver"] |
init_worker
apisix/init/http_init_worker()
init_worker 阶段执行了所有组件的初始化,也就是对应组件的 init_worker 方法。
比如 admin timers plugin plugin_config route service consumer config upstream ssl。、
这个阶段主要的作用是初始化各个组件。每个组件自身都实现了一个 init_worker 方法,除了自身相关的内容,主要是同步组件自身对应的 etcd 信息。
etcd watch 实现
1 | obj, err = core.config.new("/etcd_path", cfg) |
比如在 router 的 http_init_worker 阶段,watch 了 /global_rules
1 | local global_rules, err = core.config.new("/global_rules", { |
core.config.new(key,ops)
函数对应的执行在文件 core/config_etcd.lua
中。
> 在 apisix/core.lua 中 local config = require("apisix.core.config_" .. config_center), config_center 来自配置文件,默认为 etcd。
key 为 etcd 监控的节点,ops 为需要的参数。
当 automatic == true 时 ,会创建 ngx.timer_at , 否则只会初始化 etcd_cli
load_full_data
函数,将 etcd 取回的数据填充到 key 对应的 obj 中(将etcd 数据转换为 lua 对象)
- self.item_scheme 检验数据
- self.checker 对象检查
- 将数据写入 self.value , self.values_hash[key] 记录对应key的index
- 执行 self.filter
_automatic_fetch
函数,启动 ngx_timer_at 调用函数 _automatic_fetch ,通过自调用形成迭代。
在_automatic_fetch函数中真正执行同步的是 sync_data 函数
sync_data
函数,读取 etcd,并 watch etcd ,将数据写到对象中 。
self.values : array 用来存储 etcd 写回的数据
self.values_hash: hash 用来存储 etcd key 对应的 values 的下标, 在 etcd 中 {/routes/aaa:<data>} 同步到 apisix 的存储
假设 etcd 有如下 key
`etcd: /routes/aaaa : <data>`
在self 中存储:
`self.values = [<data>,...]
self.values_hash= {"/routes/aaa":1}`
出现修改数据
1 | insert_tab(self.values, res) |
当出现删除数据时
1 | self.sync_times = self.sync_times + 1 |
这里出现的 sync_times
是一个计数器,用来记录删除values 数量,当超过 100 的时候,会对 values 里的数据进行重建。
self.conf_version
记录版本变化次数
服务发现
服务发现的 init_worker 会循环调用配置的服务发现。 discovery_type 为配置文件中配置的服务发现。
1 | local discovery_type = local_conf.discovery |
我们可以在 discovery 目录找到对应的服务发现的实现。服务发现需要实现两个接口。
1 | local _M = {} |
为了看分析比较简单,可以查看 discovery/dns.lua 的实现。
init_woker 函数初始化了 dns_client 。
nodes 函数通过 dns 服务发现来获取 service_name 对应的服务。并将返回的内容转换成 apisix 的的格式。
1 | nodes[i] = {host = r.address, weight = r.weight or 1, port = r.port or port} |
目前 apisix 支持了 consul_kv
dns
eureka
nacos
四种服务发现,如果想要其他的可以自行实现这两个函数来支持业务。
在将upstream 和 route 绑定时会 set_by_route 会触发服务发现的 nodes 函数。
access
apisix 匹配路由是在 access 阶段完成的,功能由 router_http.match(api_ctx)
提供
header_filter
会设置一些 apisix 自定义的 header ,调用 common_phase
body_filter
调用 common_phase
log
调用 common_phase
被动健康检查
释放前面阶段里通过 tablepool 申请的对象 (api_ctx plugins uri_parse_param matched_route_record )
balancer
在access 阶段就计算出了要均衡到的后端,设置并执行 balancer.lua 的 run 函数
apisix源码分析-初始化过程(3)