第十六周微职位:Memcached,haproxy,varnish

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

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、结构示意图:

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


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调试模式    
- file                 #指定varnish服务器的配置文件    
- p param = value          #指定服务器参数,用来优化varnish性能    
- file                 #Varnish进程PID文件存放路径    
- 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版本号和版权信息    
- int [, int [, int ]]      #设定varnish的工作线程数,常用的方式有:  -w min,max    
  - min , max ,timeout    
如: - w3, 25600 , 50        #这里最小启动的线程数不能设定过大,设置过大,会导致varnish运行异常缓慢
环境如下:

wKiom1nVjILhmtJuAAA7tBXR0Ko681.png

在lamp1、lamp2上分别都安装服务并启动
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/*      #修改属主权限

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





      本文转自xinrenbaodao  51CTO博客,原文链接:http://blog.51cto.com/11832904/1970415,如需转载请自行联系原作者






相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
负载均衡 网络协议 关系型数据库
一口把LVS、Nginx及HAProxy工作原理讲清楚了。(附图)
一口把LVS、Nginx及HAProxy工作原理讲清楚了。(附图)
|
7月前
|
存储 缓存 运维
LAMP+Varnish缓存详解(一)——Varnish简介
LAMP+Varnish缓存详解(一)——Varnish简介
75 0
|
7月前
|
缓存 负载均衡 应用服务中间件
百度搜索:蓝易云【LVS/Nginx/HAProxy原理及应用场景介绍】
总结:LVS、Nginx和HAProxy都是常见的负载均衡技术和工具。它们能够分担系统负载、提高可用性和性能,并在高负载环境下实现请求分发和流量管理。选择适合自己需求的负载均衡方案,可以根据具体应用场景和要求进行评估和决策。
85 4
|
监控 应用服务中间件 调度
Nginx为什么快到根本停不下来?
Nginx为什么快到根本停不下来?
232 0
|
负载均衡 网络协议 JavaScript
负载均衡 LVS vs Nginx 对比!还傻傻分不清?
负载均衡 LVS vs Nginx 对比!还傻傻分不清?
让我直接涨薪5K的Nginx/OpenResty详解,NginxLua操作Redis有多牛
实战案例运行准备:本节涉及的配置文件为源码工程的nginxredis-demo.conf文件。在运行本节实例前需要修改启动脚本openresty-start.bat(或openresty-start.sh)中的PROJECT_CONF变量的值,将其改为nginx-redis-demo.conf,然后重启OpenRestry。
|
缓存 负载均衡 监控
负载均衡 LVS vs Nginx 对比,还傻傻分不清?
负载均衡 LVS vs Nginx 对比,还傻傻分不清?
301 0
负载均衡 LVS vs Nginx 对比,还傻傻分不清?
|
负载均衡 监控 网络协议
我个人的分布式集群问题集锦,nginx/lvs/dns/cdn(★firecat推荐★)
我个人的分布式集群问题集锦,nginx/lvs/dns/cdn(★firecat推荐★)
497 0
我个人的分布式集群问题集锦,nginx/lvs/dns/cdn(★firecat推荐★)
|
监控 Java 数据库
Zabbix proxy分布式监控(学习笔记三十一)
转载:http://www.cnblogs.com/yaoyaojcy/p/8182067.html 自学Zabbix13.1分布式监控proxy介绍 zabbix2.
1566 0