第十六週微職位:Memcached,haproxy,varnish

一、爲LNMP架構添加memcached支持,並完成對緩存效果的測試報告;php

1、Memcached的簡介:css

    Memcached是一個自由開源的,高性能,分佈式內存對象緩存系統。它是一種基於內存的key-value存儲,用來存儲小塊的任意數據(字符串、對象)。這些數據能夠是數據庫調用、API調用或者是頁面渲染的結果。html

    Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的不少問題。它的API兼容大部分流行的開發語言。本質上,它是一個簡潔的key-value存儲系統。python

通常的使用目的是,經過緩存數據庫查詢結果,減小數據庫訪問次數,以提升動態Web應用的速度、提升可擴展性。mysql

特徵:nginx

    1)協議簡單;web

    2)基於libevent的事件處理;算法

    3)內置內存存儲方式;sql

    4)memcached不互相通訊的分佈式。數據庫

Memcached經常使用選項:

    -l <ip_addr>:監聽的地址
    -m <num>:緩存空間大小,單位爲MB, 默認爲64
    -c <num>:最大併發鏈接數,默認爲1024
    -M:緩存空間耗盡時,向請求者返回錯誤信息,而不是基於LRU算法進行緩存清理
    -f <factor>:growth factor, 增加因子
    -t <threads>:處理用於請求的線程數

二 基於LNMP架構添加Memcached支持並驗證其結果

一、結構示意圖:

wKiom1nViCHCDhz6AABco8LB8fY196.png

2. 實驗環境

IP    功用    

192.168.237.129    nginx    

192.168.237.131    php-fpm+mariadb+memcached    

3. 實驗步驟

Nginx, PHP-FPM和MariaDB安裝在此忽略。

(1) Memcached安裝

#安裝Memcached
yum -y install memcached
#啓動Memcached
memcached -d -m 1024 -u memcached

鏈接測試

telnet 192.168.237.131 11211

wKioL1nViDzhlqGXAAANSYQrp2Q196.png


查看Memcached信息

wKiom1nViJbQYDKLAAA5ueWCWX8084.png

(2) 安裝PHP的Memcached的擴展

    php鏈接memcached服務的模塊有兩個,php-pecl-memcache和php-pecl-memcached.若要安裝php-pecl-memcached須要依賴libmemcached程序包,能夠提供相應操做查看memcached的工具。在這裏爲方便演示就直接使用php-pecl-memcache擴展模塊。

    #安裝PHP的Memcached擴展模塊
    yum -y install php-pecl-memcache

    測試PHP是否已支持Memcached, 瀏覽器中輸入http://192.168.237.129/index.php

(3) 測試Memcached緩存

#在nginx根目錄下寫入php測試腳本
vim /usr/share/nginx/html/test.php
<?php
$mem = new Memcache;
$mem->connect("192.168.237.131", 11211);   #鏈接Memcached

$version = $mem->getVersion();
echo "Server's version: ".$version."<br/>\n";   #輸出Memcached版本信息

$mem->set('testkey', 'Hello World', 0, 600);   #向Memcached存儲數據'Hello World',時間爲600s
echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";   

$get_result = $mem->get('testkey');   #獲取testkey的值
echo "$get_result is from memcached server.";
?>

測試Memcached緩存結果,在瀏覽器中輸入192.168.237.129/test.php

wKioL1nViTfDvySaAAAt3WfwbeA835.png

能夠看出緩存已生效,再查看Memcached相應信息

wKioL1nViUegpLtZAAA9XWunRYw327.png


二、部署配置haproxy,可以實現未來自用戶的80端口的http請求轉發至後端8000上的server服務,寫出其配置過程。

Haproxy的安裝:(也可經過源碼安裝)

yum -y install haproxy

修改基本的配置文件以下:

配置文件所在地址: /etc/haproxy/haproxy.cfg   

 global   
    maxconn 5120      
    chroot /usr/share/haproxy      
    daemon      
    quiet      
    nbproc 2      
    pidfile /usr/share/haproxy/haproxy.pid      
