第十六周微職位:Memcached,haproxy,varnish
1、為LNMP架構添加memcached支持,並完成對緩存效果的測試報告;
一、Memcached的簡介:
Memcached是一個自由開源的,高性能,分布式內存對象緩存系統。它是一種基於內存的key-value存儲,用來存儲小塊的任意數據(字符串、對象)。這些數據可以是數據庫調用、API調用或者是頁面渲染的結果。
Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的很多問題。它的API兼容大部分流行的開發語言。本質上,它是一個簡潔的key-value存儲系統。
一般的使用目的是,通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態Web應用的速度、提高可擴展性。
特征:
1)協議簡單;
2)基於libevent的事件處理;
3)內置內存存儲方式;
4)memcached不互相通信的分布式。
Memcached常用選項:
-l <ip_addr>:監聽的地址-m <num>:緩存空間大小,單位為MB, 默認為64
-c <num>:最大並發連接數,默認為1024
-M:緩存空間耗盡時,向請求者返回錯誤信息,而不是基於LRU算法進行緩存清理
-f <factor>:growth factor, 增長因子
-t <threads>:處理用於請求的線程數
二 基於LNMP架構添加Memcached支持並驗證其結果
1、結構示意圖:
2. 實驗環境
IP 功用
192.168.237.129 nginx
192.168.237.131 php-fpm+mariadb+memcached
3. 實驗步驟
Nginx, PHP-FPM和MariaDB安裝在此忽略。
(1) Memcached安裝
#安裝Memcachedyum -y install memcached
#啟動Memcached
memcached -d -m 1024 -u memcached
連接測試
telnet 192.168.237.131 11211
查看Memcached信息
(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
可以看出緩存已生效,再查看Memcached相應信息2、部署配置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
3、闡述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運行異常緩慢環境如下:在lamp1、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/* #修改屬主權限
將論壇程序拷貝到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 #創建測試頁
將Lamp1服務器上的論壇程序拷貝到WEB服務器一份,因為需要論壇中的一些靜態文件如:(.jpg|.html)結尾的文件等
# scp -rp /var/www/html/* 172.16.14.3:/var/www/html/
Varnish安裝及配置
在第一部分中我們已經修改過默認監聽端口為"80",接下來為Varnish提供一個VCL配置文件,建議基於默認的配置文件基礎上修改,修改前
備份一下文件。
[[email protected] ~]# cd /etc/varnish/
[[email protected] varnish]# cp default.vcl default.vcl.bak
[[email protected] 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";
}
}
----------------------------------------------------------------------
[[email protected] ~]# service varnish restart #重啟服務生效,重啟服務器後所有緩存將被清除,當然也可以不用重啟服務使其生效,如下:
----------------------------------------------------------------------
[[email protected] ~]# 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"
服務驗證:
壓力測試,如下:
######後端服務器不經過緩存測試
[[email protected] ~]# 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
----------------------------------------------------------------------
######經過緩存測試
[[email protected] ~]# 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
----------------------------------------------------------------------
註釋:從上面數據中可以看出,經過緩存做壓力測試並發量高
測試緩存是否能命中
[[email protected] ~]# 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"
------------------------------------------------------------------------
[[email protected] ~]# 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"
從上圖中可以看出,提供靜態頁面的服務停止後,所有圖片都不能顯示,當然把服務再啟動起來就可以訪問正常了,這裏就不在測試了…
驗證健康狀態檢測
查看緩存命中率狀態;命中率的高低
本文出自 “11822904” 博客,請務必保留此出處http://11832904.blog.51cto.com/11822904/1970415
第十六周微職位:Memcached,haproxy,varnish