admin 管理员组

文章数量: 887007

AMH

AMH是业内不错的主机控制面板软件,在8月份的时候,AMH增加了varnish程序的支持,借助varnish可以显著提升网站的打开速度。但是AMH默认安装的varnish并没有一个比较好的配置,也没有清除缓存的动作。不太合理。

那么今天就来实战一下,以wordpress网站的反代为例,分享一下边缘节点反代+缓存的实战经验。

程序安装

AMH默认安装时,是自带LNMP环境的,但反代则需要另外安装LNGX反向代理环境。

登录AMH-7.1面板后台之后,在右上角找到软件商店,然后在网站环境管理里面安装LNGX。

然后还需要安装Varnish缓存程序

AMH环境配置

配置LNGX环境

软件安装成功之后,需要增加反对环境,在软件商店找到LNGX,点击管理

添加一个lngx01的环境

配置varnish

这部分没有其他的配置,主要是需要替换varnish的vcl配置文件,可以在下图找到

用以下内容替换

/*-* Copyright (c) 2006 Verdens Gang AS* Copyright (c) 2006-2015 Varnish Software AS* All rights reserved.** Author: Shing Lau <icodex@msn>** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:* 1. Redistributions of source code must retain the above copyright*    notice, this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright*    notice, this list of conditions and the following disclaimer in the*    documentation and/or other materials provided with the distribution.** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE* ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF* SUCH DAMAGE.** This is the builtin VCL code*/# We're using unix sockets, so we need to declare that we're using VCL 4.1
vcl 4.1;# Import Varnish Standard Module so I can serve custom error pages
import std;import cookie;
import directors;acl purger {"localhost";"127.0.0.1";"172.17.0.1";"10.0.0.0"/8;
}# Setup the backend
backend backend1 {.host = "1.1.1.1"; # `改为源站IP地址`.port = "80"; # `改为源站端口`.first_byte_timeout = 300s;.connect_timeout = 5s;.between_bytes_timeout = 5s;
}#######################################################################
# Client side# Regex purging
# Treat the request URL as a regular expression.
sub purge_regex {ban("obj.http.X-VC-Req-URL ~ " + req.url + " && obj.http.X-VC-Req-Host == " + req.http.host);
}# Exact purging
# Use the exact request URL (including any query params)
sub purge_exact {ban("obj.http.X-VC-Req-URL == " + req.url + " && obj.http.X-VC-Req-Host == " + req.http.host);
}# Page purging (default)
# Use the exact request URL, but ignore any query params
sub purge_page {set req.url = regsub(req.url, "\?.*$", "");ban("obj.http.X-VC-Req-URL-Base == " + req.url + " && obj.http.X-VC-Req-Host == " + req.http.host);
}sub vcl_recv {if (req.restarts > 0) {set req.hash_always_miss = true;}if (req.http.host ~ "(?i)(.*)") {set req.backend_hint = backend1;} else {return (synth(403, "Hostname not found."));}if (req.restarts == 0) {std.collect(req.http.x-forwarded-for);if (req.http.x-forwarded-for) {set req.http.x-forwarded-for = regsub(req.http.x-forwarded-for + ", " + client.ip, "\s*,.*$", "");} else {set req.http.x-forwarded-for = client.ip;}}if (req.http.X-Forwarded-Ssl ~ "(?i)on" ||req.http.Cloudfront-Forwarded-Proto ~ "(?i)https" ||req.http.X-Forwarded-Proto ~ "(?i)https" ||req.http.Proto ~ "(?i)ssl") {set req.http.X-Forwarded-Proto = "https";set req.http.X-Forwarded-Port = "443";}#return (pass);if (req.method == "PRI") {/* We do not support SPDY or HTTP/2.0 */return (synth(405, "We do not support SPDY or HTTP/2.0"));}if (req.method != "GET" &&req.method != "HEAD" &&req.method != "PUT" &&req.method != "POST" &&req.method != "TRACE" &&req.method != "OPTIONS" &&req.method != "DELETE" &&req.method != "PATCH") {/* Non-RFC2616 or CONNECT which is weird. */return (pipe);}# Implementing websocket support (.0/users-guide/vcl-example-websockets.html)if (req.http.upgrade ~ "(?i)websocket") {return (pipe);}# We only deal with GET and HEAD by defaultif (req.method != "GET" && req.method != "HEAD") {/* We only deal with GET and HEAD by default */set req.http.X-VC-Cacheable = "NO:Request method:" + req.method;return (pass);}# Set initial grace period usage statusset req.http.grace = "none";set req.hash_ignore_busy = true;# Normalize the header, remove the port (in case you're testing this on various TCP ports)set req.http.Host = regsub(req.http.host, ":[0-9]+", "");# Normalize the query argumentsset req.url = std.querysort(regsub(req.url, "^http[s]?://", ""));# collect all cookiesstd.collect(req.http.Cookie);if (req.http.Range ~ "bytes=") {set req.http.x-range = req.http.Range;}# Strip hash, server doesn't need it.if (req.url ~ "\#") {set req.url = regsub(req.url, "\#.*$", "");}# Strip a trailing ? if it existsif (req.url ~ "\?$") {set req.url = regsub(req.url, "\?$", "");}# remove ?xxx=xxxxx strings from urls so css and js files are cached.set req.url = regsub(req.url, "\.js\?.*$", ".js");set req.url = regsub(req.url, "\.css\?.*$", ".css");set req.url = regsub(req.url, "\?ver=.*$", "");set req.url = regsub(req.url, "\?replytocom=.*$", "");if (req.http.Authorization ||req.http.Authenticate ||req.http.WWW-Authenticate) {/* Not cacheable by default */set req.http.X-VC-Cacheable = "NO:Requested with: Authenticate";# set req.hash_always_miss = true;return (pass);}# # don't cache logged-in users. you can set users `logged in cookie` name in settings# if (req.http.Cookie) {#     set req.http.X-VC-Cacheable = "NO:Found logged in cookie";#     # set req.hash_always_miss = true;#     return (pass);# }# don't cache XMLHttpRequestif (req.http.X-Requested-With == "XMLHttpRequest") {set req.http.X-VC-Cacheable = "NO:Requested with: XMLHttpRequest";# set req.hash_always_miss = true;return (pass);}if (req.http.Cache-Control && req.http.Cache-Control ~ "(?i)private") {set req.http.X-VC-Cacheable = "NO:Private Use";# set req.hash_always_miss = true;return (pass);}if (req.url ~ "^[^?]*\.(?i)(asp|aspx|ashx|php|php4|php5|cgi|pl|perl|jsp|do)(\?.*)?$" || req.url ~ "\?nocache") {set req.http.X-VC-Cacheable = "NO:Pass through the dynamic request";# set req.hash_always_miss = true;return (pass);}# don't cache ajax requestif (req.url ~ "^.*/ajax/.*$" || req.url ~ "^.*/ahah/.*$") {set req.http.X-VC-Cacheable = "NO:Requested with: Ajax";return (pass);}if (req.url ~ "^/admin/" || req.url ~ "/paypal/") {set req.http.X-VC-Cacheable = "NO:Requested with: manager area";return (pass);}if ( req.url ~ "(?i)(phpmyadmin|status|munin|server-status|nocache|feed|get|ip)" ||req.url ~ "(?i)(sitemap.xml($|\.gz$))" ) {set req.http.X-VC-Cacheable = "NO:Pass through the known exclude";set req.hash_always_miss = true;return (pass);}# don't cache logged-in users. you can set users `logged in cookie` name in settingsif (req.http.Cookie ~ "(?i)(wp-postpass_|wordpress_logged_in_|comment_author)") {set req.http.X-VC-Cacheable = "NO:Found logged in cookie";# set req.hash_always_miss = true;return (pass);}# don't cache these special pagesif (req.url ~ "(?i)(nocache|wp-admin|wp-(json|comments-post|login|activate|mail)\.php|bb-admin|server-status|control\.php|bb-login\.php|bb-reset-password\.php|register\.php)") {set req.http.X-VC-Cacheable = "NO:Special page: " + req.url;# set req.hash_always_miss = true;return (pass);}# Pass through the WooCommerce dynamic pagesif (req.url ~ "^/(cart|my-account/*|checkout|wc-api/*|addons|logout|lost-password|product/*)") {set req.http.X-VC-Cacheable = "NO:Pass through the WooCommerce dynamic pages";# set req.hash_always_miss = true;return (pass);}# Pass through the WooCommerce add to cartif (req.url ~ "\?add-to-cart=" ) {set req.http.X-VC-Cacheable = "NO:Pass through the WooCommerce add to cart";# set req.hash_always_miss = true;return (pass);}# Pass through the WooCommerce APIif (req.url ~ "\?wc-api=" ) {set req.http.X-VC-Cacheable = "NO:Pass through the WooCommerce API";# set req.hash_always_miss = true;return (pass);}if (req.url ~ "^[^?]*\.(?i)(xmlrpc.php|wlmanifest.xml)(\?.*)?$") {# unset cookie only if no http authif (!req.http.Authorization) {unset req.http.Cookie;}return (pass);}if (req.http.Accept-Encoding) {# Do no compress compressed files...if (req.url ~ "^[^?]*\.(?i)(jpg|jpeg|webp|png|gif|bmp|gz|tgz|bz2|tbz|lzma|mp3|ogg|swf|ico)(\?.*)?$") {# No point in compressing theseunset req.http.Accept-Encoding;} elsif (req.http.Accept-Encoding ~ "gzip") {set req.http.Accept-Encoding = "gzip";} elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") {set req.http.Accept-Encoding = "deflate";} else {# unknown algorithmunset req.http.Accept-Encoding;}}if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") {set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", "");set req.url = regsub(req.url, "[?|&]+$", "");}# Remove all cookies for static files# A valid discussion could be held on this line: do you really need to cache static files that don't cause load? Only if you have memory left.# Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory).# Before you blindly enable this, have a read here:  (req.method ~ "^(GET|HEAD)$" &&(req.http.Content-Type ~ "(?i)(octet-stream|audio|video)" ||req.url ~ "^[^?]*\.(?i)(bmp|css|csv|doc|docx|eot|gif|ico|jpeg|jpg|js|less|pdf|png|ppt|pptx|rtf|svg|svgz|swf|ttf|txt|webp|woff|woff2|xls|xlsx|xml|avi|flac|flv|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|wav|webm|7z|bz2|gz|rar|tar|tgz|tbz|txz|xz|zip)(\?.*)?$")) {# enable this if you need itif (req.url ~ "nocache") {set req.http.X-VC-Cacheable = "NO:Not cacheable, nocache in URL";return (pass);}# unset cookie only if no http authif (!req.http.Authorization) {unset req.http.Cookie;}}# Send Surrogate-Capability headers to announce ESI support to backendset req.http.Surrogate-Capability = "key=ESI/1.0";set req.http.X-VC-My-Purge-Key = "";if (req.method == "PURGE" || req.method == "SOFTPURGE" || req.method == "BAN") {if (req.http.X-VC-Purge-Key == req.http.X-VC-My-Purge-Key) {set req.http.X-VC-Purge-Key-Auth = "true";} else {set req.http.X-VC-Purge-Key-Auth = "false";}if (client.ip !~ purger && req.http.X-VC-Purge-Key-Auth != "true") {
#            return (synth(405, "Not allowed from " + client.ip));}if (req.http.X-VC-Purge-Method) {if (req.http.X-VC-Purge-Method ~ "(?i)regex") {call purge_regex;} elsif (req.http.X-VC-Purge-Method ~ "(?i)exact") {call purge_exact;} else {call purge_page;}} else {# No X-VC-Purge-Method header was specified.# Do our best to figure out which one they want.if (req.url ~ "\.\*" || req.url ~ "^\^" || req.url ~ "\$$" || req.url ~ "\\[.?*+^$|()]") {call purge_regex;} elsif (req.url ~ "\?") {call purge_exact;} else {call purge_page;}}if (req.method == "BAN") {ban("obj.http.X-URL ~ " + req.http.X-Ban);/* Throw a synthetic page so the request won't go to the backend. */return(synth(200, "Ban added"));} else {# If you got this stage (and didn't error out above), purge the cached resultreturn (purge);}return (synth(200,"Purged " + req.url + " " + req.http.host));}unset req.http.X-VC-My-Purge-Key;# unset Varnish Caching custom headers from client#unset req.http.X-VC-Cacheable;#unset req.http.X-VC-Debug;return (hash);
}sub vcl_hash {hash_data(req.url);if (req.http.x-range ~ "bytes=") {hash_data(req.http.x-range);unset req.http.Range;}if (req.http.host) {hash_data(req.http.host);} else {hash_data(server.ip);}
}sub vcl_backend_response {set beresp.grace = 3d;set beresp.http.X-VC-Req-Host = bereq.http.host;set beresp.http.X-VC-Req-URL = bereq.url;set beresp.http.X-VC-Req-URL-Base = regsub(bereq.url, "\?.*$", "");if (bereq.http.x-range ~ "bytes=" && beresp.status == 206) {set beresp.ttl = 10m;set beresp.http.CR = beresp.http.content-range;}if (beresp.http.Surrogate-Control) {set beresp.ttl = std.duration(regsub(beresp.http.Surrogate-Control,"^.*max-age=(\d+).*$","\1"),  beresp.ttl);set beresp.grace = std.duration(regsub(beresp.http.Surrogate-Control,"^.*max-age=\d+\+(\d+).*$","\1"),beresp.grace);}if (beresp.http.Vary ~ "User-Agent") {set beresp.http.Vary = regsub(beresp.http.Vary, ",? *User-Agent *", "");set beresp.http.Vary = regsub(beresp.http.Vary, "^, *", "");if (beresp.http.Vary == "") {unset beresp.http.Vary;}}# Varnish determined the object is not cacheableif (beresp.http.Authorization ||beresp.http.Authenticate ||beresp.http.WWW-Authenticate ||beresp.http.X-Requested-With == "(?i)XMLHttpRequest") {set beresp.http.X-VC-Cacheable = "NO: Authenticate ";set beresp.uncacheable = true;set beresp.http.magicmarker = 1;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 0;set beresp.ttl = 0s;}if (beresp.http.Pragma ~ "(?i)no-cache" ||(!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "(?i)no-cache|no-store|private")) {set beresp.http.Smug-Cacheable = "No";set beresp.http.magicmarker = "1";}if (beresp.http.Set-Cookie && beresp.http.Set-Cookie !~ "(?i)(wp-postpass_|wordpress_logged_in_|comment_author|PHPSESSID)") {set beresp.http.X-VC-Cacheable = "NO: !obj.Set-Cookie";set beresp.ttl = 0s;set beresp.http.Smug-Cacheable = "No";set beresp.http.magicmarker = "1";set beresp.uncacheable = true;}# Pause ESI request and remove Surrogate-Control headerif (beresp.http.Surrogate-Control ~ "ESI/1.0") {unset beresp.http.Surrogate-Control;set beresp.do_gunzip = true;set beresp.do_esi = true;}if (beresp.http.Content-Type ~ "text") {set beresp.do_esi = true;}if (beresp.http.Content-Type ~ "text") {set beresp.do_gzip = true;}# cache only successfully responses and 404s that are not marked as privateif (beresp.status != 200 && beresp.status != 404 && beresp.http.Cache-Control ~ "private") {set beresp.http.X-VC-Cacheable = "NO: Private Use";set beresp.uncacheable = true;set beresp.http.magicmarker = 1;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 0;set beresp.ttl = 0s;}if (beresp.status == 301 || beresp.status == 302) {set beresp.http.X-VC-Cacheable = "YES: but for 10s - Status : " + beresp.status;set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");unset beresp.http.Server;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 10;}if (beresp.status == 403 || beresp.status == 404) {set beresp.http.X-VC-Cacheable = "YES: but for 30s - Status : " + beresp.status;set beresp.grace = 15s;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 15;}if (beresp.status >= 500 && beresp.status < 600 && bereq.retries < 5) {if (bereq.method != "POST") {set beresp.http.X-VC-Cacheable = "NO: Status : " + beresp.status;set beresp.ttl = 0s;set beresp.grace = 15s;# return (abandon);}}if (beresp.status >= 200 && beresp.status < 300 && bereq.method ~ "^(GET|HEAD)$") {if (bereq.url ~ "^[^?]*\.(?i)(bmp|css|csv|doc|docx|eot|gif|ico|jpeg|jpg|js|less|pdf|png|ppt|pptx|rtf|svg|svgz|swf|ttf|txt|webp|woff|woff2|xls|xlsx|xml)(\?.*)?$") {unset beresp.http.Set-Cookie;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 24*60*60*7;}if (beresp.http.Content-Type ~ "(?i)(html|xml)") {set beresp.do_gzip = true;set beresp.do_esi = true;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 60*60;} elsif (beresp.http.Content-Type ~ "(?i)(css|javascript)" ||beresp.http.Content-Type ~ "(?i)application/(x-)?javascript" ||beresp.http.Content-Type ~ "(?i)application/(x-)?font-ttf" ||beresp.http.Content-Type ~ "(?i)application/(x-)?font-opentype" ||beresp.http.Content-Type ~ "(?i)application/font-woff" ||beresp.http.Content-Type ~ "(?i)application/vnd\.ms-fontobject" ||beresp.http.Content-Type ~ "(?i)image/svg\+xml") {set beresp.do_gzip = true;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 24*60*60*7;}# Large static files are delivered directly to the end-user without# waiting for Varnish to fully read the file first.# Varnish 4 fully supports Streaming, so use streaming here to avoid locking.if (beresp.http.Content-Type ~ "(?i)(octet-stream|audio|video)" ||bereq.url ~ "^[^?]*\.(?i)(avi|flac|flv|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|wav|webm)(\?.*)?$") {unset beresp.http.Set-Cookie;# the backend doesn't send a Content-Length header, so only enable it for big objectsset beresp.do_gzip = false; # Don't try to compress it for storage# Stream large objects, <= 128 MiBif (std.integer(beresp.http.Content-Length,0) <= 134217728) {set beresp.do_stream = true;  # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 60*60;# do not cache files > 128 MiB} elsif (std.integer(beresp.http.Content-Length,0) > 134217728) {set beresp.http.X-VC-Cacheable = "NO:Large static files";set beresp.uncacheable = true;set beresp.http.magicmarker = 1;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 0;set beresp.ttl = 0s;}}}# Don't cache object as instructed by header bereq.X-VC-Cacheableif (bereq.http.X-VC-Cacheable ~ "^NO") {set beresp.http.X-VC-Cacheable = bereq.http.X-VC-Cacheable;set beresp.uncacheable = true;# overwrite ttl with X-VC-TTLset beresp.http.X-VC-TTL = 0;set beresp.ttl = 0s;}# validate if we need to cache it and prevent from setting cookieif (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {unset beresp.http.set-cookie;}if (beresp.http.X-VC-Enabled ~ "true") {if (!beresp.http.X-VC-Cacheable) {set beresp.http.X-VC-Cacheable = "YES: Is cacheable, ttl: " + std.duration(beresp.http.X-VC-TTL + "s", 0s);}} elseif (beresp.http.X-VC-Enabled ~ "false") {if (!beresp.http.X-VC-Cacheable) {set beresp.http.X-VC-Cacheable = "NO:Disabled";}set beresp.http.X-VC-TTL = 0;}# All tests passed, therefore item is cacheable# set beresp.http.X-VC-Cacheable = "YES: Is cacheable, ttl: " + std.duration(beresp.http.X-VC-TTL + "s", 0s);# overwrite ttl with X-VC-TTLif (beresp.http.X-VC-TTL) {set beresp.ttl = std.duration(beresp.http.X-VC-TTL + "s", 0s);}# if (!beresp.http.cache-control) {#     set beresp.ttl = 0s;#     set beresp.uncacheable = true;# }return (deliver);
}sub vcl_deliver {set resp.http.X-Cache-Age = resp.http.Age;set resp.http.X-Cache-Alive = regsub(obj.ttl, "^(\d+).[0-9]+", "\1");unset resp.http.Age;if (resp.http.CR) {set resp.http.Content-Range = resp.http.CR;unset resp.http.CR;}# From  (resp.http.magicmarker) {/* Remove the magic marker */unset resp.http.magicmarker;/* By definition we have a fresh object */set resp.http.Pragma = "no-cache";set resp.http.Expires = "-1";set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";}unset resp.http.X-VC-Req-Host;unset resp.http.X-VC-Req-URL;unset resp.http.X-VC-Req-URL-Base;if (obj.hits > 0) {set resp.http.X-VC-Cache = "HIT";} else {set resp.http.X-VC-Cache = "MISS";}if (req.http.X-VC-Debug ~ "true" || resp.http.X-VC-Debug ~ "true") {set resp.http.X-VC-Hash = req.http.hash;if (req.http.X-VC-DebugMessage) {set resp.http.X-VC-DebugMessage = req.http.X-VC-DebugMessage;}} else {unset resp.http.X-VC-Enabled;unset resp.http.X-VC-Cache;unset resp.http.X-VC-Debug;unset resp.http.X-VC-DebugMessage;unset resp.http.X-VC-Cacheable;unset resp.http.X-VC-Purge-Key-Auth;unset resp.http.X-VC-TTL;}# Change some headersunset resp.http.X-Powered-By;unset resp.http.Server;unset resp.http.X-Varnish;unset resp.http.Via;unset resp.http.Link;unset resp.http.X-Frame-Options;unset resp.http.X-Content-Type-Options;unset resp.http.X-Xss-Protection;unset resp.http.Referer-Policy;unset resp.http.X-Permitted-cross-domain-policies;unset resp.http.X-Drupal-Cache;unset resp.http.X-Page-Speed;unset resp.http.X-AspNet-Version;unset resp.http.X-Generator;unset resp.http.X-Via;if (obj.hits > 0) {set resp.http.X-Cache-Remote = "HIT";set resp.http.X-Cache-Hits = obj.hits;} else {set resp.http.X-Cache-Remote = "MISS";}set resp.http.X-Cache-Lookup = "Lookup From Disktank";# HTTP headers for all sitesset resp.http.X-Are-Dinosaurs-Awesome = "HELL YES";set resp.http.X-Hack = "don't hack me bro";return (deliver);
}sub vcl_backend_fetch {if (bereq.method == "GET") {unset bereq.body;}std.collect(bereq.http.x-forwarded-for);if (bereq.http.x-range) {set bereq.http.Range = bereq.http.x-range;}if (bereq.http.x-forwarded-for) {set bereq.http.x-forwarded-for = regsub(bereq.http.x-forwarded-for + ", " + client.ip, "\s*,.*$", "");} else {set bereq.http.x-forwarded-for = client.ip;}return (fetch);
}sub vcl_purge {# Only handle actual PURGE HTTP methods, everything else is discardedif (req.method != "PURGE") {# restart requestset req.http.X-Purge = "Yes";return (restart);}
}sub vcl_hit {if (obj.ttl >= 0s) {return (deliver);}set req.http.grace = "unlimited (unhealthy server)";return (deliver);
}

