Modifying cache metadata using lua module.

758 views
Skip to first unread message

Makailol Charls

unread,
Jan 28, 2014, 11:11:41 PM1/28/14
to openre...@googlegroups.com
Hello

I was trying to use https://github.com/cloudflare/lua-nginx-cache-module module with ngx_lua module and I noticed that every second request goes to backend and every second request's response header says cache-status "EXPIRED" regardless of first request is MISS or EXPIRED. After that all subsequent requests get HIT until it actually expired according to time defined in header_filter_by_lua .

I have used the same code which is given in readme file. And proxy to same nginx server running at higher port.

I have also noticed that the cache file is being created on first request only which is expected behavior and if I remove this header_filter_by_lua code, each second request gets cache HIT.

So can anyone help me to find out the reason why every second request goes to backend and sends response header cache-status "EXPIRED" instead it should get HIT?

Thanks,
Makailol

Brian Akins

unread,
Jan 29, 2014, 2:40:03 PM1/29/14
to openre...@googlegroups.com
FWIW, I've had nothing but pain trying to use the built-in nginx cache in a programatic way.  I usually use a shared dictionary or redis rather than trying to deal with it.  This doesn't answer your question, but just a bit of advice from someone who went down that road before.

Yichun Zhang (agentzh)

unread,
Jan 29, 2014, 2:47:06 PM1/29/14
to openresty-en
Hello!

On Tue, Jan 28, 2014 at 8:11 PM, Makailol Charls wrote:
> I was trying to use https://github.com/cloudflare/lua-nginx-cache-module
> module with ngx_lua module and I noticed that every second request goes to
> backend and every second request's response header says cache-status
> "EXPIRED" regardless of first request is MISS or EXPIRED.

Nobody is maintaining this module right now and I have no idea what
the current state of this module.

I may take the maintainership in the next quarter because our company
will probably make use of it online :)

Thank you for trying it out anyway :)

Best regards,
-agentzh

Peter Booth

unread,
Jan 30, 2014, 12:44:15 AM1/30/14
to Openresty
Brian,

The nginx cache is tremendously powerful and I believe that, when combined with openresty, 
it can be made to do *anything*. 

Note that I didn’t say easily do anything.

I spent a few hours a week over a year building a bunch of caches that that implemented very 
complex business rules. Each page was a single Location block of 40 to 60 lines. I’ve attached one 
at the end of this mail as an example.

The cache configuration options are very subtle, and the way that they interact isn’t linear or obvious 
but it does make sense. The best way to debug is to use wget -S, with a custom .wgetrc that pretends to be a browser
If your website is visible on the internet then redbot.org can be a very useful tool

If you want specific help then I suggest that you include:

  • your entire nginx.conf
  • the output of wget -S when you are requesting a series of representative pages
  • the first ten lines of some cached files (which shows cache key)
Here’s an example of an nginx cache definition for a page that has quite a complex cache key:

Hpe this helps,

Peter


# Blog pages get cached
        location ~ /blog/ {
            # Cleanup the cache-busting URLs used by the hackers who attacked in Nov 2012  
            rewrite "/(.*)/2];ord.*$" $1 ;

            proxy_no_cache $arg_mid $arg_siteID;
            proxy_cache_bypass $arg_mid $arg_siteID;
            proxy_cache_use_stale updating;
            default_type text/html;
            proxy_cache_valid 200 302 301 15m;
            proxy_ignore_headers Set-Cookie Cache-Control; 
            proxy_pass_header off;
            proxy_hide_header Set-Cookie;
            # this is to prevent our backend's Expires header from busting the cache.
            # It doesn't actually enable browser caching because Akamai overwrites it
            expires 900s;
            add_header  Last-Modified "";
            add_header  ETag "";

            

            # Build cache key            
            set $e4x_currency $cookie_google_lang;
            set_if_empty $google_lang ‘ENG';
            set $num_items $cookie_NumberOfItems;
            set_if_empty $num_items 'LOW';
            set $nao $arg_Nao;
            set_if_empty $nao '0_nao';
            set $ns $arg_ns;
            set_if_empty $ns '0_ns';
            set $orig_uri $uri;            
            # If a page name contains a colon then cache it with a pipe sign instead
            set_by_lua $key_uri '
                local nu = string.gsub(ngx.var.orig_uri, ":", "|");
                 return nu;
            ';
            set $brand_landing $arg_adminPage;
            set_if_empty $admin_page 'false';
            set $oper $cookie_OPER;
            set_if_empty $oper '0_oper';
            proxy_cache_key "$key_uri|$nao|$ns|$google_lang|$num_items|$oper|$admin_page";
            proxy_cache blog_pages;            
            # Add Canonical URL string
            set $folder_id $arg_FOLDER%3C%3Efolder_id;
            set $canonical_url "http://$http_host$uri";
            add_header Link "<$canonical_url>; rel=\"canonical\"";
            proxy_pass http://apache$request_uri;
        }


