转自:https://www.kancloud.cn/zouhongzhao/magento2-in-action/647798
注意:这篇文章讲的是varnish和ssl同时存在的情况,比较复杂。如果你只需要配置ssl,不需要varnish的话,请参考
https://bbs.mallol.cn/thread-622.htm
配置Varnish
注意:Varnish
默认只支持http(80)
端口,不支持https(443)
,若要支持https(443)
,必须配置Nginx反向代理才能生效
当然你可以不用Varnish
,只配置SSL
也可以。
以下操作在/var/www/magento2-live
项目下执行。
请自行更改你的项目路径和URL。
没有SSL证书的去 https://freessl.cn/ 免费申请
M2后台启用Varnish缓存
从你的Magento管理仪表板上点击 STORES button (leftside)
> Configuration
> ADVANCED
> System
> Full Page Cache
取消选择使用系统值并从缓存应用程序列表中选择Varnish Cache (Recommended)
,保存配置,单击Varnish Configuration
链接并单击Export VCL for Varnish 4
按钮。
我们下载保存这个varnish.vcl
范例文件,备用。
最后,使用以下命令刷新Magento缓存:
cd /var/www/magento2-live
php bin/magento cache:flush
完成后,你可以继续配置Varnish。
服务器安装并配置Varnish
确保安装在你的服务器上的所有软件包都是最新的
sudo apt-get update && sudo apt-get upgrade
Varnish在官方Ubuntu 16.04版本库中提供,所以我们可以使用apt-get命令轻松安装它:
sudo apt-get install varnish
一旦安装完成,我们将配置Varnish在端口80上侦听,并使用将在端口8080上监听的Nginx Web服务器作为后端。
输入以下命令编辑Varnish缓存文件并创建一个新的配置文件/etc/systemd/system/varnish.service.d/
:
sudo mkdir -p /etc/systemd/system/varnish.service.d
sudo systemctl edit varnish.service
添加/追加下列配置选项:
将Varnish端口6082更改为HTTP端口80。
[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T localhost:6082 -p thread_pools=4 -p thread_pool_max=1500 -p connect_timeout=300 -p listen_depth=512 -p http_resp_hdr_len=65536 -p http_resp_size=98304 -p workspace_backend=98304 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,1024m
并重新加载systemd单元
sudo systemctl daemon-reload
接下来,编辑默认的Varnish vcl文件
sudo vim /etc/varnish/default.vcl
把刚才下载的varnish.vcl
范例文件代码复制进去。
配置文件内容如下:
vcl 4.0;
import std;
# The minimal Varnish version is 4.0
# For SSL offloading, pass the following header in your proxy server or load balancer: 'X-Forwarded-Proto: https'
backend default {
.host = "127.0.0.1";
.port = "8080";
.first_byte_timeout = 600s;
}
acl purge {
"127.0.0.1";
}
sub vcl_recv {
if (req.url ~ "(jpg|jpeg|png|gif|tiff|bmp)$") {
return (pipe);
}
if (req.method == "PURGE") {
if (client.ip !~ purge) {
return (synth(405, "Method not allowed"));
}
if (!req.http.X-Magento-Tags-Pattern) {
return (synth(400, "X-Magento-Tags-Pattern header required"));
}
ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
return (synth(200, "Purged"));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Bypass shopping cart, checkout and search requests
if (req.url ~ "/checkout" || req.url ~ "/catalogsearch") {
return (pass);
}
# normalize url in case of leading HTTP scheme and domain
set req.url = regsub(req.url, "^http[s]?://", "");
# collect all cookies
std.collect(req.http.Cookie);
# Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") {
# No point in compressing these
unset 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 {
# unkown algorithm
unset req.http.Accept-Encoding;
}
}
# Remove Google gclid parameters to minimize the cache objects
set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA"
set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar"
set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz"
# static files are always cacheable. remove SSL flag and cookie
if (req.url ~ "^/(pub/)?(media|static)/.*\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)$") {
unset req.http.Https;
unset req.http.X-Forwarded-Proto;
unset req.http.Cookie;
}
return (hash);
}
sub vcl_hash {
if (req.http.cookie ~ "X-Magento-Vary=") {
hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
}
# For multi site configurations to not cache each other's content
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# To make sure http users don't see ssl warning
if (req.http.X-Forwarded-Proto) {
hash_data(req.http.X-Forwarded-Proto);
}
}
sub vcl_backend_response {
if (beresp.http.content-type ~ "text") {
set beresp.do_esi = true;
}
if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
# cache only successfully responses and 404s
if (beresp.status != 200 && beresp.status != 404) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.http.Cache-Control ~ "private") {
set beresp.uncacheable = true;
set beresp.ttl = 86400s;
return (deliver);
}
if (beresp.http.X-Magento-Debug) {
set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;
}
# validate if we need to cache it and prevent from setting cookie
# images, css and js are cacheable by default so we have to remove cookie also
if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
unset beresp.http.set-cookie;
if (bereq.url !~ "\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)(\?|$)") {
set beresp.http.Pragma = "no-cache";
set beresp.http.Expires = "-1";
set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
set beresp.grace = 1m;
}
}
# If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass
if (beresp.ttl <= 0s ||
beresp.http.Surrogate-control ~ "no-store" ||
(!beresp.http.Surrogate-Control && beresp.http.Vary == "*")) {
# Mark as Hit-For-Pass for the next 2 minutes
set beresp.ttl = 120s;
set beresp.uncacheable = true;
}
return (deliver);
}
sub vcl_deliver {
if (resp.http.X-Magento-Debug) {
if (resp.http.x-varnish ~ " ") {
set resp.http.X-Magento-Cache-Debug = "HIT";
} else {
set resp.http.X-Magento-Cache-Debug = "MISS";
}
} else {
unset resp.http.Age;
}
unset resp.http.X-Magento-Debug;
unset resp.http.X-Magento-Tags;
unset resp.http.X-Powered-By;
unset resp.http.Server;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
}
保存更改并重新启动Varnish以使更改生效
sudo systemctl restart varnish
配置Nginx SSL
将Web服务器配置为侦听除默认端口80以外的端口(例如:8080),因为Varnish直接响应传入的HTTP请求,而不是Web服务器。为此,在'server'块中添加'listen'指令,如下所示:
sudo nano /etc/nginx/sites-enabled/magento2-live
将侦听端口更改为8080,并启用Nginx SSL HTTP2,
打开Nginx配置文件并将其更改如下:
upstream fastcgi_backend {
server unix:/run/php/php7.0-fpm.sock;
}
server {
server_name yourdomain.com www.yourdomain.com;
listen 8080;
set $MAGE_ROOT /var/www/magento2-live;
set $MAGE_MODE production; # or developer
access_log /var/log/nginx/magento2-access.log;
error_log /var/log/nginx/magento2-error.log;
include /var/www/magento2-live/nginx.conf.sample;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/nginx/ssl/magento2/ssl-cert-snakeoil.pem; # change with your SSL cert
ssl_certificate_key /etc/nginx/ssl/magento2/ssl-cert-snakeoil.key; # change with your SSL key
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;
keepalive_timeout 300s;
location / {
proxy_pass http://127.0.0.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Ssl-Offloaded "1";
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
#proxy_hide_header X-Varnish;
#proxy_hide_header Via;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
如果您还没有SSL证书,则可以去购买可信SSL证书。
在/etc/nginx/sites-enabled/default
文件中也进行相同的更改(把listen 80
改成listen 8080
)。
测试Nginx配置
通过执行以下命令保存更改并测试Nginx配置
sudo nginx -t
输出应该看起来像这样
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新启动Varnish和Nginx
最后,重新启动Nginx以使更改生效
sudo systemctl restart nginx
sudo systemctl restart varnish
验证
我假设你已经遵循了上述所有步骤(安装和配置)。现在让我们来检查Varnish缓存服务器是否考虑了HTTP响应。
检查Varnish状态
systemctl status varnish
检查Varnish是否正在侦听端口80,运行以下命令
netstat -tulpn | grep varnishd
验证HTTP响应头,您可以简单地使用CLI:
注意:必须在开发者模式下才能看到HTTP响应标题
https://devdocs.magento.com/guides/v2.3/config-guide/varnish/config-varnish-final.html
curl -I -v --location-trusted 'http://www.yourdomain.com/'
应该会看到这些重要的标题
X-Magento-Cache-Control: max-age=86400, public, s-maxage=86400
Age: 0
X-Magento-Cache-Debug: MISS
将基础URL更改为https并刷新缓存
php bin/magento setup:store-config:set --use-secure=1 --use-secure-admin=1 --base-url-secure="https://www.yourdomain.com/"
php bin/magento cache:flush
要对Magento Admin和店面都使用安全套接字层(SSL)(也称为HTTPS),你必须设置以下所有参数:
--use-secure:设置为1
--base-url-secure:设置为安全的URL(即以https://开头)
--use-secure-admin:设置为1
如果现在一切正常,你应该可以通过https://www.yourdomain.com/adminlogin
登录到你的Magento后端。
现在,一旦你在浏览器中访问你的网站,它应该通过Varnish来提供服务。
就是这样。
你已经用Varnish和Nginx成功配置了Magento。
你的Magento网站现在应该会明显更快。
测试
如果有问题的话,
先清下m2的varnish缓存:
php bin/magento cache:flush full_page
或者后台清缓存
clickSYSTEM
>Tools
>Cache Management
, then clickFlush Magento Cache
.
清除varnish缓存:
sudo systemctl restart varnish
再更新下系统:
php bin/magento maintenance:enable && git pull origin master
rm -rf var/di/* && rm -rf var/generation/* && rm -rf var/cache/* && rm -rf var/page_cache/* && rm -rf var/view_preprocessed/* && rm -rf pub/static/* && rm -rf generated/* && mkdir var/di
php bin/magento setup:upgrade && php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f && php bin/magento indexer:reindex && php bin/magento maintenance:disable && php bin/magento cache:clean && php bin/magento cache:flush
总结
这一章比较绕,其实大致流程如下:
1,访客打开网站
如果是通过SSL(https
,一般是443端口)访问,请求会转到Nginx。Nginx再把请求转给Varnish。
如果是通过非SSL(http
,一般是80端口)访问,请求会转到Varnish,被重定向到SSL URL
。
2,Varnish接收
Varnish收到请求后,会检查请求是否有缓存,
有缓存的话 会将缓存的数据传递给Nginx。
没有缓存的话 就请求Magento2获取数据,再缓存后 返回给Nginx。
3,数据传递给Nginx
一旦Varnish有回应,它将被传递回Nginx,以便它可以传递给访问者。
因为Varnish不直接支持SSL。
这就是Nginx需要站在中间的原因,所以它可以通过SSL将响应传递给访问者。
4,向访问者提供数据
一旦Nginx有响应数据,它通过SSL安全地将数据传递给访问者。因为Varnish不能直接用于安全的SSL响应。
参考文章
关于其他系统(Centos/Red Hat/Debian)下的Varnish配置,可以参考下面这篇文章:
https://docs.varnish-software.com/tutorials/configuring-systemd-services/
相关问题
1,重启nginx警告*hash_max_size,*hash_bucket_size
Starting nginx: nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
解决办法:
编辑vim /etc/nginx/nginx.conf
,在http里面增加
proxy_headers_hash_max_size 51200;
proxy_headers_hash_bucket_size 6400;
2,不管怎么操作,总是出现503 backend fetch failed
这是magento2的一个bug,还未修复。
2.2.x版本有问题。老版本有些是好的。
https://github.com/magento/magento2/issues/11692
如果是用的直接从后台导出的Varnish配置文件,可能会有问题。
直接用我的varnish.vcl范例文件代码试试。
3,Cannot open socket: :80: Address already in use
先查看是哪个进程占用的80端口,一般是nginx
sudo netstat -nlpt
找到进程号后,杀死这个进程
sudo kill 进程号 -9
如果是nginx占用80端口的话,你还需要改nginx虚拟主机配置文件。/etc/nginx/sites-enabled/
下面的所有主机配置文件。
把listen 80
都改成listen 8080
。
最后再重启nginx
ssl下的多网店vhost配置
以store view
多网店多域名为例:
upstream fastcgi_backend {
server unix:/run/php/php7.0-fpm.sock;
}
map $http_host $MAGE_RUN_CODE {
magento2demo.texiaoyao.cn default;
magento2demo-zh.texiaoyao.cn cn;
}
server {
listen 8080;
server_name magento2demo.texiaoyao.cn;
set $MAGE_ROOT /var/www/magento2-live;
set $MAGE_MODE production;
set $MAGE_RUN_TYPE store;
include /var/www/magento2-live/nginx.conf.sample;
error_log /var/log/magento2-live/nginx/error.log;
}
server {
listen 8080;
server_name magento2demo-zh.texiaoyao.cn;
set $MAGE_ROOT /var/www/magento2-live;
set $MAGE_MODE production;
set $MAGE_RUN_TYPE store;
include /var/www/magento2-live/nginx.conf.sample;
error_log /var/log/magento2-live/nginx/error.log;
}
server {
listen 443 ssl http2;
server_name magento2demo.texiaoyao.cn magento2demo-zh.texiaoyao.cn;
ssl_certificate /usr/local/nginx/conf/ssl/magento2demo.texiaoyao.cn.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/magento2demo.texiaoyao.cn.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;
keepalive_timeout 300s;
location / {
proxy_pass http://127.0.0.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Ssl-Offloaded "1";
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
#proxy_hide_header X-Varnish;
#proxy_hide_header Via;
proxy_connect_timeout 1800s;
proxy_read_timeout 1800s;
proxy_send_timeout 1800s;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
强制HTTPS
1) 只有SSL,没安装Varnish的情况下
Nginx配置文件
server
{
listen 80;
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
index index.php index.html index.htm default.php default.htm default.html;
set $MAGE_ROOT /var/www/magento2-live/;
set $MAGE_MODE production;
set $MAGE_RUN_TYPE store;
include /var/www/magento2-live/nginx.conf.sample;
#SSL-START
#error_page 404/404.html;
#HTTP_TO_HTTPS_START
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
#HTTP_TO_HTTPS_END
ssl_certificate /etc/nginx/ssl/magento2/ssl-cert-snakeoil.pem; #change with your SSL cert
ssl_certificate_key /etc/nginx/ssl/magento2/ssl-cert-snakeoil.key; # change with your SSL key
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
#SSL-END
}
2) SSL和Varnish同时存在的情况下
需要改下 vim /etc/varnish/default.vcl
,添加几行代码
sub vcl_recv {
if (client.ip != "127.0.0.1" && req.http.host ~ "^(?i)www.domain.com" && req.http.X-Forwarded-Proto !~ "(?i)https") {
return (synth(750, ""));
}
....
}
sub vcl_synth {
if (resp.status == 750) {
set resp.status = 301;
set resp.http.Location = "https://www.domain.com" + req.url;
return(deliver);
}
}
还需要修改下Nginx配置文件
server {
listen 8080;
listen [::]:8080;
server_name yourdomain.com;
return 301 https://www.yourdomain.com$request_uri;
}
server {
server_name www.yourdomain.com;
listen 8080;
listen [::]:8080;
#HTTP_TO_HTTPS_START
#HTTP_TO_HTTPS_END
set $MAGE_ROOT /var/www/www.yourdomain.com;
set $MAGE_MODE production; # or developer
#access_log /var/log/domains/www.yourdomain.com/nginx/access.log;
error_log /var/log/domains/www.yourdomain.com/nginx/error.log;
include /var/www/www.yourdomain.com/nginx.conf.sample;
}
然后M2的web/unsecure/base_url
也要改成https
,跟web/secure/base_url
一样