实战WordPress Varnish反向代理

以本站作为反代案例,源站在欧洲某国,国内访问则通过CN2GIA的VPS作为边缘节点,现在就在这台VPS上安装AMH做反代,在完成以上所有配置之后,开始以下配置

一、首先切换到LNGX反代环境

二、添加反代网站

缓存是用varnish做的,因此后端监听地址这里务必填http://127.0.0.1:6081,这个是varnish的监听地址。所以记得要取消LNGX自带的缓存(Cache)。

三、配置varnish

在上面的后端地址已经指定了用varnish做缓存,所以真正的后端地址的配置就需要在varnish上做配置了,找到varnish的配置,在backend部分指定源站IP和端口:

...# Setup the backend
backend backend1 {.host = "1.1.1.1"; # `改为源站IP地址`.port = "80"; # `改为源站端口`.first_byte_timeout = 300s;.connect_timeout = 5s;.between_bytes_timeout = 5s;
}backend backend2 {.host = "1.1.1.1"; # `改为源站IP地址`.port = "80"; # `改为源站端口`.first_byte_timeout = 300s;.connect_timeout = 5s;.between_bytes_timeout = 5s;
}...sub vcl_recv {...if (req.http.host ~ "(?i)(^((.*).)?evlit)") {set req.backend_hint = backend1;} elseif (req.http.host ~ "(?i)(^((.*).)?other.domain)") {set req.backend_hint = backend2;} else {return (synth(403, "Hostname not found."));}...
}

 以上配置中的backend1是本例的配置关键,backend2则是配置其他域名的。

