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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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
1
|
#yum -y install varnish
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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}"
#所有启动加载选项
|
启动服务如下:
1
|
# service varnish start
|
Varnish命令介绍
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 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运行异常缓慢
|
1
2
3
4
5
6
7
8
|
######在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界面
安装论坛程序:
1
2
3
4
5
6
7
8
9
10
11
|
# 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配置文件,建议基于默认的配置文件基础上修改,修改前
备份一下文件。
[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"
从上图中可以看出,提供静态页面的服务停止后,所有图片都不能显示,当然把服务再启动起来就可以访问正常了,这里就不在测试了…
验证健康状态检测
查看缓存命中率状态;命中率的高低
本文转自xinrenbaodao 51CTO博客,原文链接:http://blog.51cto.com/11832904/1970415,如需转载请自行联系原作者