亚马逊AWS官方博客

使用 Amazon RDS Proxy 提升应用程序可用性

Original Link: https://amazonaws-china.com/cn/blogs/database/improving-application-availability-with-amazon-rds-proxy/

Amazon RDS Proxy 的最大优势,在于显著缩短数据库故障转移之后的应用程序恢复时间。RDS Proxy能够同时支持MySQL与PostgreSQL引擎,但在本文中,我们将单纯使用MySQL测试工作负载向大家展示RDS Proxy如何在故障转移之后,将Amazon Aurora MySQL客户端的恢复时间缩短达79%,并将Amazon RDS for MySQL的故障恢复时间缩短达32%。本文还将阐述RDS Proxy如何帮助客户端摆脱读取器终端节点-写入器终端节点转换问题,同时克服客户端配置中的优化不充分状况。接下来,我们将讨论在故障转移期间闲置连接保留机制的支持下,RDS Proxy如何通过活动连接监控与客户端连接池机制带来更出色的计划内与计划外故障转移效果。最后,本文还将与大家分享一些关于客户端配置的最佳实践。

背景

RDS Proxy可以被放置在Amazon RDS for MySQL/PostgreSQL以及Aurora MySQL/PostgreSQL数据库之前。它将帮助用户管理应用程序对数据库的访问,同时提供连接池、多路复用以及良好的故障转移功能。除了进一步扩展数据库的连接限制之外,RDS Proxy还能够管理应用程序的突发连接与请求。本文将着重介绍RDS Proxy在故障转移层面的优势。

所谓故障转移,就是当主数据库实例无法正常访问时,由另一实例接管并提升为新的主实例的过程。故障转移会断开客户端连接。对于由管理操作(例如滚动升级)引发的故障转移,我们将其称为计划内故障转移;而由于真实故障引发的故障转移,则属于计划外故障转移。无论如何,我们都需要尽可能缩短停机时间以最大程度减少客户端中断造成的影响。

Amazon RDS提供多个高可用性选项,RDS Proxy则为各个选项提供故障转移恢复支持。Amazon RDS多可用区选项能够在主配置与辅助配置之间实现同步复制。Aurora则提供两种高可用性选项,最多支持15个异步副本、以及多主模式。全部Aurora副本都处于只读访问模式,大家可以选定其中的任何一个副本节点并将其提升为集群的新主节点,而无需担心引发数据丢失。Aurora多主模式则可提供多条活动写入通道。

配合这些选项,在发生故障转移时,客户端需要首先检测连接故障、发现新的主节点,并尽快与其重新连接。在RDS Proxy的协助下,应用程序能够摆脱与故障转移相关的复杂性因素,从而实现更快的恢复速度(仅需3秒)。Aurora中的故障转移机制速度更快,其中DNS的传播延迟就成了影响整体故障转移时间的核心因素。RDS Proxy会主动监控数据库实例,并自动将客户端接入正确的目标。此外,它还会在数据库故障转移期间继续保留闲置的客户端连接(而非将其丢弃)。所谓闲置连接,是指那些不包含重要请求的连接。

Aurora故障转移

经过 100次内部测试执行之后,我们将Aurora集群直连模式与通过RDS Proxy建立的Aurora集群代理模式进行了故障转移时间比较。

下表对结果进行了总结,单位为毫秒:

测试 最小 最大 平均 代理优势
RDS Proxy配合Aurora 1667 15511 3138 87%
使用MariaDB 驱动程序进行Aurora直连 9720 31491 24037

使用RDS Proxy时的平均故障转移时长为3.1秒,使用MariaDB驱动程序进行数据库直连的平均故障转移时长则高达24秒。改进幅度高达87%。

对于关系数据库来说,即使只是最基础的基准测试,只需3秒的故障转移速度也着实令人惊叹。而这一切,都是Aurora努力创新的成果。但显而易见的是,即使是以往表现最佳的MariaDB Aurora驱动程序(其中针对故障转移进行了优化)也不足以发挥Aurora的所有优势。只有配合RDS Proxy,我们才能真正让Aurora MySQL的故障转移变得迅如闪电,突破驱动程序本身对于数据库恢复速度的限制。

DNS生存时间

大家可以采用多种不同方式调整客户端驱动程序。例如,MariaDB ConnectorJ驱动程序就提供近100种配置选项。操作系统、JVM以及连接池框架中还包含更多配置选项。本文将只讨论其中最重要的部分,首先自然是DNS客户端缓存配置。