完成以上配置之后,配置好本机hosts之后,就可以访问了。

但WordPress访问仍然是有问题的,https和http会反复横跳。继续往下看⬇️

四、WordPress配置

打开wp-config.php,在第二行添加配置:

if ((isset($_ENV["HTTPS"]) && ("on" == $_ENV["HTTPS"]))|| (isset($_SERVER["HTTP_X_FORWARDED_SSL"]) && (strpos($_SERVER["HTTP_X_FORWARDED_SSL"], "1") !== false))|| (isset($_SERVER["HTTP_X_FORWARDED_SSL"]) && (strpos($_SERVER["HTTP_X_FORWARDED_SSL"], "on") !== false))|| (isset($_SERVER["HTTP_CF_VISITOR"]) && (strpos($_SERVER["HTTP_CF_VISITOR"], "https") !== false))|| (isset($_SERVER["HTTP_CLOUDFRONT_FORWARDED_PROTO"]) && (strpos($_SERVER["HTTP_CLOUDFRONT_FORWARDED_PROTO"], "https") !== false))|| (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && (strpos($_SERVER["HTTP_X_FORWARDED_PROTO"], "https") !== false))|| (isset($_SERVER["HTTP_X_PROTO"]) && (strpos($_SERVER["HTTP_X_PROTO"], "SSL") !== false))
) {$_SERVER["HTTPS"] = "on";
}

