Web Cache Server 介於 Client 跟 Web Server 之間,當使用者存取一個網址,Web Cache Server 會先向後端的 Web Server 取得資料,如果下一個 request 又存取了相同的網址,這時候就可直接由 Web Cache Server 回傳給 Client,用以減少 Web Server 的 Loading。
其他常見的開源代理伺服器有 Squid,Varnish,Nginx,HAProxy,Apache Traffic Server(ATS),其中 HAProxy 沒有 Cache 的功能,Squid 是比較老牌的 proxy server,但遇到 session 數量太高時,容易失效,已經比較少用了,然後 Varnish 取代了 Squid 的地位。
Varnish 主要功能就是 reverse proxy cache server,由於是使用記憶體作為cache,適合用來處理小文件如 css,js 及小圖片的cache。
nginx 主要功能是靜態網頁服務,若是為了提供訪問最頻繁資源的cache,可以使用 nginx-cache 模組,適合cache少量頁面資源,如果 Cache 內容過多容易造成性能瓶頸與負載過大。
所以目前看起來,有兩個伺服器可以嘗試,一個是 ngnix + cache,這個可以用在少量 cache 資源,加上可以處理靜態網頁檔案,另一個是 Apache Traffic Server (ATS),這是比較專用的 cache server,如果要建置專業的 CDN,應該要選擇使用 ATS。
Apache Traffic Server(ATS或TS)是一個高性能的、模塊化的 HTTP 代理和cache服務器。Traffic Server 最初是 Inktomi 公司的商業產品,該公司在 2003 年被 Yahoo 收購,之後 Traffic Server 一直在 Yahoo 內部使用長達 4 年,直到 2009 年 8 月 Yahoo 向 Apache 軟件基金會(ASF)貢獻了源代碼,並於 2010 年 4 月成為了 ASF 的頂級項目(Top-Level Project)。Apache Traffic Server 現在是一個開源項目,開發語言為C++。
| 軟件名稱 | 性能 | 功能 | 過濾規則配置 | 
|---|---|---|---|
| Squid | 不能多核,disk cache有容量優勢,性能中等 | 多,支援ACL角色控制,也支援ICP cache 協定 | 支援外部規則文件讀取及熱加載,支援熱啟動 | 
| Varnish | 多核支援,memory cache,性能強 | 夠用,不支援集群,支援後端存活檢查 | 不支援外部文件讀取,需要轉譯,支援熱啟動 | 
| Nginx | 多核,支援代理插件,性能較強 | 多,通過plugin可以充當多種服務器 | 不支援外部文件讀取,需要轉譯,支援熱啟動 | 
| ATS | 多核,disk/memory cache,性能強 | 夠用,支援plugin開發,也支援ICP協議 | 支援外部規則文件讀取及熱加載,支援熱啟動,但缺乏文檔 | 
| HAProxy | 多核,無 cache,支援HTTP header語法操作,性能強 | 少,只專注HTTP頭部解析和轉發功能,支援ACL角色控制,支援後端存活檢查 | 支援外部規則文件讀取及熱加載,支援熱啟動,支援 sticky session 和長連接 | 
nginx for CentOS 7
安裝 nginx
yum -y install nginx
# 立即啟動
systemctl start nginx
# 查看目前運作狀態
systemctl status nginx
# 查看 nginx 服務目前的啟動設定
systemctl list-unit-files | grep nginx
# 若是 disabled,可以改成開機自動啟動
systemctl enable nginx調整 nginx 設定,先把 nginx service port 改為 6000
vi /etc/nginx/nginx.conf
listen       6000 default_server;
listen       [::]:6000 default_server;
systemctl restart nginx安裝及設定 PHP-FPM
yum -y install php php-fpm php-mysql
# 查詢 PHP-FPM 的狀態
systemctl list-unit-files | grep php-fpm
# 改成開機自動啟動
systemctl enable php-fpm
# 立即啟動
systemctl start php-fpm
# 查看目前運作狀態
systemctl status php-fpm修改 PHP-FPM 設定
chown -R nginx.nginx /var/lib/php/session
vi /etc/php-fpm.d/www.conf
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
; listen = 127.0.0.1:9000  改成
listen = /var/run/php-fpm/php-fpm.sock
systemctl restart php-fpm修改 ulimit open file的限制
# 查閱file open 限制
ulimit -a
vi /etc/security/limits.conf
# 增加 4行
* soft nofile 65535
* hard nofile 65535
root hard nofile 65535
root soft nofile 65535
# 設定 file open數量
ulimit -n 65535nginx proxy_cache
nginx 自 v0.7.48 開始支援了類似 Squid 的功能,他會把 url 當作 key,以 MD5 對 key 進行 hash,然後得到硬碟上對應的 hash 檔案目錄,然後將快取的內容存放到這個目錄中。目前沒有清除 cache 的功能,但可透過 ngxcachepurge 模組,清除指定 URL 的 cache。
建立 cache 目錄
mkdir -p /usr/share/nginx/cache
chown -R nginx.nginx /usr/share/nginx/cacheproxy_cache 相關的設定值
# 設定快取檔案的存放路徑 proxy_cache_path
proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];
# path  快取檔案的存放路徑
# levels=number  快取空間有兩層 hash 目錄
# keys_zone=zone_name:zone_size  zone_name是為這個快取空間命名,zone_size是記憶體快取的空間大小
# inactive=time  快取存活的時間
# max_size=size  硬碟快取空間
# example
proxy_cache_path /usr/share/nginx/cache levels=1:2 keys_zone=STATIC:50m inactive=1d max_size=20g;
# ---------------
# 設定要使用哪一個快取空間名稱 proxy_cache
proxy_cache zone_name;
# zone_name 就是剛剛在 proxy_cache_path 設定的 zone_name
# example
proxy_cache STATIC;
# ---------------
# proxy_cache_methods 設定快取哪些 HTTP method,預設為 GET/HEAD
proxy_cache_methods [GET HEAD POST]
# ---------------
# proxy_cache_min_uses 設定快取的最小使用次數,預設為 1
proxy_cache_min_uses 1;
# ---------------
# proxy_cache_valid 對不同的 reponse status code 的 URL 設定不同的快取時間
proxy_cache_valid reply_code time;
# example
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid 404 1m;
proxy_cache_valid any 1m;
# ---------------
# proxy_cache_key 設定快取的 key 值
proxy_cache_key "$host:$server_port$uri$is_args$args"
# ---------------
# 如果後端服務器經常發生503錯誤,服務不能保證可正確取得資料,為了避免訪問錯誤,可以在cache server上做調整。如果cache過期,但訪問後端服務器又不能返回正常的內容,則使用cache的內容。
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
如果要驗證是不是從 Cache 取得的內容,可以加上這個 header
add_header      Nginx-Cache     "$upstream_cache_status from cache";當我們用瀏覽器觀看 Header 時,如果沒有 hit,會看到這樣的 header
Nginx-Cache:MISS from cache如果有 hit,會看到這樣的 header
Nginx-Cache:HIT from cache範例
完整的範例
http {
    proxy_cache_path /usr/share/nginx/cache levels=1:2 keys_zone=STATIC:50m inactive=1d max_size=20g;
    server {
        location / {
            proxy_pass             http://127.0.0.1:8080;
            proxy_set_header       Host $host;
            proxy_cache            STATIC;
            proxy_cache_valid      200 302 10m;
            proxy_cache_valid      301 1h;
            proxy_cache_valid      404 1m;
            proxy_cache_valid      any 1m;
            proxy_cache_use_stale  error timeout invalid_header updating
                                   http_500 http_502 http_503 http_504;
        }
    }
}紀錄最後修改好的設定檔
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
    worker_connections 1024;
}
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;
    proxy_cache_path /usr/share/nginx/cache levels=1:2 keys_zone=STATIC:50m inactive=1d max_size=20g;
    server {
        listen       6000 default_server;
        listen       [::]:6000 default_server;
        server_name  _;
    server_tokens off;
        root         /usr/share/nginx/html;
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
        location / {
            proxy_pass             http://127.0.0.1:8080;
            proxy_set_header       Host $host;
            proxy_set_header       X-Real-IP $remote_addr;
            proxy_set_header       X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    location ~ .*\.(gif|jpg|png|bmp|swf|js|css|lzv|pdf|html|jsp)$ {
        proxy_cache            STATIC;
        proxy_cache_valid      200 302 10m;
        proxy_cache_valid      301 1h;
        proxy_cache_valid      404 1m;
        proxy_cache_valid      any 1m;
        #proxy_cache_use_stale  error timeout invalid_header updating
        #                       http_500 http_502 http_503 http_504;
        proxy_cache_key     $host$uri$is_args$args;
        proxy_set_header       Host $host;
        proxy_set_header       X-Real-IP $remote_addr;
        #proxy_set_header       X-Real-IP $Forwarded-For;
        proxy_set_header       X-Forwarded-For $proxy_add_x_forwarded_for;
        add_header      Nginx-Cache     "$upstream_cache_status from cache";
        proxy_pass             http://127.0.0.1:8080;
    }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}清除 cache
如果要清除 cache,可直接刪除 proxycachepath 目錄下所有檔案
vi clear_nginx_cache.sh
#!/bin/bash
find /usr/share/nginx/cache -type f -exec rm -f {} \;
chmod 755 clear_nginx_cache.sh每天定時刪除超過兩天的 cache file
vi /etc/cron.daily/delete_nginx_cache.sh
#!/bin/bash
find /usr/share/nginx/cache -type f -mtime +2 -print0 | xargs -0 -r rm >/dev/null 2>&1
chmod 755 /etc/cron.daily/delete_nginx_cache.sh處理 Nginx 產生的大量 TCP_WAIT
由於 Nginx Proxy 會產生大量 TCP_WAIT,我們需要調整 linux TCP 的參數,並調整 nginx 的設定。
# 用 netstat 查看 TCP_WAIT 數量
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
# 用 ss 查看 TCP_WAIT 數量
ss -ant | awk 'NR>1 {++s[$1]} END {for(k in s) print k,s[k]}'查看 /proc/sys/net/ipv4/iplocalport_range 設定檔,可得知 Linux 動態分配 Local Port 的 Range。
cat /proc/sys/net/ipv4/ip_local_port_range
32768   61000透過修改 /etc/sysctl.conf 可調整 local service ports
vim /etc/sysctl.conf
net.ipv4.ip_local_reserved_ports = 32768-61000
sysctl -p修改 /etc/sysctl.conf TCP 參數
vim /etc/sysctl.conf
net.ipv4.ip_local_port_range = 1024 65535
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save = 1
net.core.somaxconn = 65535
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
# sysctl.conf 重新載入設定
sysctl -p修改 /etc/security/limits.conf
vim /etc/security/limits.conf
* soft nofile 655360
* hard nofile 655360
ulimit -n 655360修改 /etc/nginx/nginx.conf 參數
vim /etc/nginx/nginx.conf
worker_rlimit_nofile 102400;
events {
    worker_connections 1024; # 可以加到 4096
    #worker_connections 768;
    use epoll;
    # multi_accept on;
}
upstream webserver {
   server 127.0.0.1:8000 weight=10;
   keepalive       16;
}
http {
    #keepalive_timeout 65;
    keepalive_timeout 1;
}
# 後面 proxy_pass 的地方要改成這樣
proxy_pass             http://webserver;
References
varnish / squid / nginx cache 有什麼不同?
RHEL / CentOS 7 安裝 Nginx, MySQL, PHP (LEMP)
 
 
沒有留言:
張貼留言