页面加载时间已成为每一个电子商务网站的非常重要的一项指标。而 Magento 是一个资源消耗的大户,如果不使用诸如反向代理和整页缓存机制的话,其性能是非常之差。而使用 nginx + memcached 来创建一个整页缓存是非常简单的。
有言在先:
建议不用使用 Varnish 或者是 Magento 自身的整页缓存机制,本文介绍的方案非常简单,如果你使用其他方法可能会引来更多的麻烦,这些麻烦主要集中在缓存的清除上。
另外一个问题是你需要确认使用指定的 URL 来清除两级缓存中的数据。
下面让我们来看具体的实现方法:
这个配置文件我在 Magento 和 WordPress 都测试过!
001 |
#memcache servers load balanced |
002 |
upstream memcached { |
003 |
server server_ip_1:11211 weight=5 max_fails=3 fail_timeout=30s; |
004 |
server server_ip_2:11211 weight=3 max_fails=3 fail_timeout=30s; |
005 |
server server_ip_3:11211; |
006 |
keepalive 1024 single; |
007 |
} |
008 |
#fastcgi - little load balancer |
009 |
upstream phpbackend{ |
010 |
server server_ip_1:9000 weight=5 max_fails=5 fail_timeout=30s; |
011 |
server server_ip_2:9000 weight=3 max_fails=3 fail_timeout=30s; |
012 |
server server_ip_3:9000; |
013 |
} |
014 |
server { |
015 |
listen 80; ## listen for ipv4; this line is default and implied |
016 |
root /var/www/vhosts/kingletas.com/www; |
017 |
server_name kingletas.com; |
018 |
index index.php index.html index.htm; |
019 |
020 |
client_body_timeout 1460; |
021 |
client_header_timeout 1460; |
022 |
send_timeout 1460; |
023 |
client_max_body_size 10m; |
024 |
keepalive_timeout 1300; |
025 |
026 |
location /app/ { deny all; } |
027 |
location /includes/ { deny all; } |
028 |
location /lib/ { deny all; } |
029 |
location /media/downloadable/ { deny all; } |
030 |
location /pkginfo/ { deny all; } |
031 |
location /report/config.xml { deny all; } |
032 |
location /var/ { deny all; } |
033 |
034 |
location ~* \.(jpg|png|gif|css|js|swf|flv|ico)$ { |
035 |
expires max; |
036 |
tcp_nodelay off; |
037 |
tcp_nopush on; |
038 |
} |
039 |
location / { |
040 |
|
041 |
try_files $uri $uri/ @handler; |
042 |
expires 30d; |
043 |
} |
044 |
location @handler { |
045 |
rewrite / /index.php; |
046 |
} |
047 |
048 |
location ~ \.php$ { |
049 |
if (!-e $request_filename) { |
050 |
rewrite / /index.php last; |
051 |
} |
052 |
expires off; ## Do not cache dynamic content |
053 |
default_type text/html; charset utf-8; |
054 |
if ($request_method = GET) { # I know if statements are evil but don't know how else to do this |
055 |
set $memcached_key $request_uri; Catalog request modal |
056 |
memcached_pass memcached; |
057 |
error_page 404 502 = @cache_miss; |
058 |
add_header x-header-memcached true; |
059 |
} |
060 |
if ($request_method != GET) { |
061 |
fastcgi_pass phpbackend; |
062 |
} |
063 |
} |
064 |
location @cache_miss { |
065 |
# are we using a reverse proxy? |
066 |
proxy_set_header X-Real-IP $remote_addr; |
067 |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
068 |
proxy_set_header Host $http_host; |
069 |
proxy_redirect off; |
070 |
proxy_max_temp_file_size 0; |
071 |
|
072 |
#configure fastcgi |
073 |
fastcgi_pass 127.0.0.1:9000; |
074 |
fastcgi_send_timeout 5m; |
075 |
fastcgi_read_timeout 5m; |
076 |
fastcgi_connect_timeout 5m; |
077 |
fastcgi_buffer_size 256k; |
078 |
fastcgi_buffers 4 512k; |
079 |
fastcgi_busy_buffers_size 768k; |
080 |
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code; |
081 |
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name; |
082 |
fastcgi_param PHP_VALUE "memory_limit = 32M"; |
083 |
fastcgi_param PHP_VALUE "max_execution_time = 18000"; |
084 |
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
085 |
include fastcgi_params; |
086 |
} |
087 |
location ~ /\. { |
088 |
deny all; |
089 |
} |
090 |
} |
091 |
#if you want to make it even better your own cdn |
092 |
#server { |
093 |
# listen 80; |
094 |
# server_name ; |
095 |
# root /var/www/vhosts/kingletas.com/www; |
096 |
#} |
097 |
#server { |
098 |
# listen 80; |
099 |
# server_name css.kingletas.com; |
100 |
# root /var/www/vhosts/kingletas.com/www; |
101 |
#} |
102 |
#server { |
103 |
# listen 80; |
104 |
# server_name js.kingletas.com; |
105 |
# root /var/www/vhosts/kingletas.com/www; |
106 |
#} |
另外一个要点需要记住的是 Nginx 试图从内存中读取数据,而不往里面写,也就是说你仍然需要自己负责往 memcached 中写数据,因此我们需要在 WordPress 里的 index.php 做如下处理:
01 |
/** |
02 |
* Front to the WordPress application. This file doesn't do anything, but loads |
03 |
* wp-blog-header.php which does and tells WordPress to load the theme. |
04 |
* |
05 |
* @package WordPress |
06 |
*/ |
07 |
08 |
/** |
09 |
* Tells WordPress to load the WordPress theme and output it. |
10 |
* |
11 |
* <a href="http://my.oschina.net/var" target="_blank" rel="nofollow">@var</a> bool |
12 |
*/ |
13 |
ini_set("memcache.compress_threshold",4294967296); //2^32 |
14 |
ob_start(); |
15 |
16 |
define('WP_USE_THEMES', true); |
17 |
18 |
/** Loads the WordPress Environment and Template */ |
19 |
require('./wp-blog-header.php'); |
20 |
21 |
$buffer = ob_get_contents(); |
22 |
23 |
ob_end_clean(); |
24 |
25 |
$memcache_obj = memcache_connect("localhost", 11211); |
26 |
memcache_add($memcache_obj,$_SERVER['REQUEST_URI'],$buffer,0); |
27 |
28 |
echo $buffer; |
最后需要注意的是,我们必须修改 memcache.compress_threshold 设置项值为很大的数字,因为一旦超限时 memcached 将会忽略不压缩的设置。
同样的思路也适用于 Magento。
















