nic-6443 opened a new pull request, #14061:
URL: https://github.com/apache/apisix/pull/14061

   ### Description
   
   `oas-validator` caches specs fetched from `spec_url` in a per-worker 
lrucache keyed by the URL (plus `ssl_verify` and a hash of the request 
headers), with `count = 512` and no memory bound. Every distinct URL adds a 
fully compiled copy, and a URL that is no longer requested stays cached until 
count eviction, since resty.lrucache only expires entries lazily. With large 
specs a compiled copy is easily 10+ MB, so a route whose `spec_url` changes 
over time (e.g. a versioned spec URL) grows worker memory on every change until 
the process is OOM-killed.
   
   The cache is now keyed by the resource that declares the plugin 
(`conf._meta.parent.resource_key`, which `set_plugins_meta_parent` sets for 
routes, services, consumers, consumer groups, plugin configs and global rules), 
with the URL key as the version. When a resource switches to another URL its 
slot is overwritten, so the old compiled spec loses its last reference right 
away. If a conf has no parent, the URL-keyed behavior is kept.
   
   To keep sharing one compiled spec across resources that declare the same 
URL, compiled entries are also kept in a weak-valued table keyed by the URL 
key. A new slot reuses an entry from there only while it is younger than 
`spec_url_ttl`, so the TTL refresh still refetches the spec. Stale serving, 
background refresh and serial creation are unchanged.
   
   There is a second leak on the same path: changing `spec_url_ttl` in the 
plugin metadata rebuilds the lrucache, but `core.lrucache` keeps every lrucache 
it ever created as a key of its internal `stale_obj_pool`, so the old cache and 
every spec in it stay alive forever. That pool is now weak-keyed. Its values 
(pending refresh jobs) do not reference the lrucache itself, so a dropped 
lrucache can be collected; lrucaches that are still in use are unaffected.
   
   Tests assert release through fetch counts on the local spec server, not 
memory numbers:
   
   - changing a route's `spec_url` and running a full GC makes another route 
declaring the old URL fetch it again (on master it is served from the URL-keyed 
cache, so the count stays at 1)
   - two routes declaring the same URL fetch it once
   - after changing `spec_url_ttl` and a full GC, a spec held only by the 
previous cache is fetched again
   - with a 1s TTL and two routes sharing one URL, the background refresh still 
refetches the spec
   - `t/core/lrucache.t`: an lrucache dropped by its owner releases its cached 
objects
   
   ### Checklist
   
   - [x] I have explained the need for this PR and the problem it solves
   - [x] I have explained the changes or the new features added to this PR
   - [x] I have added tests corresponding to this change
   - [x] I have updated the documentation to reflect this change
   - [x] I have verified that this change is backward compatible (If not, 
please discuss on the [APISIX mailing 
list](https://github.com/apache/apisix/tree/master#community) first)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to