五、WordPress插件管理缓存

前面提到缓存,如果缓存不能被管理,那么这个缓存就没什么意义。需要到WordPress后台插件搜索varnish,然后找到 Purge Varnish Cache 安装就好。

安装后激活,然后需要进行配置

配置主要有两个地方,Varnish Control Terminal是一个varnish的API管理接口,varnish默认监听的是本地回环地址127.0.0.1:6082,但在本例中需要改为公网监听地址。

首先在AMH的varnish的启动参数里面,将127.0.0.1地址改为0.0.0.0,这样就可以在公网访问这个高位端口了

Varnish Control Key则是作为API管理接口的鉴权密钥,可以在linux终端里查看到varnish的启动命令行里找到

这串4f043f13c9891ae61e6f2d2eb就是密钥了,将它填到wordpress插件里就好了。

最后

AMH默认其实也有缓存的,我没实际测试,主要是我一直以来习惯使用varnish做边缘节点的缓存工具,而且搭配wordpress插件,也可以很方便地刷新缓存,其他的配置,比如发帖自动刷新varnish的缓存,可以直接保持默认就好。

当然,现在你也可以测试一下了。😊

 原创文章,转载请著名出处,同时文章同步发表在:

AMH-7.1 面板:实战LNGX+Varnish反向代理,提升Wordpress网站打开速度 - EVLIT

本文标签: AMH