defaults      
    option  httplog      
    option  dontlognull      
    timeout connect 5s      
    timeout client 50s      
    timeout server 20s      
listen http      
    bind :80      
    timeout client 1h      
    tcp-request inspect-delay 2s       
    tcp-request content accept if is_http      
    server server-http :8080      
backend servers     
    server server1 127.0.0.1:8080 maxconn 32

 

三、闡述varnish的功能及其應用場景,並經過實際的應用案例來描述配置、測試、調試過程。


先安裝varnish

#yum -y install varnish
配置文件的簡單介紹

  

NFILES=131072                
MEMLOCK=82000    
NPROCS="unlimited"    
# DAEMON_COREFILE_LIMIT="unlimited"        #內核最大打開的文件數    
RELOAD_VCL=1                               #是否自動加載VCL    
VARNISH_VCL_CONF=/etc/varnish/default.vcl  #默認加載的VCL文件    
VARNISH_LISTEN_PORT=80                     #監聽端口,默認爲6081    
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1     #管理的IP地址    
VARNISH_ADMIN_LISTEN_PORT=6082             #管理端口    
VARNISH_SECRET_FILE=/etc/varnish/secret    #密鑰文件    
VARNISH_MIN_THREADS=50                     #最小線程數量    
VARNISH_MAX_THREADS=1000                   #最大線程數量  
VARNISH_THREAD_TIMEOUT=120                 #線程超時時間    
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin #緩存文件位置    
VARNISH_STORAGE_SIZE=1G                    #設置文件緩存大小變量    
VARNISH_MEMORY_SIZE=64M                    #設置內存緩存大小變量    
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}" #默認存儲到文件中,這裏能夠修改存儲位置    
VARNISH_STORAGE="malloc,${VARNISH_MEMORY_SIZE}" #設置緩存位置爲內存    
VARNISH_TTL=120                    
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \    
             -f ${VARNISH_VCL_CONF} \    
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \    
             -t ${VARNISH_TTL} \    
             -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \    
             -u varnish -g varnish \    
             -S ${VARNISH_SECRET_FILE} \    
             -s ${VARNISH_STORAGE}"    #全部啓動加載選項

啓動服務以下:

# service varnish start

Varnish命令介紹

# varnishd -h    
-a address:port        #表示varnish對httpd的監聽地址及其端口    
-b address:port        #表示後端服務器地址及其端口    
-d                     #表示使用debug調試模式    
-f file                #指定varnish服務器的配置文件    
-p param=value         #指定服務器參數,用來優化varnish性能    
-P file                #Varnish進程PID文件存放路徑    
-n dir                 #指定varnish的工做目錄    
-s kind[,storageoptions] #指定varnish緩存內容的存放方式,經常使用的方式有:「-s file,<dir_or_file>,<size>」;其中「<dir_or_file>」    
                          指定緩存文件的存放路徑,「<size>」指定緩存文件的大小    
-t                     #指定默認的TTL值    
-T address:port        #設定varnish的telnet管理地址及其端口    
-V                     #顯示varnish版本號和版權信息    
-w int[,int[,int]]     #設定varnish的工做線程數,經常使用的方式有:  -w min,max    
 -w min,max,timeout    
如:-w3,25600,50       #這裏最小啓動的線程數不能設定過大,設置過大,會致使varnish運行異常緩慢
環境以下:

wKiom1nVjILhmtJuAAA7tBXR0Ko681.png

在lamp一、lamp2上分別都安裝服務並啓動
######在Lamp1服務器上安裝Httpd、Php、Mysql,啓動服務    
# yum -y install httpd php mysql-server php-mysql    
# service httpd start    
# service mysqld start    
------------------------------------------------------------------------    
######在Lamp2服務器上安裝Httpd、Php,啓動服務    
# yum -y install httpd php php-mysql    
# service httpd start


lamp上都測試php界面

安裝論壇程序:

