在APISIX定制化开发中很多时候我们需要用到自定义数据的持久化,这个是一个很常见的问题,怎么能高性能的进行持久化和变更所有的进程感知持久化数据变更是一个大家都需要了解的问题。
我们都知道apisix 使用的数据存储未etcd,etcd 是一个KV 存储,通过提供的watch 功能能够很轻松的感知数据的变化。那么apisix 是怎么实现的呢?
在我们进行apisix 第一次启动的时候或者官方的容器内的启动脚本可以看到下面的一段命令:
set -eo pipefail
PREFIX=${APISIX_PREFIX:=/usr/local/apisix}
if [[ "$1" == "docker-start" ]]; then
if [ "$APISIX_STAND_ALONE" = "true" ]; then
cat > ${PREFIX}/conf/config.yaml << _EOC_
deployment:
role: data_plane
role_data_plane:
config_provider: yaml
_EOC_
cat > ${PREFIX}/conf/apisix.yaml << _EOC_
routes:
-
#END
_EOC_
/usr/bin/apisix init
else
/usr/bin/apisix init
/usr/bin/apisix init_etcd
fi
exec /usr/local/openresty/bin/openresty -p /usr/local/apisix -g 'daemon off;'
fi
exec "$@"
在启动命令之前活进行init_etcd 的操作,这个操作的意义是什么呢?在这个操作执行的指令会便利下面的kv 进行初始化数据的插入。
init_kv=(
"/apisix/consumers/init_dir"
"/apisix/global_rules/init_dir"
"/apisix/plugin_metadata/init_dir"
"/apisix/plugins/init_dir"
"/apisix/protos/init_dir"
"/apisix/routes/init_dir"
"/apisix/services/init_dir"
"/apisix/ssls/init_dir"
"/apisix/stream_routes/init_dir"
"/apisix/upstreams/init_dir"
)
这个数据初始化是非常重要的,只有设置了init_dir 的key 才能使用apisix 的watch 机制去监听数据。因此在我们开发自定义插件的时候在启动之前也是需要设置初始化数据的。
在初始化数据之后我们如何使用这个watch 功能呢?apisix 其实提供了相关的方案,初始化代码如下:
function _M.init()
local err
operation_watch, err = core.config.new("/test/v1/", {
automatic = true,
item_schema = demo.schema
})
if not operation_watch then
core.log.error("failed to create etcd instance for fetching request intercept setting: ", err)
return
end
end
在插件的初始化阶段初始化watch 功能(之前需要设置init_dir),需要设定每个缓存对象的schema,需要保证所有的数据的schema一致,初始化成功后就可以使用operation_watch 这个对象去读取本地缓存的数据了。
读取数据使用的方法如下:
if not operation_watch or not operation_watch.values then
core.log.warn("OPERATION_LOSS", "not find operations configs")
return nil
end
local service_version_operations = {}
for _, item in ipairs(operation_watch.values) do
if item.service == service then
table.insert(service_version_operations, item)
end
end
一般有2中方法,上面代码的方法是取到所有的值进行遍历比对应该获取的数据,另一种方法未get schema 的id