2

I am using the open source Nginx as the web server with Proxy_cache.

I have a unique usecase of deleting the key in cache as well as pass the request to the backend servers to delete the key in DB without caching the response.

So delete key in Web server cache and backend DB in same request.
Client => load balancer => Nginx(proxy_cache) => application => PostgreSQL

e.g Nginx.conf

if ( $http_x_delete_key ){
  content_by_lua_file ./purge_key.lua;
  proxy_pass          http://backend_servers; 
}

e.g purge_key.lua

...
if ngx ~= nil then
    ...
    delete_file(filename)
    ngx.log(ngx.NOTICE, 'deleted')
    -- ngx.exit(ngx.OK);
    -- return
end

The 'if' block in Nginx location section just stops the flow (How nginx "location if" works) and returns the response without sending it to the backend and is not passing the request as it is.
I have even compiled OpenResty using the free 'ngx_cache_purge' module but the purge command also doesn't pass the request to the backend.

Generally you timeout or refresh the key using the backend response but in my case I need more explicit control to delete the key either in the same request or it's response.

Does Openresty+Memcache, Apache httpd, Apache Traffic Server or Varnish (vcl_purge and pass) solve this usecase or is there some other way to do it?

dv3
  • 31
  • 4

2 Answers2

1

I have kind of found a way to do this.

Depending on the HTTP request header value, run a lua script to delete the cache file (hash of key and it's last x+y characters if x:y cache level) in Nginx's proxy_cache.

Using 'access_by_lua' instead of 'content_by_lua' as the content handler phase will always exit and return even if I don't write 'ngx.exit' or 'ngx.OK'.

I have to run the lua script in the NGX_HTTP_ACCESS_PHASE and not in the NGX_HTTP_CONTENT_PHASE as I am not generating content or response which should come from the backend in my scenario.

e.g Nginx.conf

proxy_cache_bypass     $http_x_delete_key;
proxy_no_cache         $http_x_delete_key;

if ( $http_x_delete_key ){
  ...
  access_by_lua_file ./purge_key.lua;
}

When the delete key request comes, Nginx will
1. Run the lua script to delete cache file but not return immediately as it's in access phase
2. Request will bypass the cache
3. Upon receiving the request the application will delete key in the DB
4. The response will not be cached in Nginx proxy_cache

dv3
  • 31
  • 4
0

The common approach is to have the application do both- delete from cache and from the database. Alternatively, have the nginx hosted lua do both.

Generally speaking, any multi-stage/multi-upstream kind of request processing is application tier, not webserver/network tier. No configuration-driven proxy server should be bent into the shape of solving that problem.

So do it as part of your application, and decide whether the right footprint is in the upstream codebase or in lua. Most likely the best place is the upstream codebase.

Jonah Benton
  • 1,242
  • 7
  • 13
  • I have to setup things around a legacy application code and so it requires tinkering with everything else in the architecture to suit it. – dv3 May 23 '18 at 18:26