# mysql    
mysql> create database bbs;    
mysql> grant all on bbs.* to 'bbsuser'@'172.16.%.%' identified by 'bbspass';    
mysql> flush privileges;    
註釋:爲論壇建立一個數據庫並受權用戶訪問    
------------------------------------------------------------------------    
######安裝論壇程序    
# unzip Discuz_X3.0_SC_UTF8.zip    
# cp -rf upload/* /var/www/html/    
# chmod -R +w /var/www/html/{config,data,uc_server,uc_client}    #添加可寫權限    
# chown -R apache /var/www/html/*      #修改屬主權限

wKioL1nVjQaR5HNAAADtJ1Gyvuk230.png

將論壇程序拷貝到lamp2服務器上一份並訪問測試

# scp -rp /var/www/html/* 172.16.14.3:/var/www/html/    

# service httpd restart    #重啓lamp2服務器的WEB服務    

安裝web服務器並測試頁面:

# yum -y install httpd    

# service httpd start    

# echo "<h1>WEB</h1>" > /var/www/html/index.html #建立測試頁    

wKioL1nVjVHgmLu0AABd5OXCCDQ507.png

將Lamp1服務器上的論壇程序拷貝到WEB服務器一份,由於須要論壇中的一些靜態文件如:(.jpg|.html)結尾的文件等

# scp -rp /var/www/html/* 172.16.14.3:/var/www/html/    


Varnish安裝及配置

在第一部分中咱們已經修改過默認監聽端口爲"80",接下來爲Varnish提供一個VCL配置文件,建議基於默認的配置文件基礎上修改,修改前    

備份一下文件。    

[root@varnish ~]# cd /etc/varnish/    

[root@varnish varnish]# cp default.vcl default.vcl.bak    

[root@varnish varnish]# vim default.vcl    

######定義ACL    

acl purgers {                    #定義acl,實現IP地址過濾    

    "127.0.0.1";    

    "172.16.0.0"/16;    

}    

######定義健康狀態檢測    

probe dynamic {                  #設置動態網站服務器健康狀態檢測    

    .url = "/index.html";    

    .interval = 5s;    

    .timeout = 1s;    

    .expected_response = 200;    

}            #這裏設置了兩個健康狀態檢測主要是爲了區分動、靜網站    

probe static {                   #設置動態網站服務器健康狀態檢測    

    .url = "/index.html";        #定義檢測的頁面    

    .interval = 5s;              #探測請求的發送週期,默認爲5秒    

    .timeout = 1s;               #每次探測請求的過時時間    

    .expected_response = 200;    

}    

######定義後端服務器    

backend app1 {                  #定義一個後端服務器    

    .host = "172.16.14.2";      #服務器地址    

    .port = "80";               #服務器監聽端口    

    .probe = dynamic;           #健康狀態檢測    

}    

backend app2 {    

    .host = "172.16.14.3";    

    .port = "80";    

    .probe = dynamic;    

}    

backend web {              

    .host = "172.16.14.4";    

    .port = "80";    

    .probe = static;    

}    

######定義後端服務器組,實現負載均衡效果    

director apps random {          #定義一個後端服務器組,實現負載均衡效果    

    {    

         .backend = app1;       #調用前面已定義過的後端主機    

     .weight = 2;           #設置權重    

    }    

    {    

     .backend = app2;    

     .weight = 2;    

    }    

}    

######定義vcl_recv函數,實現請求到達併成功接收後調用此函數中定義的規則    

