1、web站点架构
前端一台主机提供app server,当用户请求到达时,如果要存储结构化数据,就需要找一台主机做database server。当业务达到一定程度时,要把web server、存储等分割开来。大多数时候还需要文件系统服务器。要考虑的问题,一、文件服务器需要什么样的方式进行联系,二是基于什么样方式联系数据库服务器?无论是文件系统服务器还是数据库服务器的访问接口是不同的,比如每一个database都有自己的API,这个API以套接字的方式向外输出。如果app server想要跟database打交道,就要在app server上部署上与datbase对应的访问驱动。如何跟文件系统打交道,如果是nfs server那就把它挂载至本地就可以了,如果不是可挂载的存储,那么它的访问模式就跟关系型数据库的访问方式类似了。
静态内容让静态服务器提供,动态内容让动态服务器提供,根据用户请求内容的类型,分别分发到不同的服务器上。
haproxy的应用:
从客户端-->服务器-->动态引擎(即app server)-->数据库,haproxy都可以作为负载均衡器的提供实现。用户请求到达时可以将haproxy作为负载均衡器将用户的请求分散至多个后端的web server,如果web server本身向后端请求内容时不能负载均衡的话,也可以借助于haproxy将web server对后端动态内容请求负载均衡至多个应用程序服务器(即动态引擎),应用程序访问mysql时,需要动静分离,同时也需要将静态或动态内容的请求分发到不同的集群上,所以也可以借助于haproxy做负载均衡。
HAProxy的两个最主要的功用:
http协议的反向代理
tcp层的负载均衡器,不支持udp
LB:负载均衡实现方式
tcp层:
LVS,haproxy,nginx
application layer:
http协议:haproxy,nginx,ats,apache
mysql协议:mysql-proxy
2、代理服务器及haproxy基础
haproxy可以在用户空间模拟tcp的方式进行调度,所以一些基于tcp协议工作的服务都可以借助于haproxy进行调度。
HAProxy不提供任何高可用功能,而是提供代理功能,是http协议的代理,同时也是tcp层的负载均衡器。haproxy也提供非常强大的后端upstream或者real sever的健康状态检测功能,所以后端某个主机一旦宕机,haproxy就可以把请求重新发送到另外一个主机,因此一定意义上htproxy也具有高可用的功能。
在tcp层,haproxy主要实现的负载均衡调度的功能,所以一般提到haproxy作为代理时主要是涉及http协议。
http协议的代理根据方向的不同分为两种:
正向代理:代理,一手托两家,代理自己代为接收内网主机的请求,并对请求重新构建请求报文后发送到互联网上
反向代理:nat,通过地址转换的方式在内网和互联网之间建立了一个链路
代理的作用:web缓存(加速)、反响代理、内容路由(根据流量及内容类型等将请求转发至特定服务器)、转码器
缓存作用:减少冗余内容传输;节省带宽、缓解网络瓶颈;降低了对原始服务器的请求压力;降低了传输延迟
HAProxy:只是http协议的反向代理,不提供缓存功能, 但额外支持对基于tcp通信的应用做LB。
LVS无法在应用层完成比如动静分离的功能,
HAProxy简介
参考 https://www.jianshu.com/p/c9f6d55288c0 http://www.ttlsa.com/linux/haproxy-study-tutorial/
(1)HAProxy 是一款提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。 HAProxy特别适用 于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的 并发连接。并且它的运行模式使得它可以很简单安全 的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。
(2)HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连 接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是 为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。
(3)HAProxy 支持连接拒绝 : 因为维护一个连接的打开的开销是很低的,有时我们很需要限制攻击蠕虫(attack bots),也就是说限制它们的连接打开从而限制它们的危害。 这个已经为一 个陷于小型DDoS攻击的网站开发了而且已经拯救了很多站点,这个优点也是其它负载均衡器没有的。
(4)HAProxy 支持全透明代理(已具备硬件防火墙的典型特点): 可以用客户端IP地址或者任何其他地址来连接后端服务器. 这个特性仅在linux2.4/2.6内核打了cttproxy补丁后才可以使用. 这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。
性能
HAProxy借助于OS上几种常见的技术来实现性能的最大化。
1,单进程、事件驱动模型显著降低了上下文切换的开销及内存占用。
2,O(1)事件检查器(event checker)允许其在高并发连接中对任何连接的任何事件实现即时探测。
3,在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期及内存带宽;
4,借助于Linux 2.6 (>= 2.6.27.19)上的splice()系统调用,HAProxy可以实现零复制转发(Zero-copy forwarding),在Linux 3.5及以上的OS中还可以实现零复制启动(zero-starting);
5,内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长;
6,树型存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列;
7,优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程中重读任何内存区域;
8,精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;
所有的这些细微之处的优化实现了在中等规模负载之上依然有着相当低的CPU负载,甚至于在非常高的负载场景中,5%的用户空间占用率和95%的系统空间占用率也是非常普遍的现象,这意味着HAProxy进程消耗比系统空间消耗低20倍以上。因此,对OS进行性能调优是非常重要的。即使用户空间的占用率提高一倍,其CPU占用率也仅为10%,这也解释了为何7层处理对性能影响有限这一现象。由此,在高端系统上HAProxy的7层性能可轻易超过硬件负载均衡设备。
在生产环境中,在7层处理上使用HAProxy作为昂贵的高端硬件负载均衡设备故障故障时的紧急解决方案也时长可见。硬件负载均衡设备在“报文”级别处理请求,这在支持跨报文请求(request across multiple packets)有着较高的难度,并且它们不缓冲任何数据,因此有着较长的响应时间。对应地,软件负载均衡设备使用TCP缓冲,可建立极长的请求,且有着较大的响应时间。
HAProxy目前主要有三个版本: 1.3 , 1.4 ,1.5,CentOS6.6 自带的RPM包为 1.5 的。
HAProxy的核心功能
- 负载均衡:L4和L7两种模式,支持RR/静态RR/LC/IP Hash/URI Hash/URL_PARAM Hash/HTTP_HEADER Hash等丰富的负载均衡算法
- 健康检查:支持TCP和HTTP两种健康检查模式
- 会话保持:对于未实现会话共享的应用集群,可通过Insert Cookie/Rewrite Cookie/Prefix Cookie,以及上述的多种Hash方式实现会话保持
- SSL:HAProxy可以解析HTTPS协议,并能够将请求解密为HTTP后向后端传输
- HTTP请求重写与重定向
- 监控与统计:HAProxy提供了基于Web的统计信息页面,展现健康状态和流量数据。基于此功能,使用者可以开发监控程序来监控HAProxy的状态
HAProxy的关键特性
- 采用单线程、事件驱动、非阻塞模型,减少上下文切换的消耗,能在1ms内处理数百个请求。并且每个会话只占用数KB的内存。
- 大量精细的性能优化,如O(1)复杂度的事件检查器、延迟更新技术、Single-buffereing、Zero-copy forwarding等等,这些技术使得HAProxy在中等负载下只占用极低的CPU资源。
- HAProxy大量利用操作系统本身的功能特性,使得其在处理请求时能发挥极高的性能,通常情况下,HAProxy自身只占用15%的处理时间,剩余的85%都是在系统内核层完成的。
- HAProxy作者在8年前(2009)年使用1.4版本进行了一次测试,单个HAProxy进程的处理能力突破了10万请求/秒,并轻松占满了10Gbps的网络带宽。
可以从三个因素来评估负载均衡器的性能:
安装和配置haproxy示例
# yum install haproxy -y
# rpm -ql haproxy //查看haproxy的配置文件
/etc/haproxy/haproxy.cfg //主文件
/usr/sbin/haproxy //主程序
# cp haproxy.cfg{,.bakup}
haproxy是如何工作的?分为前后端分离和前后端不分离得情况
前后端分离得情况:
frontend:前端,指明监听在某个地址的某个端口上,可以接受客户端的请求的,接收到请求后就发送给backend。
use_backend:在前端要指明use_backend,但是use_backend是条件式的,可以指明在什么条件下使用,符合条件的都是用backend,
default_backend:不用条件式,可以使用默认做后端,不符合条件的都使用default_backend
backend:定义后端服务器组,指明有多少台服务器和使用什么算法。
balancer
server
server
use_backend:haproxy是利用use_backend把frontend和backend连接起来
前后端不分离得情况:一个frontend对应一个backend
listen:是指明监听的哪个地址哪个端口,表示前端
serevr:所有后端在server这里定义,不用专门定义backend.
default
另外frontend和backend中不光可以定义服务器,可以定义调用哪些后端,还可以像nginx一样定义条件判断,做URL重写等功能,这些可以在default中定义。
default就是为listen、fronend、backend提供统一的默认参数,如果listen等定义了就是用自己定义的参数,如果没有定义则使用default。
haproxy的配置文件:haproxy.cfg
全局配置:主要是配置haproxy服务器程序本身的工作特性
代理配置:配置haproxy作为服务器代理如何使用,所以代理配置下就是frontend、backend、listen、default
# vim /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#--------------------------------------------------------------------- #---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# ) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# ) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2 //定义日志选项,这里是通过log server来记录日志的 chroot /var/lib/haproxy //切换目录至/var/lib/haproxy下以安全方式运行
pidfile /var/run/haproxy.pid
maxconn 4000 //最大连接数
user haproxy //进程启动后以haproxy的身份运行
group haproxy
daemon //启动为守护进程,如果没有此选项那么haproxy将运行在前台 # turn on stats unix socket //表示本地访问stats(统计数据)时可以基于共享内存进行通信
stats socket /var/lib/haproxy/stats #---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/
option redispatch
retries
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 #---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main *:5000 //main是frontend的名字,*表示本机的所有地址,5000表示对应主机的端口
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js use_backend static if url_static
default_backend app #---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static //static是backend的名字,如果frontend调用的后端服务器的时候可以直接调用static
balance roundrobin
server static 127.0.0.1: check #---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
server app1 127.0.0.1: check
server app2 127.0.0.1: check
server app3 127.0.0.1: check
server app4 127.0.0.1: check
全局变量配置选项
配置环境:
代理服务器:192.168.184.141
后端服务器:192.168.184.142、192.168.184.142
在两台后端服务器安装上httpd并创建web页面
# yum install httpd -y
# echo "<h1>node2</h1>" > /var/www/html/index.html
# echo "<h1>node3</h1>" > /var/www/html/index.html
# systemctl start httpd
在代理服务器即node1:192.168.128.131上编辑文件
# vim haproxy.cfg
前面的不修改
1 #---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main *:80
default_backend websrvs //调用backend的名字 #---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend websrvs //websrvs是backend的名字
balance roundrobin
server web1 192.168.184.142:80 check //server也应该有自己的名字,这里是web1,check表示要做健康状态检查
server web2 192.168.184.143:80 check
# systemctl start haproxy
# systemctl status haproxy
# ss -tnlp //可以看到监听80端口的是haproxy进程,确保httpd和nginx没有开启
在浏览器中输入http://192.168.184.141/已经可以访问web服务了,表示代理服务器192.168.128.141已经可以做负载均衡了。
如果将后端的任意一台web服务器停掉web服务,那么代理服务器就不再把请求发送至这个主机,即haproxy可以作后端健康状态检测
开启日志功能:
log 127.0.0.1 local2 //在haproxy.cfg文件中,定义日志选项,这里是通过log server来记录日志的,是发给服务器有服务器接受记录的
# vim /etc/rsyslog.conf //修改如下
# Provides UDP syslog reception //先提供服务
$ModLoad imudp
$UDPServerRun 514
# Save boot messages also to boot.log
local7.* /var/log/boot.log
local2.* /var/log/haproxy.log //添加此行,让local2可以记录日志
# systemctl restart rsyslog //重启日志服务
# systemctl status rsyslog
# ss -tunl //查看是否监听了514端口
# tail /var/log/haproxy.log //查看代理服务器日志
Jan 20 10:24:07 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:07.908] main websrvs/web2 1/0/1/1/3 304 141 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Jan 20 10:24:08 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:07.911] main websrvs/web1 210/0/1/2/213 200 274 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Jan 20 10:24:08 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:08.123] main websrvs/web2 204/0/1/1/206 200 274 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Jan 20 10:24:08 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:08.329] main websrvs/web1 258/0/1/1/260 200 274 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Jan 20 10:24:08 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:08.589] main websrvs/web2 201/0/0/1/202 200 274 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Jan 20 10:24:08 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:08.792] main websrvs/web1 189/0/1/1/191 200 274 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Jan 20 10:24:09 localhost haproxy[6290]: 192.168.128.1:56276 [20/Jan/2019:10:24:08.984] main websrvs/web2 321/0/0/2/323 200 274 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
# tail /var/log/httpd/access_log //在后端服务器node2节点上查看httpd服务的访问日志,这里记录的都是代理服务器的访问记录,应该记录客户端的地址
192.168.128.1 - - [20/Jan/2019:09:57:24 +0800] "-" 408 - "-" "-"
192.168.128.131 - - [20/Jan/2019:10:00:46 +0800] "GET / HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
192.168.128.131 - - [20/Jan/2019:10:00:47 +0800] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
192.168.128.131 - - [20/Jan/2019:10:00:47 +0800] "GET / HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
192.168.128.131 - - [20/Jan/2019:10:00:48 +0800] "GET / HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"