WordPress博客二级域名动静分离的方法
网站搬家
最近又给博客搬了家,从linode日本搬到了阿里云,一方面是为了提高国内的访问速度,另一方面也是为了完成域名备案后享受国内CDN的服务。整个搬家的过程不赘述,主要包含下面几个部分要考虑:
- 新站LNMP环境设置,包含ngx_purge, image_filter, memcached等各种网站插件
- 备份源站数据库和网站文件
- rsync传输数据库和网站到新站
- 还原数据
- 配置PHP, nginx的各种参数
- 设置DNS解析到新站,重新申请HTTPS证书
- 设置定时备份脚本
- 设置海外备用站点和同步等
详细的过程以后有空再发一篇博文,这里先挖一个坑。
需要注意的是,linode上的站点先不要关了,还是留着等搜索引擎的DNS记录都更新以后,才能考虑关闭旧站。
动静分离的目的
原本网站里所有的静态资源都是在主域名主域名下面,图片等都在wp-uploads/目录下。一开始也没考虑过动静分离,因为linode的G口带宽足以应付每秒上千个请求,相应速度都不是一个问题。那么现在搬到阿里云的1M小水管后,平均1个3,4百KB的网页需要3秒钟才能下载完成,如果有几个IP同时访问的话就能明显感觉到卡顿了。因此不得不为将来的性能问题做考虑,加入以后上了CDN以后,要加速静态资源,最好将静态资源都放在一个单独的二级域名下,比如“static.feiqy.com”,这样CDN只加速这一个域名下的图片等文件,网页文件从主站下载,就能大大减轻带宽的压力,应付10来个IP应该没有什么问题。即使暂时不接入CDN加速,多一个域名能提高浏览器同时加载资源的数量,也是不错的。
也考虑过如果不用二级域名做动静分离,而采用融合CDN全站加速的方案,这样和目前的nginx插件image_filter缩略图功能、和nginx的fastcgi网页缓存功能有冲突,暂时不想对nginx的优化方案做大改动,所以不考虑全站加速。
方法
假如主域名和静态文件域名分别为www.feiqy.com和static.feiqy.com,需要完成下面几件事情。
添加二级域名static.feiqy.com,解析到主域名服务器(暂不接入CDN)
申请二级域名HTTPS证书
这里需要申请static.feiqy.com的证书,假定当前使用的证书是Let’s encrypt签发的话,不支持泛域名*.feiqy.com,因此需要给当前的证书新增一个域名。certbot-auto脚本的使用方法在前文certbot也介绍过,这里只列出命令,需要注意的是签发证书时不要忘记停止nginx服务。
1 |
./certbot-auto certonly --standalone --email info@feiqy.com -d feiqy.com -d www.feiqy.com -d static.feiqy.com -d static1.feiqy.com |
为二级域名和主域名分别配置nginx站点,并且设置为相同的根目录
这一步是重点,需要分别设置主域名和静态资源域名的nginx配置,首先是二级域名的配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
server { listen 443 ; server_name static.feiqy.com; root /home/wwwroot/feiqy.com; ssl on; ssl_certificate /etc/letsencrypt/live/feiqy.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/feiqy.com/privkey.pem; add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; location ~* .*\.(gif|jpg|jpeg|png|bmp)?$ { set $width ''; set $height ''; set $width $arg_width; set $height $arg_height; if ( $width != '' ) { add_header Thumbnail "By Nginx"; } if ( $height = '' ) { set $height '-'; } if ( $width = '' ) { set $width '-'; set $height '-'; } image_filter resize $width $height; image_filter_buffer 2M; image_filter_jpeg_quality 80; image_filter_transparency on; expires max; access_log off; } location ~ .*\.(eot|otf|ttf|woff|woff2)?$ { add_header Access-Control-Allow-Origin *; expires max; access_log off; } location ~ .*\.(js|css)?$ { expires 12h; access_log off; } location = /robots.txt { deny all; } access_log /home/wwwlogs/static.feiqy.com.log; } |
需要注意的几点:
- root指令需要设成和主域名一样的根目录
- location ~* .*\.(gif|jpg|jpeg|png|bmp)?$的指令里利用image_filter来生成缩略图,缩略图处理必须在静态资源域名下处理。
- location ~ .*\.(eot|otf|ttf|woff|woff2)?$的指令里要记得加上Access-Control-Allow-Origin的http头部,不然会出现字体加载的跨域错误。
- location = /robots.txt的指令里禁止搜索引擎爬虫抓取。
然后是主域名的nginx配置,这里重点是将所有静态资源的处理都移到了二级域名去处理,因此只留下了动态资源处理和fastcgi缓存的部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
fastcgi_cache_path /tmp/wpcache levels=1:2 keys_zone=WORDPRESS:250m inactive=1d max_size=1G; fastcgi_temp_path /tmp/wpcache/temp; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; server { listen 443 default; #listen [::]:80; server_name www.feiqy.com feiqy.com; index index.html index.htm index.php default.html default.htm default.php; root /home/wwwroot/feiqy.com; if ($host = 'feiqy.com') { rewrite ^(.*)$ https://www.feiqy.com$1 permanent; } ssl on; ssl_certificate /etc/letsencrypt/live/feiqy.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/feiqy.com/privkey.pem; add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; set $skip_cache 0; if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") { set $skip_cache 1; } if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; } location ~ [^/]\.php(/|$) { try_files $uri =404; fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; include fastcgi.conf; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; add_header X-Cache "$upstream_cache_status From $host"; fastcgi_cache WORDPRESS; fastcgi_cache_valid 200 301 302 1d; } location / { try_files $uri $uri/ /index.php?$args; rewrite /wp-admin$ $scheme://$host$uri/ permanent; } location ~ /.well-known { allow all; } location /xmlprc.php { deny all; } location = /robots.txt { access_log off; log_not_found off; } location ~ /\. { deny all; access_log off; log_not_found off; } access_log /home/wwwlogs/www.feiqy.com.log; } |
注意网站根目录和二级域名的一样。
具体内容的含义主要参考自于zhangge.net
在workdpress当前主题的functions.php中,重写静态资源URL为二级域名
目前网站中所有的静态资源还是通过类似下面的URL访问,那么怎么样才能使得这些域名变成static.feiqy.com的形式呢?
https://static.feiqy.com/wp-content/uploads/2017/10/18902_en_1.jpg
一种考虑是通过直接修改数据库所有静态资源URL,全部批量替换为static.feiqy.com开头,那么以后新的文章还是不能自动变成二级域名,网上查到一种方法是通过修改wordpress某个地方,暴露出设置选项能全局修改媒体库的URL,这种方法我没有尝试。
另一种方法是直接在主题的代码中自动重写所有静态资源的域名,一劳永逸而且随时可以改成别的域名。
将下面的代码加入主题中functions.php,放在
?>前面。
这样在网页中所有的静态资源(jpg,js,css,gif,png,jpeg,woff)都自动地替换成为static开头的域名。如果有需要还可以加入其它种类的资源,比如ttf,mp4等文件。
1 2 3 4 5 6 7 8 9 10 11 12 |
function QiNiuCDN(){ function Rewrite_URI($html){ $pattern ='/https:\/\/(www\.|)feiqy\.com\/wp-([^"\']*?)\.(jpg|js|css|gif|png|jpeg|woff)/i'; $replacement = 'https://static.feiqy.com/wp-$2.$3'; $html = preg_replace($pattern, $replacement,$html); return $html; } if(!is_admin()){ ob_start("Rewrite_URI"); } } add_action('init', 'QiNiuCDN'); |
完成这一步,在浏览器的调试模式下看看效果,所有的图片都变成了独立的二级域名。
最后不要忘了,在wp-config.php里定义COOKIE_DOMAIN 常量来限制cookie的作用域,因此当浏览器加载静态资源域名里的内容时,request header里不会带有主域名的cookie,节约了传输带宽,达到提高加载速度的目的。
define('COOKIE_DOMAIN', 'www.feiqy.com');
效果
测一下全国各地首页打开速度,基本上还行。
压力测试就不做了,毕竟只有1M的带宽。
下次有空了再接入七牛、又拍云等CDN看看效果,毕竟只对静态资源加速是很容易的事。
本文出自扉启博客,转载时请注明出处及相应链接。
本文永久链接: https://www.feiqy.com/wordpress-static-separation/
一条评论
wp后台可以自定义上传目录以及上传文件的域名,在http://域名/wp-admin/options.php路径中