On my WordPress Caching write up someone mentioned asked a very good question in the comments. What good is the caching if your site gets brought down by excessive search queries?
Great article.
However I have following problem.
My WP setup is like that.
Currently I am on shared hosting with WP + W3 Total cache and during peak hours, my site is very slow. That is mainly because I have a huge traffic from Google.
My webstie caches plenty of keywords with AskApache Google 404 and Redirection.
What happens is that traffic from Google goes to /search/what-ever-keywords dynamicly created everytime. And that is killing my system.
The problem is I have no idea how to help poor server and cache that kind of traffic.Would you have any advice for that ?
Regards,
Peter
Fortunately the Nginx webserver has a way to soften the impact with a module called Limit Request. For wordpress this is how you would implement it:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
#... the rest of your content
server {
#... your server content
location /search {
limit_req zone=one burst=3 nodelay;
try_files $uri /index.php;
}
}
}
What we have here is almost identical to the example provided in the Nginx Wiki (HttpLimitReqModule). Essentially we’ve created a zone that allows a user no more than 1 requests per seconds, assigning them via $binary_remote_addr (which is smaller than $remote_addr while still accomplishing the same goal), within a space of 10MB.
Then we’ve placed a limit_req directive into the /search location. (Remember to include the rewrite so that index.php receives the search request in wordpress) This directive uses the zone we created earlier, allowing for a burst of up to 3 requests from a single user. If the user exceeds the limit too many times (the burst limit) they’re presented with a 503 error which Google and others consider sort of a ‘back off’ response.
By default the burst value is zero.
We use try_files here because rewriting will occur before the limiting had a chance to act, since the rewrite phase takes precedence before most other processes.
Here is an example wordpress configuration utilizing the above, configured for W3TC w/ Memcache (or OpCode Caching), please see the article [ The Importance of Caching WordPress] for details on caching WordPress in other ways, and why you should be using caching with wordpress.
This is config is somewhat based off the same configuration I currently use for kbeezie.com on a FreeBSD server.
user kb244 www;
worker_processes 2;
events {
worker_connections 2048;
}
http {
sendfile on;
tcp_nopush on; # Generally on for linux, off for FreeBSD/Unix
tcp_nodelay on;
server_tokens off;
include mime.types;
default_type application/octet-stream;
index index.php index.htm index.html redirect.php;
#Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_types text/plain text/css application/json application/x-javascript text/xml
application/xml application/xml+rss text/javascript;
#FastCGI
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort on;
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 120;
fastcgi_index index.php;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
listen 80;
# Replace with your domain(s)
server_name kbeezie.com www.kbeezie.com;
# Setting your root at the server level helps a lot
# especially if you don't like having to customize your
# PHP configurations every single time you create a vhost
root /usr/local/www/kbeezie.com;
# Always a good idea to log your vhosts seperately
access_log /var/log/nginx/kbeezie.access.log;
error_log /var/log/nginx/kbeezie.error.log;
# I'm using W3TC with memcache, otherwise this block
# would look a lot more complicated for handling file
# based caching.
location / {
try_files $uri $uri/ /index.php;
}
# And here we have the search block limiting the requests
location /search {
limit_req zone=kbeezieone burst=3 nodelay;
try_files $uri /index.php;
}
# We want WordPress to handle the error page
fastcgi_intercept_errors off;
# Handle static file requests here setting appropiate headers
location ~* \.(ico|css|js|gif|jpe?g|png)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
# I prefer to save this location block in it's own php.conf
# in the same folder as nginx.conf so I can just use:
# include php.conf;
# at the bottom of each server block I want PHP enabled on
location ~ \.php$ {
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_pass unix:/tmp/php5-fpm.sock;
# I use a Unix socket for PHP-Fpm, yours instead may be:
# fastcgi_pass 127.0.0.1:9000;
}
# Browsers always look for a favicon, I rather not flood my logs
location = /favicon.ico { access_log off; log_not_found off; }
# Make sure you hide your .hidden linux/unix files
location ~ /\. { deny all; access_log off; log_not_found off; }
}
}
As always a little research and tweaking to your own requirements is advised.