fastcgi cache how-to cache for logged-in users and make it custom for each user
Currently I'm doing cache using fastcgi_cache for non-logged-in users, and using ( if + fastcgi_no_cache + fastcgi_cache_bypass ) to pass logged-in users directly to backend which is PHP-FPM.
this work good enough, but when PHP-FPM start hitting 500+ req/s the slow/load start.
So what i'm thinking about is to create a cache for logged-in users and each user has it's own cached files, is that possible? if yes can you please provide me some tips about that. I've goggled a lot but nothing help with that.
the site running custom php cms with mysql and memcached and apc
cat /etc/nginx/nginx.comf
user username username;
worker_processes 8;
worker_rlimit_nofile 20480;
pid /var/run/nginx.pid;
events {
worker_connections 10240;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
error_log /var/log/nginx/error.log warn;
log_not_found off;
log_subrequest off;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 3;
keepalive_requests 50;
send_timeout 120;
connection_pool_size 256;
chunked_transfer_encoding on;
ignore_invalid_headers on;
client_header_timeout 60;
large_client_header_buffers 4 128k;
client_body_in_file_only off;
client_body_buffer_size 512K;
client_max_body_size 4M;
client_body_timeout 60;
request_pool_size 32k;
reset_timedout_connection on;
server_name_in_redirect off;
server_names_hash_max_size 4096;
server_names_hash_bucket_size 256;
underscores_in_headers off;
variables_hash_max_size 4096;
variables_hash_bucket_size 256;
gzip on;
gzip_buffers 4 32k;
gzip_comp_level 1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 0;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/javascript text/xml application/xml application/xml+rss application/atom+xml;
open_file_cache max=3000 inactive=20s;
open_file_cache_min_uses 1;
open_file_cache_valid 20s;
open_file_cache_errors off;
fastcgi_buffer_size 8k;
fastcgi_buffers 512 8k;
fastcgi_busy_buffers_size 16k;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_min_uses 1;
fastcgi_cache_path /dev/shm/nginx levels=1:2 keys_zone=website:2000m inactive=1d max_size=2000m;
fastcgi_connect_timeout 60;
fastcgi_intercept_errors on;
fastcgi_pass_request_body on;
fastcgi_pass_request_headers on;
fastcgi_read_timeout 120;
fastcgi_send_timeout 120;
proxy_temp_file_write_size 16k;
fastcgi_max_temp_file_size 1024m;
include /etc/nginx/vhosts/*.conf;
}
vhost settings :
server {
listen 80;
server_name domain.com;
access_log off;
error_log /var/log/nginx/error.log warn;
root /home/username/public_html;
location ~ \.php$ {
# pass cache if logged in
set $nocache "";
if ($http_cookie ~ (MyCookieUser*|MyCookiePass*)) {
set $nocache "Y";
}
fastcgi_no_cache $nocache;
fastcgi_cache_bypass $nocache;
fastcgi_cache website;
fastcgi_cache_key $host$uri$is_args$args;
fastcgi_cache_valid 200 301 302 304 40s;
fastcgi_cache_valid any 5s;
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503 http_404;
fastcgi_ignore_headers Set-Cookie;
fastcgi_hide_header Set-Cookie;
fastcgi_ignore_headers Cache-Control;
fastcgi_hide_header Cache-Control;
fastcgi_ignore_headers Expires;
fastcgi_hide_header Expires;
fastcgi_no_cache $nocache;
fastcgi_cache_bypass $nocache;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:8081;
fastcgi_param SCRIPT_FILENAME /home/username/public_html$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|ppt|txt|mid|swf|midi|wav|bmp|js)$ {
root /home/username/public_html;
expires max;
add_header Cache-Control cache;
}
}
php-fpm config
emergency_restart_threshold = 10
emergency_restart_interval = 60s
process_control_timeout =10s
rlimit_files = 102400
events.mechanism = epoll
[www]
user = username
group = username
listen = 127.0.0.1:8081
listen.backlog = 10000
pm = dynamic
pm.max_children = 2048
pm.start_servers = 64
pm.min_spare_servers = 20
pm.max_spare_servers = 128
pm.process_idle_timeout = 10s;
pm.max_requests = 50000
request_slowlog_timeout = 40s
request_terminate_timeout = 60s
Server RAM : 32GB DDR3 Processor : Dual E5620 Centos6 64bit
Solution 1:
You just need to add a variable string to fastcgi_cache_key
that represents the user ID. Something like:
set $user_key 0;
if ($cookie_userid != "") { // you set cookie "userid" via your app
set $user_key $cookie_userid;
}
fastcgi_cache_key $user_key$scheme$host$uri$args;
This way, all anonymous users will get $user_key = 0
, and the rest of your users will have their own cached version of each page.
Depending on your traffic, this could be heavy on whatever storage you choose, as you will be saving tons of duplicate pages with (maybe?) small personalizations.