sub vcl_recv {    

######定義動、靜分離,以".php"或".php?後面跟全部文件"結尾的請求都發送到動態服務器,其餘請求都發送到靜態服務器    

    if (req.url ~ "\.php(\?\.*|$)") {    

    set req.backend = apps;    

    } else {    

    set req.backend = web;    

    }    

    return(lookup);    

######定義容許清除緩存的IP地址,調用的是前面定義的ACL    

    if (req.request == "PURGE") {    

        if (!client.ip ~ purgers) {    

        error 405 "Method not allowed";    

    }    

        return(lookup);    

    }    

######從新定義http請求首部,讓後端服務器能夠記錄請求客戶端的真實IP地址    

        if (req.restarts == 0) {    

            if (req.http.x-forwarded-for) {    

               set req.http.X-Forwarded-For =    

               req.http.X-Forwarded-For + ", " + client.ip;    

            } else {    

                 set req.http.X-Forwarded-For = client.ip;    

            }    

         }    

######除了定義的請求方法外,其餘請求都到後端服務器    

    if (req.request != "GET" &&    

        req.request != "HEAD" &&    

        req.request != "PUT" &&    

        req.request != "POST" &&    

        req.request != "TRACE" &&    

        req.request != "OPTIONS" &&    

        req.request != "DELETE") {    

        return (pipe);    

    }    

    if (req.request != "GET" && req.request != "HEAD") {    

        return (pass);    

    }    

######定義不緩存認證與Cookie信息    

    if (req.http.Authorization || req.http.Cookie) {    

        return (pass);    

    }    

######定義壓縮功能    

    if (req.http.Accept-Enconding) {    

       if (req.url ~ "\.(jpg|jpeg|gif|bmp|png|flv|gz|tgz|tbz|mp3)$") {    

           remove req.http.Accept-Encoding;    

       remove req.http.Cookie;    

       } else if (req.http.Accept-Encoding ~ "gzip") {    

       set req.http.Accept-Encoding = "gzip";    

       } else if (req.http.Accept-Encoding ~ "deflate") {    

       set req.http.Accept-Encoding = "deflate";    

       } else { remove req.http.Accept-Encoding;    

       }    

    }    

######定義指定格式結尾的文件去除Cookie信息    

    if (req.request == "GET" && req.url ~ "\.(jpeg|jpg|gif|png|bmp|swf)$") {    

    unset req.http.cookie;    

    }    

######定義防盜鏈設置    

    if (req.http.referer ~ "http://.*") {    

        if (!(req.http.referer ~ "http://.*\.baidu\.com" || req.http.referer ~"http://.*\.google\.com.*")) {    

              set req.http.host = "www.allen.com";    

          set req.url = "http://172.16.14.4/error.html";    

    }    

    }    

}    

######定義vcl_hash函數    

sub vcl_hash {    

    hash_data(req.url);    

    if (req.http.host) {    

        hash_data(req.http.host);    

    } else {    

        hash_data(server.ip);    

    }    

    return(hash);    

}    

######定義vcl_hit函數    

sub vcl_hit {    

    if (req.request == "PURGE") { #語法方法爲"PURGE"    

       purge;                     #清除緩存    

       error 200 "Purged.";       #返回錯誤狀態碼爲"200"    

    }    

    return(deliver);    

}    

######定義vcl_miss函數    

sub vcl_miss {    

    if (req.request == "PURGE") {    

    purge;    

    error 404 "Not In Cache.";    

    }    

    return(fetch);    

}    

######定義vcl_psss函數    

sub vcl_pass {    

    if (req.request == "PURGE") {    

       error 502 "Purged On A Passed Object.";    

    }    

    return(pass);    

}    

######定義vcl_fetch函數    

sub vcl_fetch {    

######定義緩存,若是匹配到已定義文件結尾的緩存1天,其餘則緩存1小時    

    if (req.request == "GET" && req.url ~ "\.(html|jpg|png|bmp|jpeg|gif|js|ico|swf|css)$") {    

       set beresp.ttl = 1d;    

       set beresp.http.expires = beresp.ttl;    

    } else {    

       set beresp.ttl = 1h;    

    }    

    return(deliver);    

}    

######定義在http首部中,若是請求命中顯示"HIT",未命中則顯示"MISS"    

sub vcl_deliver {    

    if (obj.hits > 0) {    

       set resp.http.X-Cache = "HIT";    

    } else {    

       set resp.http.X-Cache = "MISS";    

    }    

}    

----------------------------------------------------------------------    

[root@varnish ~]# service varnish restart    #重啓服務生效,重啓服務器後全部緩存將被清除,固然也能夠不用重啓服務使其生效,以下:    

