以前做網站的時候遇到了網站的通路量很大,而導緻後端處理程式響應逾時而導緻的一些問題。當時采用的架構是nginx+php-fastcgi,同僚想到了用nginx-proxycache來做頁面緩存,效果也還行。下面我想介紹一下varnish的使用技巧
準備
varnish嚴格來說是可以當作一個代理伺服器的軟體,直接将http請求轉發到php-cgi,然後交給php處理,varnish會擷取經過php處理後的資料,最後傳回給浏覽器。如圖
但是,現在php-fastcgi已經被逐漸淘汰了,也就是說我們一般情況下不會使用php-fastcgi,那麼我們不能直接将varnish與php組合,因為php-fpm的互動方式為socket,而不再是監聽本機的9000端口
是以我們必須找一個的媒介,連接配接varnish和php-fpm,nginx可以扮演這個媒介,如下圖:
那麼問題來了,根據研究發現,varnish處理http請求不如nginx那麼高效。是以如果我們讓nginx做前鋒,這樣就更完美了。那我們需要怎麼才能達到這個目的呢,下面我們來整理一下流程
下面就來實作一下圖三的架構吧。
事先需要準備nginx,varnish,php-fpm,php這些軟體,os是ubuntu,所有軟體都可以用apt-get
install來安裝,不了解包名全稱的話可以先apt-get update,更新一下源,然後再用apt-cache search
xxx來查找軟體包名
安裝完varnish後,可以使用service varnish回車,檢視可操作選項* usage: /etc/init.d/varnish
{start|stop|restart|reload|force-reload|configtest},一般安裝完畢後,系統會自動啟動varnish的,nginx也是一樣,便不贅述了
配置
安裝完所需的軟體後,下面需要配置這些軟體,來實作這個架構
nginx部分
vi /etc/nginx/nginx.conf
http {
## proxy global setting
proxy_connect_timeout 5;
proxy_read_timeout 60;
proxy_send_timeout 5;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
##end
## cache proxy pass
upstream cache {
server 127.0.0.1:6081;
}
## php proxy pass
upstream php {
server 127.0.0.1:8080;
# basic settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
#depend on nginx-extras 需要安裝nginx-extras才能定義server
more_set_headers 'server: bird-shark';
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# ssl settings
ssl_protocols tlsv1 tlsv1.1 tlsv1.2; # dropping sslv3, ref: poodle
ssl_prefer_server_ciphers on;
# logging settings
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# gzip settings
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# virtual host configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
varnish部分
vi /etc/varnish/default.vcl
server {
listen 80 default_server;
listen [::]:80 default_server;
index index.html index.htm index.php;
server_name localhost;
location ~ .*\.(gif|jpg|png|css|js|flv|ico|swf|html)$ {
proxy_set_header host $host;
proxy_set_header x-real-ip $remote_addr;
proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
proxy_pass http://cache;
# pass the php scripts to fastcgi server listening on 127.0.0.1:9000
#
location / {
proxy_pass http://php;
proxy_pass_header server;
}
listen 8080;
root /var/www/html;
index index.html index.htm index.php;
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
try_files $uri $uri/ =404;
location ~ ^(.+\.php)(.*)$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_intercept_errors on;
fastcgi_buffers 8 128k;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
include fastcgi_params;
測試&分析
1. 在不使用緩存子產品的情況下
vi /etc/nginx/sites-available/default
#location ~ .*\.(gif|jpg|png|css|js|flv|ico|swf|html)$ {
# proxy_set_header host $host;
# proxy_set_header x-real-ip $remote_addr;
# proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
# proxy_pass http://cache;
#}
先用chrome浏覽器通路檢視請求頭
我們再使用curl,在伺服器上執行以下指令
curl -k -v 'http://192.168.99.1/public/home/images/t_navigation_logo.png' -h 'pragma: no-cache' -h 'accept-encoding: gzip, deflate, sdch' -h 'accept-language: zh,en;q=0.8,zh-cn;q=0.6' -h 'upgrade-insecure-requests: 1' -h 'user-agent: mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/52.0.2743.116 safari/537.36' -h 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -h 'connection: keep-alive' --compressed
發現有輸出内容。
然後,反選disable cache
然後在伺服器上執行以下指令
curl -k -v 'http://192.168.99.1/public/home/images/t_navigation_logo.png' -h 'if-none-match: "57c6b733-1962"' -h 'accept-encoding: gzip, deflate, sdch' -h 'accept-language: zh,en;q=0.8,zh-cn;q=0.6' -h 'upgrade-insecure-requests: 1' -h 'user-agent: mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/52.0.2743.116 safari/537.36' -h 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -h 'connection: keep-alive' -h 'if-modified-since: wed, 31 aug 2016 10:53:39 gmt' --compressed
發現隻傳回了頭部資訊,然而沒有内容傳回
然後我們比較兩個指令 發現差別就在-h 'pragma: no-cache'和 -h 'if-modified-since: wed,
31 aug 2016 10:53:39 gmt' -h 'if-none-match: "57c6b733-1962"'
57c6b733-1962這串字元對應的是伺服器響應給浏覽器的etag部分的内容,然後我們修改一下部分的内容
curl -k -v 'http://192.168.99.1/public/home/images/t_navigation_logo.png' -h 'if-none-match: "57c6b733-1234"' -h 'accept-encoding: gzip, deflate, sdch' -h 'accept-language: zh,en;q=0.8,zh-cn;q=0.6' -h 'upgrade-insecure-requests: 1' -h 'user-agent: mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/52.0.2743.116 safari/537.36' -h 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -h 'connection: keep-alive' -h 'if-modified-since: wed, 31 aug 2016 10:53:39 gmt' --compressed
在伺服器端執行一下。發現有内容傳回,是以這個etag相當于token,它不是由nginx随便生成的,且跟請求連結應是一一對應的,用來辨別緩存的,當伺服器傳回的狀态為304的時候,這時候我們浏覽器會直接找到本地的緩存資料
2. 在使用緩存子產品的情況下
location ~ .*\.(gif|jpg|png|css|js|flv|ico|swf|html)$ {
proxy_set_header host $host;
proxy_set_header x-real-ip $remote_addr;
proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
proxy_pass http://cache;
用浏覽器檢視響應頭
發現x-cache:miss from 192.168.99.1.這表示緩存未命中,然後我們重新整理x-cache:hit from 192.168.99.1,這時候發現已經命中了。
對于已經命中的資源檔案,我們如果将其删除會出現什麼效果呢,答案是,其依然可以通路,除非重新開機或者将緩存清除
但是對purge顯然是不對外公開的,以下是伺服器端用curl清除varnish緩存的指令
curl -v -k -x purge http://localhost/public/home/css/t_navigation.css
結語
varnish是一款記憶體類型的緩存軟體,而非nginx擴充proxy_cache那種實體緩存類型的軟體,存取速度比較快,但是也有弊端,重新開機後所有緩存得重寫。不管怎麼說,什麼架子都适用的場景,要想滿足業務需求還是得搗鼓透徹,而我也隻是将我想到的給實作出來,畢竟資源和精力都是有限的,也就随便玩玩,諸位看客看看就好,别太認真,知道怎麼回事兒就行。
作者:birdshark
來源:51cto