在客户端使用DNS名称接入数据库时,首先需要通过查询DNS服务器将该名称解析为IP地址。客户端随后会将响应结果保存在缓存当中。根据协议,DNS响应结果中指定了生存时间(TTL),即控制客户端将该记录缓存多长时间。RDS中的TTL设置默认为4秒,但各类系统往往会在客户端缓存中使用不同的设置,进一步延长TTL。操作系统与JVM运行时环境都存在这样的缓存机制。JVM中的缓存设置因版本与操作系统而异,因此我们需要做出明确的设定。以下代码所示,为建议设定值:

java.security.Security.setProperty("networkaddress.cache.ttl" , "1");

java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "1");

这就缩短了JVM中的默认DNS缓存生存时间,使驱动程序能够在故障转移期间更快发现DNS名称IP地址的变更。

配合客户端优化的故障转移基准

在下一项基准测试中,我们将使用经过DNS TL设置优化的客户端(如前所述)以及本文稍后将谈到的其他推荐客户端设置。在下图中,我们比较了使用最佳设置的MariaDB驱动程序与通过RDS Proxy接入Aurora MySQL时的故障转移时间差异。

下表对测试结果做出汇总,单位为毫秒。

测试 最小 最大 平均 代理优势
代理Aurora (Maria驱动程序) 1644 11642 2913 79%
直连Aurora (Maria Aurora 驱动程序) 5146 30782 13783

使用精心调优的MariaDB客户端,配合RDS Proxy时的平均故障转移时间为2.9秒,而直连的平均故障转移时间为13.8秒——RDS Proxy的改进幅度为79%。请注意,具体恢复时间还与实际工作负载密切相关。

Aurora客户端配置

在之前的测试中,我们使用了针对Aurora做出增强优化的MariaDB COnnectorJ。具体来讲,指向该数据库的直接连接使用以jdbc:mariadb:aurora://<cluster-endpoint>开头的连接URL。如此一来,MariaDB COnnectorJ驱动程序就能够使用Aurora中的专用系统标签快速发现主数据库实例。关于更多详细信息,请参阅《在兼容MySQL的Amazon Aurora中使用Maria JDBC驱动程序》。

通过RDS Proxy的连接则使用常规驱动程序,其中的URL为jdbc:mariadb://<proxy-endpoint>形式。尽管未使用任何特殊的客户端配置,但RDS Proxy仍然取得了更好的故障转移时间成绩。更重要的是,其中的客户端逻辑更加简单,因此RDS Proxy将具有更好的普适性。

读取器与写入器角色转换

一旦主实例出于某些原因而不再可用,Aurora会自动执行故障转移。在故障转移期间,主实例会由写入器角色转换为读取器角色;与此同时,Aurora集群中的某读取器节点将被提升为主实例。如果直连集群端点,由于DNS记录可能被缓存,因此客户端仍可能继续接入旧的主实例。这时,即使建立起连接,由于旧的主实例角色已经发生变化(转换为只读实例),客户端将无法正常执行写入操作。RDS Proxy能够消除此类错误,保证客户端永远只接入当前的主实例。

主动监控与计划外故障转移

RDS Proxy并不依赖DNS传播来执行故障转移,因此能够改善整个转移效果。RDS Proxy彻底消除了之前提到的Aurora集群客户端读取器-写入器角色转换的问题。它能够主动监控Aurora数据库集群中的各个数据库实例,并在故障转移期间快速调整客户端的操作方式。

到目前为止,本文所涉及的都只是计划内/管理性故障转移场景。对于Aurora,我们可以通过AWS管理控制台、API或者AWS命令行界面(AWS CLI)根据需求调整实例大小,Amazon也可能根据用户指定的维护计划执行集群调整,由这类操作带来的都属于计划内故障转移。在这类情况下,在数据库进程未准备就绪时,数据库主机将正常关闭连接并拒绝创建新的连接。这意味着客户端或RDS Proxy能够轻松检测到问题,并稍后执行重试。

但在计划外故障转移的场景下,主机会毫无征兆地突然失去可访问性。现有客户端TCP连接仍然处于开启状态,而客户端检测到当前连接因收不到响应而造成死信。要应对这类情况,我们需要遵循以下最佳实践,包括配置套接字超时、连接超时以及TCP继续活动等。RDS Proxy也可以协助客户端顺利应对这类计划外故障转移。

