缓存目的
为了避免每次请求都查询数据库,可以将自定义实体缓存在节点的内存中,这样不会频繁地触发数据库查询,而是在内存中查询,这比从数据库中查询要快得多、可靠得多,特别是当大流量请求时。
缓存方式
daos层自定义实体(key-auths案例)
指定cache_key 字段,这里注意key 字段具有唯一属性,以保证缓存里不会发生重复的实体
local typedefs = require "kong.db.schema.typedefs"
return {
keyauth_credentials = {
ttl = true,
primary_key = { "id" },
name = "keyauth_credentials",
endpoint_key = "key",
cache_key = { "key" },
workspaceable = true,
admin_api_name = "key-auths",
admin_api_nested_name = "key-auth",
fields = {
{ id = typedefs.uuid },
{ created_at = typedefs.auto_timestamp_s },
{ consumer = { type = "foreign", reference = "consumers", required = true, on_delete = "cascade", }, },
{ key = { type = "string", required = false, unique = true, auto = true }, },
{ tags = typedefs.tags },
},
},
}
kong.plugins.<plugin_name>.daos
kong缓存级别
官网链接
-
L1: lua内存缓存 单个Nginx worker进程级别的缓存,可以保存任何类型的Lua值。 -
L2: 共享缓存 (Shared memory cache ,SHM) Nginx 节点级别的缓存,可以被所有Nginx worker进程共享,这只能保存标量值,因此需要对更复杂的类型(如Lua表)进行(反)序列化。
从数据库中提取数据时,数据将存储在两个缓存中。如果同一worker进程再次请求数据,它将从Lua内存缓存中检索以前反序列化的数据。如果同一Nginx节点中的另一个worker请求该数据,它将在SHM中找到该数据,对其进行反序列化(并将其存储在自己的Lua内存缓存中),然后返回该数据。
缓存的基本函数
local key = kong.request.get_query_arg("apikey")
local cache_key = kong.db.keyauth_credentials:cache_key(key)
local credential, err = kong.cache:get(cache_key, nil, load_entity_key, apikey)
if err then
kong.log.err(err)
return kong.response.exit(500, { message = "Unexpected error" })
end
if not credential then
return kong.response.exit(401, { message = "Invalid authentication credentials" })
end
先创建一个缓存cache_key键,然后使用该键从缓存中检索该键(如果缓存未命中,则从数据库中检索)
缓存的清除
当需要在数据库中更新或删除缓存的自定义实体(例如用Admin API),此时数据库中的数据与缓存在节点内存中的数据之间会产生不一致。为了避免这种不一致性,我们需要从内存存储中取出缓存的实体,并强制Kong从数据库中再次查询,我们将此过程称为缓存失效。
如果希望缓存的实体在CRUD操作时失效,而不是等待它们到达TTL,那么必须遵循以下几个步骤。大多数实体都可以自动执行此过程,但可能需要手动订阅某些CRUD事件才能使某些关系更复杂的实体失效。
自动缓存失效(原理)
如果依赖实体架构的cache_key 属性,则可以为实体提供现成的自动缓存失效机制 : 当与该key相关的CRUD操作发生时,都会使得kong产生一个受影响的cache_key ,并将其广播到集群上的所有其他节点,以便它们可以从缓存中驱逐该特定值,并在下一个请求到来时,重新从数据库中获取新值。
注意:Kong提供的负缓存。在上面的示例中,如果给定key 在数据库中没有找到,缓存模块将该key存储一个miss 标记,就像它是命中一样。同样该“创建”事件也由Kong传播到各个节点。等将来经过CRUD操作后,该key有更新真正有效的值,此时各个节点可以将缓存里存储的miss 标记驱逐,并从数据库中获取新创建的apikey。
手动缓存失效
要监听Kong内部的缓存失效,需要在插件的init_worker处理程序中实现以下内容:
function MyCustomHandler:init_worker()
kong.worker_events.register(function(data)
end, "crud", "consumers")
kong.worker_events.register(function(data)
kong.log.inspect(data.operation)
kong.log.inspect(data.old_entity)
kong.log.inspect(data.entity)
kong.log.inspect(data.schema)
end, "crud", "consumers:update")
end
一旦为所需实体设置了上述侦听器,可以按照自己的意愿对插件缓存的任何实体执行手动失效,例如:
kong.worker_events.register(function(data)
if data.operation == "delete" then
local cache_key = data.entity.id
kong.cache:invalidate("prefix:" .. cache_key)
end
end, "crud", "consumers")
|