一个最小化的高可用架构是怎么样的

160 阅读5分钟

一、引言

在当今数字化的时代,系统的高可用性变得至关重要。无论是企业级的应用还是互联网服务,一旦系统出现故障,都可能导致巨大的经济损失和不良的社会影响。高可用架构一定非常非常复杂么,如何在用较低的成本搭建一个最小化的高可用架构呢?

二、简单的应用架构及其缺陷

最初的架构设计往往追求简单性和快速实现。一个典型的应用架构可能包括以下几个组件:

  1. 网关

作为系统的入口,负责接收外部请求并进行初步的路由和转发。

  1. 应用服务

实现业务逻辑的核心部分,处理具体的业务请求。

  1. 注册中心

用于服务的注册与发现,帮助各个组件之间进行通信。

  1. 数据库

存储系统的核心数据,为应用服务提供数据支持。

image.png

然而,这种简单的架构存在一个致命的缺陷——单点故障。无论是网关、应用服务、注册中心还是数据库,任何一个环节出现问题,整个系统都将不可用。这种架构在小型应用或测试环境中可能尚可接受,但对于生产环境和大型系统来说,显然是不可靠的。

三、高可用架构的目标与方向

高可用架构的目标是尽量提高系统的可用时间。通常我们用可用性百分比来衡量系统的可用性,例如99.99%的可用性意味着在一年内系统至少有99.99%的时间是可用的。为了实现这一目标,可以从两个主要方向入手:

1. 提高单节点的稳定性

通过提高代码质量、使用合理的配置、提高基础资源稳定性等方法,降低单个节点的故障率。这是提高系统可用性的基础,但仅靠这一点是不够的,因为无论单节点的稳定性多高,仍然存在故障的可能性。

2. 冗余备份

采用冗余备份的思想,将单节点扩充为多个节点。如果一个节点出现故障,其余节点可以继续工作,从而保证系统的可用性。这种冗余设计是高可用架构的关键,但也会带来新的问题,如节点之间的通信和协调问题。

image.png

四、引入代理层解决多节点通信问题

将节点扩充后,需要解决两个迫切的问题:一是如何自动发现故障并进行转移,二是多节点组成的层与层之间如何连接

软件工程中有一个法则:几乎所有的问题都可以通过抽象一层来解决。

因此,我们可以在层与层之间引入一个代理层。

image.png

1. 代理层的作用

代理层与节点之间定时进行心跳包交互,及时发现故障节点,并实现故障的自动转移。层与层之间的通信通过代理层进行,从而解决了多节点之间的连接问题。

2. 代理层的实现

代理层可以采用多种技术实现,如负载均衡器、反向代理服务器等。这些技术可以有效地分配流量,实现节点之间的负载均衡,同时也可以进行健康检查,及时发现故障节点并将其从可用节点列表中移除。

五、解决代理层的单点问题

引入代理层后,细心的读者肯定又发现了问题,代理层又出现了单点的问题!这个要如何解决呢,难道我们在代理层冗余多个节点,并在代理层之上再套一层代理么,这样不是层层套娃,永远无法解决问题了么。有没有一种方法可以不需要引入代理层,就可以实现层与层之间通讯呢?

还真有,Linux原生提供了两种方案支持:

1. DNS轮询

在Linux的网络层面,DNS轮询是一种简单而有效的解决方案。通过配置DNS服务器,将多个节点的IP地址关联到同一个域名。当客户端请求该域名时,DNS服务器会按照一定的策略(如轮询)返回一个可用的IP地址。这样,即使某个节点出现故障,客户端仍然可以通过其他节点访问系统。

比如将”www.test.com”这个域名绑定到多个代理节点192.168.0.2和192.168.0.3中,这样可以实现通过一个域名访问多个节点。

DNS方案有个最大的缺陷:DNS无法感知节点是否正常,如果其中一个节点挂了,DNS还是会按照轮询的方式发送消息,这样就会导致一半的交易无法收到返回。

 

2. 虚拟IP

虚拟IP是另一种常用的解决方案。通过配置虚拟IP,将多个节点绑定到同一个虚拟IP地址。当某个节点出现故障时,虚拟IP会自动转移到其他可用节点上。这样,客户端始终通过虚拟IP访问系统,而无需关心具体的节点IP地址。典型解决方案: nginx+keepalived,后续我会详细演示如何关于使用keepalived的高可用方案。

 

六、总结

通过以上分析,我们可以看到,构建一个最小化的高可用架构需要综合考虑多个方面。从简单的应用架构出发,识别单点故障并采取冗余备份的策略,引入代理层解决多节点通信问题,最后通过DNS轮询或虚拟IP解决代理层的单点问题。这些方法和技术共同构成了一个高可用的系统架构,为系统的稳定性和可靠性提供了有力的保障。在实际的架构设计中,还需要根据具体的需求和场景,灵活选择和组合这些方法,以实现最优的高可用效果。