RDS Proxy会监控每个数据库实例,并在几秒钟之内检测到故障。一旦发现故障,RDS Proxy将停止将新查询定向至存在故障的数据库实例。在故障转移期间,RDS Proxy还会保留各闲置客户端连接,意味着存在非活动连接的客户端连接池也能够更轻松地处理故障转移,而无需重新创建每一条连接。如此一来,客户端将节约下重建闲置TLS连接所带来的开销。另外,RDS Proxy还能够主动终止故障数据库实例中那些未执行完毕的事务,帮助客户端快速重试(而不必等待超时)。

RDS Proxy始终接受新连接,并会延后转发查询,直到新的主实例恢复可用为止。如果没有RDS Proxy,一旦发生故障转移,客户端只会检测到主数据库实例不可用,并可能立即尝试重新连接。由于主数据库仍在恢复当中,这些重连尝试往往不会成功。而一旦重新连接次数过多,主实例的恢复很可能因此而再次崩溃。结果就是,客户端的重试逻辑反而加重了故障的严重程度。但在RDS Proxy的加持下,我们根本不需要建立这种复杂的重试逻辑。

Amazon RDS多可用区模式

Amazon RDS的多可用区模式,是一项有助于缓解计划外故障转移影响的重要功能。使用RDS MySQL中的多可用区配置时,主数据库实例将位于某一可用区内,而同步备用实例则位于其他可用区。此时,客户端应用程序将使用某项主机名称指向数据库的主实例。一旦发生故障,RDS服务将切换主实例与辅助实例之间的角色。此外,RDS服务还将变更数据库主机名称的基础IP地址,确保客户端应用程序无需变更自身连接设置即可在故障转移期间直接接入新的主数据库实例。

使用Amazon RDS多可用区模式,原始主实例在故障转移期间不再需要关闭其TCP连接。故障转移开始后,客户端将不再从数据库处获取更多TCP流量,而是由客户端自主判断是否超时。这种精心设计的原始主数据库实例硬防护机制,意味着客户端能够随时从容应对计划内与计划外故障转移。这样做的最大好处在于,只需要通过Amazon RDS API或CLI进行管理性故障转移,即可轻松对现有系统的计划内与计划外故障转移效果做出测试。但需要注意的是,MariaDB驱动程序以及多数操作系统中的默认设置并不能够很好地配合多可用区模式。在默认情况下,MariaDB驱动程序永远不会将响应等待判定为超时,而某些操作系统的TCP活动保持周期可能超过2个小时。但好消息是,RDS Proxy将彻底消除这些设置,现在主机名称的基础DNS配置(在本示例为中RDS Proxy)将永远不会变更。

RDS多可用区故障转移恢复基准

以下结果,为使用MariaDB驱动程序直连数据库与通过RDS Proxy连接时,对50次故障转移的测试结果。表内各项数值的单位为毫秒。

测试 最小 最大 平均 代理优势
代理多可用区(Maria驱动程序) 21485 29176 25075 32%
直连多可用区(Maria驱动程序) 27240 52234 36849

总之,将RDS Proxy与Amazon RDS多可用区数据库配合使用,平均故障转移周期约为25秒;而数据库直连模式的停机时间则在37秒到40秒之间。

而且与Amazon RDS多可用区的25秒恢复时间相比,Aurora在db.r5.large实例上的恢复时间甚至可以做到3秒以内。这主要是因为Aurora当中包含多项创新功能,可在故障转移之后加快数据库的恢复时间。

总结

本文向大家介绍了RDS Proxy的以下几项核心优势:

  • 在测试工作负载中,将Aurora MySQL的故障转移时间缩短达79%。
  • 在测试工作负载中,将RDS MySQL多可用区的故障转移时间缩短达32%。
  • 无需特殊的客户端逻辑,能够与多种不同客户端驱动程序良好对接。
  • 将客户端与Aurora集群中的读取方-写入方角色转换隔离开来。
  • 主动监控各数据库,包括计划外故障转移迹象。
  • 在故障转移期间不丢弃闲置连接,从而减少对客户端连接池的影响。
  • 始终接受连接,使客户端免受连接超时的影响。

RDS Proxy也非常易于上手。大家可以将任何MySQL或者PostgreSQL客户端驱动程序与RDS Proxy端点相对接,并立即享受由其带来的便利。欢迎大家马上开始体验RDS Proxy!

 

关于作者

Anton Okmyanskiy,Amazon Web Services公司首席工程师。

Steve Abraham ,Amazon Web Services公司首席数据架构师。他与我们的客户一道为各类数据库项目提供指导与技术支持,帮助项目方在AWS服务的帮助下提高解决方案价值。