高可用系列文章之一 - 概述 - 东风微鸣技术博客 (ewhisper.cn)
单点是系统高可用最大的风险和敌人,应该尽量在系统设计的过程中避免单点。
保障系统的高可用, 方法论上,高可用保证的原则是「集群化」(或 「冗余」), 只有一个单点,该单点宕机所有服务都会受影响而不可用;如果有冗余或备份,其中一个点宕机还有其他冗余或备份节点能够提供服务。
保证系统高可用,架构设计的核心准则是:冗余。
有了冗余之后,还不够,每次出现故障需要人工介入恢复势必会增加系统的 MTTR。所以,又往往是通过「自动故障转移」来实现系统的高可用。
在下面的技术方案中,详细介绍了如何通过冗余+自动故障转移来保证系统的高可用特性。
制造业系统一般采用分层架构, 最简单的典型架构的展示如下:
ℹ️ 备注:
数据库以 MySQL 为例.
常见的系统架构如上, 分为:
整个系统的高可用, 是通过对每一层的冗余+自动故障转移来综合实现的.
ℹ️ 备注:
通过更加细化和细致的分层, 也可以提高可用性. 如将以上架构细化为:
- 客户端层;
- 可选新增: 反向代理层
- 可选新增: 表示层(Web Server)层
- 应用服务层(App Server)层
- 可选新增: 服务调用层
- 可选新增: 缓存层
- 数据库层
本文暂不涉及这一内容.
通过冗余这一核心原则, 优化后的高可用架构如下图所示:
ℹ️ 说明:
- 实线 : 请求调用
- 点+横线: 心跳检测
- 点虚线: 尚未真实发生的请求调用
- 短横虚线: 数据库主从同步
- "X" - 对应节点宕机不可用.
高可用方案调整说明如下:
ℹ️ 备注:
上图中, 也画出了高可用的另一种实施方案, 本文不做详细讨论:
- 应用横向拆分: 单体应用(monolithic application)根据重要性进行拆分, 将重要性高的服务和重要性低的服务进行拆分, 单独部署.
- 重要性高的应用, 如低延迟类应用, 流水线上应用等;
- 重要性低的应用, 如高延迟类应用, 报表应用等.
除此之外, 还可以根据实际业务情况进一步将数据库进行拆分, 本文亦不做详细讨论:
- 数据库拆为 2 个库, 其中一个库通过数据同步从另一个库定时(实时或非实时)同步数据. 举例说明: 业务库, 报表库. (业务库定期同步数据给报表库)
- 重要性高的应用, 读取写入业务库;
- 重要性低的应用. 如报表类应用. 不允许使用业务库, 而是使用报表库.
下面逐一进行分层论述.
客户端层 到 负载均衡层 高可用, 通过负载均衡层的冗余来实现的. 具体实现方式如下:
至少有 2 台 nginx, 其中一台提供服务, 另一台冗余以保证高可用. 并通过 Keepalived 的 virtual IP 来提供同一 IP(如上图为: 1.2.5.6), 通过心跳探测来进行故障检测和故障转移.
在上图中, NGINX 主节点提供对外服务.
当 NGINX 主节点(如: 192.168.0.1)发生宕机, Keepalived 能够探测到, 会自动进行故障转移, 将流量自动转移到 NGINX 从节点(如: 192.168.0.2). 由于使用的是相同的 virtual IP(仍为: 1.2.5.6), 这个切换过程对调用方是透明的.
负载均衡层 到 应用服务层 的高可用, 是通过应用服务层的冗余来实现的. 在NGINX的配置文件 nginx.conf
中, 可以通过 upstream
指令配置多个应用服务器, 并且 nginx 能够探测到多个应用服务器的存活性.
ℹ️ 知识点:
在 NGINX 开源版本中, 如果不使用第三方插件,NGINX 的存活探测为: 被动探测.
当应用服务层 其中一个节点宕机的时候, nginx 能够探测到, 会自动进行故障转移, 不会将流量分发到发生故障的节点, 而是分发到其他的正常应用服务器节点, 整个过程由 NGINX 自动完成, 对调用方透明.
数据库层建议采用「主从同步, 读写分离」架构. 数据库的高可用, 又可细分为: 「读库高可用」 和「写库高可用」 两类.
ℹ️ 备注:
由于制造业采用了多种数据库, 包括但不限于:
- Oracle
- SQL Server
- MySQL
不同数据库的高可用解决方案并不完全相同, 所以本文不对数据库的具体高可用技术做细节描述. 只进行理论论述.(以 MySQL 为例)
常见的数据库高可用方案有:
- MySQL: 主从同步;
- Oracle: RAC
- SQL Server: Alwayon
读库高可用, 是通过读库的冗余来实现的.
如果要对读库实现高可用, 一般来说至少有 2 个从库, 数据库连接池会建立与读库的多个连接, 每次请求会路由到这些读库.
当读库 - 从1发生宕机的时候, 应用服务层的数据库连接池能够探测到, 会自动的进行故障转移, 将流量自动迁移到其他的读库, 如读库 - 从2, 整个过程由数据库连接池自动完成, 对调用方是透明的.
ℹ️ 备注:
需要应用系统或中间件的数据库连接层实现数据库连接池功能.
写库的高可用, 是通过写库的冗余来实现的.
以 MySQL 为例, 可以设置两个 MySQL 双主同步, 一台对线上提供服务, 另一台冗余以保证高可用.
✔️ 选型结果:
ℹ️ 定义及概述:
在分布式系统中,负载均衡(load balance)是一种有效的将网络请求分配到多个服务器的过程。通过将负载进行负载均衡,可以有效地改进系统响应时间,提高系统的可用性。随着系统变的愈发复杂,用户增多和网络流量增大,负载均衡已经成为系统设计中的必要一环。
负载均衡器可以是硬件也可以是软件,它会将网络请求分发到服务器集群上。
常见的硬件负载均衡器包括:
常见的软件负载均衡器包括:
结合制造行业最佳实践, 以及制造业的实际情况考虑, 制造业在全国乃至全球拥有多座工厂, 每个工厂拥有独立的机房. 采用硬件负载均衡成本过高. 确定采用软件负载均衡器作为负载均衡技术实现. 下面对软件负载均衡器逐一进行论述:
NGINX:
Nginx("engine x")是一款是由俄罗斯的程序设计师 Igor Sysoev 所开发高性能的 Web 和 反向代理 服务器.
优点:
缺点:
ip_hash
实现源地址会话保持, 且可以通过第三方模块实现cookie会话保持.LVS:
LVS:使用 Linux 内核集群实现一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。
优点:
缺点:
HAProxy:
HAProxy 是一个使用 C 语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于 TCP 和 HTTP 的应用程序代理。
优点:
缺点:
选型结论:
LVS 试用场景单一, 且存在硬伤(即: 后面有Windows Server的机器的话, 实施比较复杂). 直接排除.
HAPorxy 针对 HTTP 的支持没有 NGINX 丰富, 且重启中断相对 NGINX 时间更长.
另外, nginx 除了当前可以用作负载均衡器之外, 还可以用作 web server, http 缓存等场景, 且容易上手.
最终确定选择 NGINX 作为某制造业公司负载均衡器.
NGINX 高可用技术方案只有一种, 即: NGINX + Keepalived 实现高可用.
keepalived
开源项目包括三个组成部分:
keepalived
Linux服务器的守护程序。
虚拟路由器冗余协议(VRRP)的实现,用于管理虚拟路由器(虚拟 IP 地址或 VIP)。
VRRP 确保始终存在一个主节点。备用节点侦听来自主节点的 VRRP 通告包。如果在超过配置的广播间隔的三倍的时间内未收到广播包,则备用节点将作为主节点接管,并将配置的 VIP 分配给自己。
一种运行状况检查工具,用于确定服务(例如,Web 服务器,PHP 后端或数据库服务器)是否已启动并且可以运行。
如果节点上的服务未通过配置的运行状况检查次数,keepalived
则将虚拟 IP 地址从主(主动)节点重新分配给备用(被动)节点。
✔️选型结果:
负载均衡策略: RR(轮询, 默认策略)
会话保持策略: (非必须)
ip_hash
NGINX负载均衡策略:
least_conn
.ip_hash
hash
- 指定服务器组的负载均衡方法,其中客户机-服务器映射基于hash 值。key可以包含文本、变量及其组合。选型过程:
负载均衡策略,根据实际情况按需选择,无特殊要求的情况下选择 rr 即可。
会话保持策略, 需要根据特定的场景进行选择:
ip_hash
cookie
会话保持: sticky
cookie
会话保持均无法满足需求, 则可能需要通过 hash
来定制会话保持策略.略.
由于应用系统的多样性, 本文不对应用服务层 -> 数据库层高可用选型做约束. 仅提供顶层架构要求:
参考文件 |
---|
Availability - Wikipedia |
High Availability - Wikipedia |
system-design-primer - GitHub |
High Availability Support for NGINX |
Usage of web servers broken down by ranking |
三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.