天天看點

Nginx代理varnish的那些姿勢

以前做網站的時候遇到了網站的通路量很大,而導緻後端處理程式響應逾時而導緻的一些問題。當時采用的架構是nginx+php-fastcgi,同僚想到了用nginx-proxycache來做頁面緩存,效果也還行。下面我想介紹一下varnish的使用技巧

準備

varnish嚴格來說是可以當作一個代理伺服器的軟體,直接将http請求轉發到php-cgi,然後交給php處理,varnish會擷取經過php處理後的資料,最後傳回給浏覽器。如圖

Nginx代理varnish的那些姿勢

但是,現在php-fastcgi已經被逐漸淘汰了,也就是說我們一般情況下不會使用php-fastcgi,那麼我們不能直接将varnish與php組合,因為php-fpm的互動方式為socket,而不再是監聽本機的9000端口

是以我們必須找一個的媒介,連接配接varnish和php-fpm,nginx可以扮演這個媒介,如下圖:

Nginx代理varnish的那些姿勢

那麼問題來了,根據研究發現,varnish處理http請求不如nginx那麼高效。是以如果我們讓nginx做前鋒,這樣就更完美了。那我們需要怎麼才能達到這個目的呢,下面我們來整理一下流程

Nginx代理varnish的那些姿勢

下面就來實作一下圖三的架構吧。

事先需要準備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浏覽器通路檢視請求頭

Nginx代理varnish的那些姿勢

我們再使用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

Nginx代理varnish的那些姿勢

然後在伺服器上執行以下指令

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