高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用。对于一个系统而言,可能包含很多模块,比如前端应用,缓存,数据库,搜索,消息队列等,每个模块都需要做到高可用,才能保证整个系统的高可用。对于数据库服务而言,高可用可能更复杂,对用户的服务可用,不仅仅是能访问,还需要有正确性保证,因此数据库的高可用需要更加认证对待。
MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。
MMM提供了自动和手动两种方式移除一组服务器中复制延迟较高的服务器的虚拟ip,同时它还可以备份数据,实现两节点之间的数据同步等。
(相关资料图)
MySQL本身没有提供replication failover的解决方案,通过MMM方案能实现服务器的故障转移,从而实现mysql的高可用。
MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司的youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。
MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。
MHA Manager可以单独部署在独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。
此种架构,一般初创企业比较常用,也便于后面步步的扩展
MySQL Cluster简单地讲是一种MySQL集群的技术,是由一组计算机构成,每台计算机可以存放一个或者多个节点,其中包括MySQL服务器,DNB Cluster的数据节点,管理其他节点,以及专门的数据访问程序,这些节点组合在一起,就可以为应用提高可高性能、高可用性和可缩放性的Cluster数据管理;
通过Nginx负载均衡进行请求转发
在这个架构图中,一层Nginx,首先Nginx主要职责给Tomcat一层反向代理。
此外,Nginx还可以FTPServer指定的目录再做一层目录转发,保证上传上去的图片实时可以通过http协议访问到。单服务架构先不用考虑集群碰到的各种问题
比如,我们的登录的时候登录了A服务器,session信息存储到A服务器上了,假设我们使用的负载均衡策略是ip hash,那么登录信息还可以从A服务器上访问,但是这个有可能造成某些服务器压力过大,某些服务器又没有什么压力,这个时候压力过大的机器(包括网卡带宽)有可能成为瓶颈,并且请求不够分散。
这时候我们使用轮询或者最小连接负载均衡策略,就导致了,第一次访问A服务器,第二次可能访问到B服务器,这个时候存储在A服务器上的session信息在B服务器上读取不到。
打个比方,我们有轮询,权重,地址散列,地址散列又分为原ip地址散列hash,目标ip地址散列hash,最少连接,加权最少连接,还有继续升级的很多种策略
轮询:优点:实现简单,缺点:不考虑每台服务器处理能力权重:优点:考虑了服务器处理能力的不同地址散列:优点:能实现同一个用户访问同一个服务器最少连接:优点:使集群中各个服务器负载更加均匀加权最少连接:在最少连接的基础上,为每台服务器加上权值。算法为(活动连接数*256+非活动连接数)/权重,计算出来的值小的服务器优先被选择。对于同一个连接中的数据包,负载均衡会将其转发至后端固定的服务器进行处理。
解决了我们session共享的问题,但是它有什么缺点呢?
一台服务器运行的服务挂掉,或者重启,上面的 session 都没了负载均衡器成了有状态的机器,为以后实现容灾造成了羁绊就是每一个Tomcat都存储我们的Session,不同的tomcat之间进行拷贝复制。
解决了我们session共享的问题,但是它有什么缺点呢?
应用服务器间带宽问题,因为需要不断同步session数据大量用户在线时,服务器占用内存过多主要用于我们将session会话如同token一般存储在我们的前端
解决了我们session共享的问题,但是它有什么缺点呢?
cookie 的长度限制cookie存于浏览器,安全性是一个问题就是通过一个专门管理session会话的管理器服务,进行集中化存储和管理session
解决了我们session共享的问题,这种方案需要思考哪些问题呢?保证 session 服务器的可用性,session服务器单点如何解决?
我们在写应用时需要做调整存储session的业务逻辑打个比方,我们为了提高session server的可用性,可以继续给session server做集群tomcatA的环境变量和以往一样, 不做改变
sudo vim /ect/profile
export CATALINA_BASE=/Users/tomcat/apache-tomcat-9.0.21export CATALINA_HOME=/Users/tomcat/apache-tomcat-9.0.21export TOMCAT_HOME=/Users/tomcat/apache-tomcat-9.0.21
export CATALINA_2_BASE=/Users/tomcat/tomcat2export CATALINA_2_HOME=/Users/tomcat/tomcat2export TOMCAT_2_HOME=/Users/tomcat/tomcat2
继续配置tomcatB下的catalina.sh里的内容,
cd tomcat目录,在# OS specific support. $var mustbe set to either true or false.下加入。
sudo vi catalina.shexport CATALINA_BASE=$CATALINA_2_BASEexport CATALINA_HOME=$CATALINA_2_HOME
source /etc/profile
使环境变量生效, 执行
echo $CATALINA_2_BASE
如果有输出, 即环境变量已经生效
/Users/tomcat/tomcat2
分别进入两个tomcat下的bin目录启动tomcat, 正常即可
sudo vim /etc/hosts
所谓tomcat集群,就是可以向外提供并行服务的多台机器,任何一台服务器宕机,其它服务器可以替代它向外提供服务,而不影响用户访问。
nginx是一个常用的反向代理服务,可自定义模块,实现请求转发及负载均衡(根具体采用策略有关)。为了tomcat集群的高可用性,还需要实现nginx的双机热备。
一,如果仅是对外提供一个页面访问,不用区分单一用户(不区分每个访问session,不涉及用户权限,用户资料等内容),仅仅配置nginx负载均衡策略即可。
二,如果涉及到用户session,做一些鉴权缓存、存放临时信息时,就必须做tomcat的session共享。
目前可参考到的session共享方式主要分为两种。
对tomcat及应用的若干配置文件进行配置即可实现,网上有很多资料可参考。但这种方式些弊端,看过一些资料,不建议用session复制的方式。在实际使用过程中,也发现有存在session莫名失踪的现象。
比较常见的是tomcat集成memcached服务器来存储session。实际项目中,我们采用过利用redis实现session存储,redis高效的存取性能为高效的访问提供了保障,但是目前redis的集群功能似乎没有发布,如何解决redis的单点故障需要研究。
小结:是否实现session共享与nginx的负载策略有很大关系。比如采用轮询策略,就必须实现session共享,因为客户端会访问到每台服务器;而如果采用ip_hash策略,就可以不用考虑session共享的问题了,但是ip_hash有些缺陷使它不能随便使用(如多台pc使用同一个外网ip)。
最近发现一个nginx的粘连模块(类似session粘连),可以看做nginx的第5种均衡策略。它利用客户端cookie,对其写入一个route参数,每次访问可以根据route的值,固定的访问一台服务器,解决的session共享的问题。
Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev(伊戈尔·西索夫)所开发,供俄国大型的入口网站及搜索引擎Rambler(漫步者)(俄文:Рамблер)使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:新浪、网易、 腾讯等。
我们想要使用Nginx那么就必须满足上面的四个条件.我们配置负载均衡的目的是在于当用户访问我们的服务器的时候, 首先会通过 Nginx服务器来决定转发到哪个Tomcat服务器上去给用户提供服务, 当然这个概率是我们通过权重来配置的. 经过Nginx指派之后, 我们就可以处理高并发的访问了, 这里就能达到负载均衡的目的.
Nginx的负载均衡是通过upstream来实现的,在upstream中指定若干个 server,格式如下:
myserver就是通过 upstream 定义的一组负载均衡模板,其中:
在配置完upstream后,还要让客户端过来的请求反向代理到myserver,格式如下:
完成了负载均衡的配置,但是在实际需求中除了上面的设置外,还会增加一些额外设置:
负载均衡策略设置请求上游服务器携带请求头信息upstream模块中其他参数设置
除以上5种,还有一种:least-connected — 下一个请求被分配到拥有最少活动连接数的服务器。
编辑nginx配置文件(例中为/usr/local/ngnix/conf/nginx.conf),找到http结点,
http { upstream myapp1 { server 192.168.1.103:8080; server 192.168.1.104:8080; } server { listen 80; server_name localhost; location /webautotest/ { proxy_buffering off; proxy_pass http://myapp1; } }}
[root@localhost nginx-1.10.0]# /usr/local/ngnix/sbin/nginx -s reload
http { upstream myapp1 { server srv1.example.com; server srv2.example.com; server srv3.example.com; } server { listen 80; location / { proxy_pass http://myapp1; } }}
upstream myapp1 { least_conn; server srv1.example.com; server srv2.example.com; server srv3.example.com;}
注意,round-robin或least-connected负载均衡下,每个后续的客户端可能被分发至不同服务器,不保证相同客户端的请求总是被发送到相同的服务器。
如果有必要把客户端绑定至特定服务器,则可使用ip-hash负载均衡机制。
ip-hash机制下,客户端ip地址被用作hash key来判断客户端请求应该发送到哪个服务器,这种方法保证了来自相同客户端的请求总是发送到相同服务器(如果服务器可用的话)
upstream myapp1 { ip_hash; server srv1.example.com; server srv2.example.com; server srv3.example.com;}
可通过配置服务器权重来影响负载均衡机制。上面的例子中,都未配置服务器权重,这意味着所有服务器都拥有相同的权重。针对round-robin负载机制,权重意味着更多或更少的请求传送至服务器---假设有足够的请求,且按统一方式处理请求,且足够快完成请求处理。
upstream myapp1 { server srv1.example.com weight=3; server srv2.example.com; server srv3.example.com;}
上例配置中,每发送至服务器实例的5个新的请求中,有3个发送到srv1,1个发送到srv2,另1个发送到srv3。
注:当前版本似乎只实现了round-robin机制下的权重设置
下面我们将介绍一下proxy模块的参数:
设置proxy_connect_timeout 为2秒,缩短超时时间,使其不至于太慢。