----------------------------------------------------------------------    

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082    

varnish> help                        #獲取幫助    

varnish> vcl.load acl_1 default.vcl  #加載acl文件,acl_1爲配置名稱    

200       

VCL compiled.    

varnish> vcl.list                    #查看加載的acl文件列表    

200       

active          7 boot    

available       0 acl_1    

varnish> vcl.use acl_1               #應用acl文件    

200    

varnish> quit                        #退出    

------------------------------------------------------------------------    

註釋:  -S:指定varnish的密鑰文件  -T:指定varnish服務器地址及管理端口,默認端口爲"6082"    

服務驗證:

壓力測試,以下:    

######後端服務器不通過緩存測試    

[root@localhost ~]# ab -c 100 -n 1000 http://172.16.14.2/index.php    

Concurrency Level:      1000    

Time taken for tests:   6.812 seconds    

Complete requests:      10000    

Failed requests:        0    

Write errors:           0    

Non-2xx responses:      10051    

Total transferred:      2281577 bytes    

HTML transferred:       0 bytes    

Requests per second:    1468.04 [#/sec] (mean)  #每秒請求併發    

Time per request:       681.179 [ms] (mean)    

Time per request:       0.681 [ms] (mean, across all concurrent requests)    

Transfer rate:          327.10 [Kbytes/sec] received    

----------------------------------------------------------------------    

######通過緩存測試    

[root@localhost ~]# ab -c 1000 -n 10000 http://172.16.14.1/index.php    

Concurrency Level:      1000    

Time taken for tests:   2.594 seconds    

Complete requests:      10000    

Failed requests:        0    

Write errors:           0    

Non-2xx responses:      10056    

Total transferred:      3117360 bytes    

HTML transferred:       0 bytes    

Requests per second:    3855.05 [#/sec] (mean)    

Time per request:       259.400 [ms] (mean)    

Time per request:       0.259 [ms] (mean, across all concurrent requests)    

Transfer rate:          1173.59 [Kbytes/sec] received    

----------------------------------------------------------------------    

註釋:從上面數據中能夠看出,通過緩存作壓力測試併發量高    

測試緩存是否能命中    

[root@lamp2 ~]# curl -I http://172.16.14.1/index.php    

HTTP/1.1 301 Moved Permanently    

Server: Apache/2.2.15 (CentOS)    

X-Powered-By: PHP/5.3.3    

location: forum.php    

Content-Type: text/html; charset=UTF-8    

Content-Length: 0    

Accept-Ranges: bytes    

Date: Thu, 05 Oct 2017 09:48:01 GMT    

X-Varnish: 2142028839    

Age: 0    

Via: 1.1 varnish    

Connection: keep-alive    

X-Cache: MISS    #第一次請求,未命中顯示"MISS"    

------------------------------------------------------------------------    

[root@lamp2 ~]# curl -I http://172.16.14.1/index.php    

HTTP/1.1 301 Moved Permanently    

Server: Apache/2.2.15 (CentOS)    

X-Powered-By: PHP/5.3.3    

location: forum.php    

Content-Type: text/html; charset=UTF-8    

Content-Length: 0    

Accept-Ranges: bytes    

Date: Thu, 05 Oct 2017 09:48:15 GMT     

X-Varnish: 2142028841 2142028839    

Age: 7    

Via: 1.1 varnish    

Connection: keep-alive    

X-Cache: HIT    #第二次請求,命中則顯示"HIT"    


驗證動、靜分離的效果:

wKiom1nVj0yg8i-TAACR8i2Ueyw707.png

    從上圖中能夠看出,提供靜態頁面的服務中止後,全部圖片都不能顯示,固然把服務再啓動起來就能夠訪問正常了,這裏就不在測試了…

    驗證健康狀態檢測

wKiom1nVj9aB7-8XAABEbzkS6MY161.png


查看緩存命中率狀態;命中率的高低

wKiom1nVj-riotgEAACGvu45KDo948.png

相關文章
相關標籤/搜索