--
You received this message because you are subscribed to the Google Groups "openresty-en" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openresty-en...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Makailol Charls

unread,
Jan 30, 2014, 12:49:28 AM1/30/14
to openre...@googlegroups.com
Hello,

Thanks Brian for your comments and suggestion on this. I will check the possibility to use redis as replacement of core proxy cache. I want to cache large number of static contents like images, some js and css too. But main thing is I would like to add proper purging mechanism and different server and client side caching TTL.

Thanks agentzh for information about this module. I'd read somewhere in openresy-en mailing list about this module which can be used to modify cache metadata so I thought your company might be using it in production for changing TTL for server side caching and browser side caching and someone was maintaining it too.

Would you share some example how can we set the TTL for server side caching ( regardless of backend caching headers) and different time of expire headers for browser caching using ngx_lua ?

Regards,
Makailol

Brian Akins

unread,
Jan 30, 2014, 2:44:03 PM1/30/14
to openre...@googlegroups.com
Peter, I am quite familiar with the internals of nginx and of ngx-lua. Your example didn't have cache manipulation in Lua, so it doesn't fit my use cases.  The cache internals make certain assumptions that aren't always true when doing full applications in Lua - particularly around sub requests, etc.  Also, in a openresty app, I wanted to cache things that weren't http requests as well (i.e., database calls).  I almost had a generic interface to the cache internals that fit my needs when I decided to throw it out and just use shared dictionaries. The code was then pure Lua and pretty compact.

The original use case is touched on briefly in my talk at Ricon last year.

Peter Booth

unread,
Jan 30, 2014, 4:20:30 PM1/30/14
to openre...@googlegroups.com, openre...@googlegroups.com
Brian,

I've used lua to augment nginx ability to implement logic not to access the cache from lua. For my needs that was sufficient.

Is there something particular about your use case that makes the subrequest feature very compelling?  

Peter

Sent from my iPhone

On Jan 30, 2014, at 2:44 PM, Brian Akins <br...@akins.org> wrote:

Peter, I am quite familiar with the internals of nginx and of ngx-lua. Your example didn't have cache manipulation in Lua, so it doesn't fit my use cases.  The cache internals make certain assumptions that aren't always true when doing full applications in Lua - particularly around sub requests, etc.  Also, in a openresty app, I wanted to cache things that weren't http requests as well (i.e., database calls).  I almost had a generic interface to the cache internals that fit my needs when I decided to throw it out and just use shared dictionaries. The code was then pure Lua and pretty compact.

The original use case is touched on briefly in my talk at Ricon last year.

--

Brian Akins

unread,
Jan 30, 2014, 6:50:27 PM1/30/14
to openre...@googlegroups.com
Yes, some of the items I fetch can contain instructions to fetch other items - think server side includes or using a map-reduce to get a list of id's then fetching those id's.  The original reason I was going to use the built in cache is because it is there, however it does its job very nicely and nothing else very well.  Once I went to share dictionaries (and then redis) I had a lot more "freedom."

If you have most of you work in the nginx side of things, then the built in cache is probably fine. Once you get into a primarily Lua driven openresty setup/app, then its probably best to handle the cache in Lua. Much better control of serving stale, expiration, etc. Also, the filesystem and global locks in nginx become a bottleneck for some use cases as each cache item is a file and there is a global lock per cache zone.  Some of these issues only become apparent in some of the edge use cases, but unfortunately most of my use cases are on the edge.
Reply all
Reply to author
Forward
0 new messages