秒杀购物商城业务服务-分布式架构介绍
- 基于MySQL数据库集群技术实现服务的高可用
- 基于Tomcat的集群负载机制实现Tomcat服务器的高可用
- 基于Nginx负载均衡机制实现负载均衡(介绍和配置)
- 基于Redis缓存服务实现数据缓存控制相关介绍和技术点分析
- 对未来的分布式技术架构扩展和延伸介绍(包含云原生部分)
基于MySQL数据库集群技术实现服务的高可用
高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用。对于一个系统而言,可能包含很多模块,比如前端应用,缓存,数据库,搜索,消息队列等,每个模块都需要做到高可用,才能保证整个系统的高可用。对于数据库服务而言,高可用可能更复杂,对用户的服务可用,不仅仅是能访问,还需要有正确性保证,因此数据库的高可用需要更加认证对待。
MySQL高可用架构分类
- MySQL实现高可用之MMM
- MySQL实现高可用之MHA
- MySQL实现高可用之主从架构
- MySQL实现高可用之Cluster模式
MMM的技术分析
MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。
MMM的基础组件分析
- mmm_mond:监控进程,负责所有的监控工作,决定和处理所有节点角色活动。因此,脚本需要在监管上运行。
- mmm_agentd:运行在每个msql服务器上的代理进程,完成监控的探针工作和执行简单的远端服务设置。此脚本需要在被监管机上运行。
- mmm_control:一个简单的脚本,提供管理mmm_mond进行的命令。
MMM实现基本实现原理
MMM提供了自动和手动两种方式移除一组服务器中复制延迟较高的服务器的虚拟ip,同时它还可以备份数据,实现两节点之间的数据同步等。
MySQL本身没有提供replication failover的解决方案,通过MMM方案能实现服务器的故障转移,从而实现mysql的高可用。
MHA简介
MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司的youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。
MHA的基础组件
MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。
MHA Manager可以单独部署在独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。
MHA的实现原理
- MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。
MySQL主从架构
此种架构,一般初创企业比较常用,也便于后面步步的扩展
此架构特点
- 成本低,布署快速、方便
- 读写分离
- 还能通过及时增加从库来减少读库压力
- 主库单点故障
- 数据一致性问题(同步延迟造成)
MySQL Cluster基本概念
MySQL Cluster简单地讲是一种MySQL集群的技术,是由一组计算机构成,每台计算机可以存放一个或者多个节点,其中包括MySQL服务器,DNB Cluster的数据节点,管理其他节点,以及专门的数据访问程序,这些节点组合在一起,就可以为应用提高可高性能、高可用性和可缩放性的Cluster数据管理;
基于Tomcat的集群负载机制实现Tomcat服务器的高可用
Tomcat集群原理
通过Nginx负载均衡进行请求转发
Tomcat集群能带来什么
- 提高服务的性能, 并发能力, 以及高可用性
- 提供项目架构的横向扩展能力
Tomcat集群产生什么问题
- Session登录信息存储以及读取的问题
- 服务器定时任务并发的问题
Tomcat 单服务体系架构
在这个架构图中,一层Nginx,首先Nginx主要职责给Tomcat一层反向代理。
此外,Nginx还可以FTPServer指定的目录再做一层目录转发,保证上传上去的图片实时可以通过http协议访问到。单服务架构先不用考虑集群碰到的各种问题
Tomcat集群"简单版"
比如,我们的登录的时候登录了A服务器,session信息存储到A服务器上了,假设我们使用的负载均衡策略是ip hash,那么登录信息还可以从A服务器上访问,但是这个有可能造成某些服务器压力过大,某些服务器又没有什么压力,这个时候压力过大的机器(包括网卡带宽)有可能成为瓶颈,并且请求不够分散。
首先要解决Session共享的问题
这时候我们使用轮询或者最小连接负载均衡策略,就导致了,第一次访问A服务器,第二次可能访问到B服务器,这个时候存储在A服务器上的session信息在B服务器上读取不到。
典型负载均衡策略分析
打个比方,我们有轮询,权重,地址散列,地址散列又分为原ip地址散列hash,目标ip地址散列hash,最少连接,加权最少连接,还有继续升级的很多种策略
- 轮询:优点:实现简单,缺点:不考虑每台服务器处理能力
- 权重:优点:考虑了服务器处理能力的不同
- 地址散列:优点:能实现同一个用户访问同一个服务器
- 最少连接:优点:使集群中各个服务器负载更加均匀
- 加权最少连接:在最少连接的基础上,为每台服务器加上权值。算法为(活动连接数*256+非活动连接数)/权重,计算出来的值小的服务器优先被选择。
Session管理-Session Sticky粘滞会话:
对于同一个连接中的数据包,负载均衡会将其转发至后端固定的服务器进行处理。
解决了我们session共享的问题,但是它有什么缺点呢?
- 一台服务器运行的服务挂掉,或者重启,上面的 session 都没了
- 负载均衡器成了有状态的机器,为以后实现容灾造成了羁绊
Session管理-Session 复制
就是每一个Tomcat都存储我们的Session,不同的tomcat之间进行拷贝复制。
解决了我们session共享的问题,但是它有什么缺点呢?
- 应用服务器间带宽问题,因为需要不断同步session数据
- 大量用户在线时,服务器占用内存过多
Session管理-基于Cookie
主要用于我们将session会话如同token一般存储在我们的前端
解决了我们session共享的问题,但是它有什么缺点呢?
- cookie 的长度限制
- cookie存于浏览器,安全性是一个问题
Session管理-Session 服务器
就是通过一个专门管理session会话的管理器服务,进行集中化存储和管理session
解决了我们session共享的问题,这种方案需要思考哪些问题呢?保证 session 服务器的可用性,session服务器单点如何解决?
- 我们在写应用时需要做调整存储session的业务逻辑
- 打个比方,我们为了提高session server的可用性,可以继续给session server做集群
Tomcat单机部署多应用
- 解压2个tomcat, 分别命名为tomcatA和tomcatB
- 分别设置2个tomcat的URIEncoding, 将tomcat的conf/server.xml里的port修改为两个不同端口。
设置tomcat的环境变量
tomcatA的环境变量和以往一样, 不做改变
设置tomcat的环境变量
sudo vim /ect/profile
在profile文件里新增
export CATALINA_BASE=/Users/tomcat/apache-tomcat-9.0.21 export CATALINA_HOME=/Users/tomcat/apache-tomcat-9.0.21 export TOMCAT_HOME=/Users/tomcat/apache-tomcat-9.0.21 复制代码
export CATALINA_2_BASE=/Users/tomcat/tomcat2 export CATALINA_2_HOME=/Users/tomcat/tomcat2 export TOMCAT_2_HOME=/Users/tomcat/tomcat2 复制代码
强制保存退出
继续配置tomcatB下的catalina.sh里的内容,
cd tomcat目录,在# OS specific support. $var must be set to either true or false.下加入。
sudo vi catalina.sh export CATALINA_BASE=$CATALINA_2_BASE export CATALINA_HOME=$CATALINA_2_HOME 复制代码
执行刷新环境变量
source /etc/profile
使环境变量生效, 执行
echo $CATALINA_2_BASE
如果有输出, 即环境变量已经生效
/Users/tomcat/tomcat2
分别进入两个tomcat下的bin目录启动tomcat, 正常即可
配置nginx
修改host
sudo vim /etc/hosts
所谓tomcat集群,就是可以向外提供并行服务的多台机器,任何一台服务器宕机,其它服务器可以替代它向外提供服务,而不影响用户访问。
nginx是一个常用的反向代理服务,可自定义模块,实现请求转发及负载均衡(根具体采用策略有关)。为了tomcat集群的高可用性,还需要实现nginx的双机热备。
一,如果仅是对外提供一个页面访问,不用区分单一用户(不区分每个访问session,不涉及用户权限,用户资料等内容),仅仅配置nginx负载均衡策略即可。
nginx负载均衡策略主要分一下四种:
1)、轮询(默认)每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器宕机,能自动剔除。
2)、ip_hash 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器。
3)、fair 按后端服务器的响应时间来分配请求,响应时间短的优先分配。
4)、url_hash 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
二,如果涉及到用户session,做一些鉴权缓存、存放临时信息时,就必须做tomcat的session共享。
目前可参考到的session共享方式主要分为两种。
1)利用tomcat自带的组播机制,实现session复制。
对tomcat及应用的若干配置文件进行配置即可实现,网上有很多资料可参考。但这种方式些弊端,看过一些资料,不建议用session复制的方式。在实际使用过程中,也发现有存在session莫名失踪的现象。
2)利用第三方机制存储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是什么?
Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev(伊戈尔·西索夫)所开发,供俄国大型的入口网站及搜索引擎Rambler(漫步者)(俄文:Рамблер)使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:新浪、网易、 腾讯等。
优点
- 可运行linux,并有 Windows移植版。
- 在高连接并发的情况下,Nginx是Apache服务器不错的替代品Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一。能够支持高达50,000个并发连接数的响应
负载均衡的功能
- 转发
- 故障移除
- 恢复添加
- 高可用 Ha
我们想要使用Nginx那么就必须满足上面的四个条件. 我们配置负载均衡的目的是在于当用户访问我们的服务器的时候, 首先会通过 Nginx服务器来决定转发到哪个Tomcat服务器上去给用户提供服务, 当然这个概率是我们通过权重来配置的. 经过Nginx指派之后, 我们就可以处理高并发的访问了, 这里就能达到负载均衡的目的.
Nginx如何实现负载均衡
Nginx的负载均衡是通过upstream来实现的,在upstream中指定若干个 server,格式如下:
myserver就是通过 upstream 定义的一组负载均衡模板,其中:
在配置完upstream后,还要让客户端过来的请求反向代理到myserver,格式如下:
完成了负载均衡的配置,但是在实际需求中除了上面的设置外,还会增加一些额外设置:
负载均衡策略设置请求上游服务器携带请求头信息upstream模块中其他参数设置
Nginx的负载均衡策略有5种方式:
除以上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; } } } 复制代码
最少连接负载均衡
- 另一个负载均衡原则为least-connected。当一些请求花费较长时间来完成时,least-connected更“公平”的控制应用程序实例上的负载。
- 配置了least-connected的负载均衡机制的情况下,nginx会尽量不让负载繁忙的应用服务器上负载过多的请求,相反的,会把新的请求发送到比较不繁忙的服务器。
配置示例:
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机制下,客户端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机制下的权重设置
健康检测
- nginx反向代理实现包含服务器健康检查。如果来自特定服务器的响应失败,报错,nginx将标记该服务器为failed,一段时间内尽量避免选择此服务器作为随后请求的分发服务器。
- max_fails机制设置fail_timeout期间,和服务器沟通失败的连续重试次数,默认为1.当设置为0时,不做服务器健康检测。fail_timeout定义了服务器被标记为failed的时长。fail_timeout时间间隔过后,nginx将开始使用活动客户端请求来探测服务器,如果探测成功则标记服务器为活动服务器。
Nginx负载均衡配置项介绍
下面我们将介绍一下proxy模块的参数:
各个参数介绍:
设置proxy_connect_timeout 为2秒,缩短超时时间,使其不至于太慢。