在实际的生产使用过程中,一个基本的能够应对日均百万PV的网络,一般会具有以下几种结构。
这其中每种结构担负了不同的角色。
代理服务器,负责进行请求调度,实现了负载均衡。
KeepAlived配置代理服务器实现了高可用。
缓存服务器,实现了资源的缓存,提高了请求的命中率,加快了访问速度。
动静分离,减轻后端服务器压力,提高资源访问速度。
数据库主从复制,读写分离,降低了数据库的压力
运维监控系统,实时监控系统运行状态。
自动化运维控制系统,批量管理大量服务器。
版本控制系统,在应用的迭代过程中有着至关重要的作用。
下面,我们来模拟实现一个简单的网络集群结构。下面是这个结构的网络拓扑图。
实验环境介绍
序号 | 担任角色 | 主机名 | 地址 | 功能描述 |
---|---|---|---|---|
A | 互联网客户端 | windows | 172.18.2.22 | 充当互联网用户进行网络访问 |
B | 代理服务器 | haproxy | VIP 172.18.3.77;DIP 192.168.22.77 | 对网络请求进行调度,实现均衡负载 |
C | 缓存服务器 | varnish 1 | 192.168.22.33 | 针对网络请求进行缓存,同时对后端服务器进行动静分离,并提供均衡负载 |
D | 缓存服务器 | varnish 2 | 192.168.22.44 | 针对网络请求进行缓存,同时对后端服务器进行动静分离,并提供均衡负载 |
E | 静态web服务器 | staticweb1 | 192.168.22.100 | 提供静态的网络服务,例如html,js,css之类 |
F | 静态web服务器 | staticweb2 | 192.168.22.101 | 提供静态的网络服务,例如html,js,css之类 |
G | 动态web服务器 | dynamicweb1 | 192.168.22.200 | 提供动态的网络服务,例如PHP,jsp等 |
H | 动态web服务器 | dynamicweb2 | 192.168.22.201 | 提供动态的网络服务,例如PHP,jsp等 |
I | 数据库服务器 | database | 192.168.22.128 | 提供数据库服务,供应用程序进行读写操作 |
实验过程中,首先关闭SELinux和防火墙策略
在主机A上安装HAProxy,并对其进行配置。
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 # 指定对外提供网络服务的端口 frontend web 172.18.3.77:80 bind 172.18.3.77:9099 stats enable stats uri /hastats stats hide-version stats refresh 2s use_backend varnish_srvs # 指定后端的Varnish缓存服务器 # 使用的端口是varnish的默认端口,这一点需要在varnish服务器中进行配置 backend varnish_srvs balance uri hash-type consistent server varnish1 192.168.22.33:6081 weight 1 check server varnish2 192.168.22.44:6081 weight 1 check
将HAProxy配置好以后,重启一下服务。然后在浏览器中输入
http://172.18.3.77:9099/hastats
,就可以查看到HAProxy的调度管理界面。
此时,如果Varnish服务器已经配置成功了的话,就会显示出如下界面。
此时,在配置好HAProxy服务器之后,就可以对varnish缓存服务器进行配置了。主要修改的文件为下面两个。Varnish1 与Varnish2的配置文件一致,将IP修改为自己对应的IP就可以了。
/etc/varnish/default.vcl
,varnish 的默认配置文件
/etc/varnish/varnish.params
,varnish 的一些默认参数。
其中
/etc/varnish/default.vcl
的配置内容,如下。
# new 4.0 format. vcl 4.0; #引入负载均衡模块 import directors; #静态检测 probe static_probe{ #指定检测URL .url="/"; #探测超时时长 .timeout=2s; #探测次数 .window=5; #探测次数成功多少次才算健康 .threshold=2; #Varnish启动探测后端主机2次健康后加入主机 .initial=2; #探测间隔时长 .interval=2s; #期望状态响应码 .expected_response=200; } #动态监测 probe dynamic_probe { .url="/index.php"; .timeout=2s; .window=5; .threshold=2; .initial=2; .interval=2s; .expected_response=200; } #指定后端服务器,并对后端服务器进行动态监测 backend staticweb1 { .host = "192.168.22.100"; .port = "80"; .probe = static_probe; } backend staticweb2 { .host = "192.168.22.101"; .port = "80"; .probe = static_probe; } backend dynamicweb1 { .host = "192.168.22.200"; .port = "80"; .probe =dynamic_probe; } backend dynamicweb2 { .host = "192.168.22.201"; .port = "80"; .probe =dynamic_probe; } # 定义负载均衡的调度算法 sub vcl_init { new staticcluster=directors.round_robin(); staticcluster.add_backend(staticweb1); staticcluster.add_backend(staticweb2); new dynamiccluster=directors.round_robin(); dynamiccluster.add_backend(dynamicweb1); dynamiccluster.add_backend(dynamicweb2); } #定义清理缓存的规则 acl purgers { "127.0.0.0"/8; "192.168.0.0"/16; } # 启用缓存清理 sub vcl_purge{ return(synth(200,"Purged")); } # 定义pipe函数 sub vcl_pipe{ return(pipe); } # 定义miss函数 sub vcl_miss{ return(fetch); } # 定义hash函数 sub vcl_hash{ hash_data(req.url); if(req.http.host){ hash_data(req.http.host); }else{ hash_data(server.ip); } if(req.http.Accept-Encoding~"gzip"){ hash_data("gzip"); }elseif(req.http.Accept-Encoding~"deflate"){ hash_data("deflate"); } } # 对接收到的请求进行配置处理 sub vcl_recv { # 不符合请求的清理操作被拒绝掉 if (req.method == "PURGE") { if (!client.ip ~ purgers) { return(synth(405,"Purging not allowed for " + client.ip)); } return(purge); } #让后端服务器能够看到真实的请求地址 if (req.restarts == 0) { if (req.http.X-Fowarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } # 设置动静分离 set req.http.X-Forward-For=client.ip; if(req.url~"(?i)\.(php|asp|aspx|jsp|do|cshtml)($|\?)"){ set req.backend_hint = dynamiccluster.backend(); } # 只缓存下列方法中指定的方法 if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "DELETE") { return (pipe); } #如果请求不是GET或者HEAD,不缓存 if (req.method != "GET" && req.method != "HEAD") { return (pass); } #如果请求包含Authorization授权或Cookie认证,不缓存 if (req.http.Authorization || req.http.Cookie) { return (pass); } if(req.http.Accept-Encoding){ if(req.url~"\.(bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)$"){ unset req.http.Accept-Encoding; }elseif(req.http.Accept-Encoding~"gzip"){ set req.http.Accept-Encoding="gzip"; }elseif(req.http.Accept-Encoding~"deflate"){ set req.http.Accept-Encoding="deflate"; }else{ unset req.http.Accept-Encoding; } } return (hash); } # 对响应的请求进行处理 sub vcl_backend_response { # 这里我们不做配置 } # 记录缓存的命中状态 sub vcl_deliver { if(obj.hits>0){ set resp.http.X-Cache="HITfrom"+req.http.host; set resp.http.X-Cache-Hits=obj.hits; }else{ set resp.http.X-Cache="MISSfrom"+req.http.host; } unset resp.http.X-Powered-By; unset resp.http.Server; unset resp.http.Via; unset resp.http.X-Varnish; unset resp.http.Age; }
对varnish的参数文件进行修改。这样便于让代理服务器知道应该将请求调度给谁。
# 6081 是varnish的默认监听端口 ,在HAProxy中需要对这个端口进行监听。 VARNISH_LISTEN_ADDRESS=192.168.22.33 VARNISH_LISTEN_PORT=6081
在上面的配置完成之后,在varnishadm控制台界面调用
backend.list
命令就能够查看,后端服务器的健康状态了。
backend.list 200 Backend name Refs Admin Probe staticweb1(192.168.22.100,,80) 1 probe Sick 0/5 staticweb2(192.168.22.101,,80) 1 probe Sick 0/5 dynamicweb1(192.168.22.200,,80) 1 probe Sick 0/5 dynamicweb2(192.168.22.201,,80) 1 probe Sick 0/5
因为我们的后端服务器还没有进行配置,所以四个服务器都是处于宕机状态。
使用yum来安装Httpd软件包就可以。安装之后,启动服务,确保80端口已经打开。此时再在Varnish服务器上调用
backend.list
命令就可以查看到已经又两个服务器处于Healthy状态了。
backend.list 200 Backend name Refs Admin Probe staticweb1(192.168.22.100,,80) 1 probe Healthy 5/5 staticweb2(192.168.22.101,,80) 1 probe Healthy 4/5 dynamicweb1(192.168.22.200,,80) 1 probe Sick 0/5 dynamicweb2(192.168.22.201,,80) 1 probe Sick 0/5
在数据库服务器上,安装数据库服务,同时建立给WordPress应用程序使用的数据库表和用户。
create database wpdb; grant all on wpdb.* to ‘wpuser‘@‘192.168.22.%‘ identified by "123456";
安装 httpd php php-mysql
# CentOS 6: yum install httpd php php-mysql service httpd start # CentOS 7: yum install httpd php php-mysql systemctl start httpd.service
安装wordpress,将wordpress 解压到http默认路径下,并修改WordPress的数据库配置文件。
修改目录权限
setfacl -R -m u:apache:rwx wordpress
创建varnish健康性检查页面
backend.list 200 Backend name Refs Admin Probe staticweb1(192.168.22.100,,80) 1 probe Healthy 5/5 staticweb2(192.168.22.101,,80) 1 probe Healthy 5/5 dynamicweb1(192.168.22.200,,80) 1 probe Healthy 5/5 dynamicweb2(192.168.22.201,,80) 1 probe Healthy 5/5
在浏览器地址栏输入
http://172.18.3.77/wordpress/index.php
,此时站点访问成功。
1、架构优点
HAProxy为缓存服务器提供了负载均衡,使用了uri调度算法,保证了同样路径的请求能够被调度到同样的主机上,提高了缓存的命中率。
HAProxy提供了web管理界面,能够更直观的进行调度管理和管控
Varnish的缓存机制,以及动静分离等技术,提高了web服务器的负载能力,从而使系统能够应对高并发量的请求
数据库的主从复制,也是企业实际生产应用中使用较多的生产策略,这样能够实现网络请求的频繁读写,对降低了数据库服务器的压力。
2、尚且不足
用户上传的静态资源如何存储到静态服务器中,文件的分布式存储与数据同步是这个结构需要解决的一个重要问题
HAproxy做负载均衡,没有冗余能力,容易出现单点故障,最好配合KeepAlived实现高可用。
如果用户在访问过程中,建立了Session会话,会话行为应该如何保持
本文出自 “救火队长” 博客,请务必保留此出处http://xiaoshuaigege.blog.51cto.com/6217242/1978988
基于HAProxy+Varnish实现动静分离、负载均衡的高可用集群
原文地址:http://xiaoshuaigege.blog.51cto.com/6217242/1978988