在你的Python应用程序中测试MongoDB故障转移
Python是一种强大而灵活的编程语言,全世界有数百万开发人员使用它来构建他们的应用程序。Python开发人员通常使用MongoDB主机(最流行的NoSQL数据库)进行应用部署,这并不奇怪,因为它很灵活且对模式没有要求。
那么,在Python中使用MongoDB的最佳方式是什么?PyMongo是一个Python发行版库,它包含用于使用MongoDB的工具,以及推荐的PythonMongoDB驱动程序。它是一个相当成熟的驱动程序,支持数据库的大多数常见操作,你可以查看本教程来了解PyMongo驱动程序的介绍。
在生产环境中部署时,强烈建议你使用一个MongoDB副本集配置进行设置,以便你的数据在地理上合理分布,从而获得高可用性。我还建议你启用SSL连接来加密客户机-数据库通信。我们经常对各种MongoDB驱动程序的故障转移特性进行测试,以使它们适用于生产用例,或者在我们的客户向我们咨询时。在本文中,我们将向你展示如何使用PyMongo连接到一个配置了自签名证书且启用了SSL的MongoDB副本集,以及如何测试代码中的MongoDB故障转移行为。
使用自签名证书连接到MongoDB SSL
第一步是确保安装了正确版本的PyMongo及其依赖项。这个指南会帮助你整理依赖性,驱动程序兼容性列表也可以在这里找到。
为了使用自签名证书连接到一个启用了SSL的MongoDB端点,mongo_client.MongoClient中的ssl和ss_ca_cert参数是我们所关心的。 我们必须将ssl设置为True,并且ss_ca_cert必须指向CA证书文件。
如果你是一个ScaleGrid客户,可以从ScaleGrid控制台下载你的MongoDB集群的CA证书文件,如下所示:
因此,一个连接片段应该是这样的:
如果你使用自己的自签名证书,主机名验证可能会失败,那么你还必须将ssl_match_hostname参数设置为False。正如驱动程序文档所述,不建议你这样做,因为这会使连接容易受到中间人攻击。
测试故障转移行为
在MongoDB部署中,故障转移不像在传统数据库管理系统中那样被认为是主要事件。尽管大多数MongoDB驱动程序都试图抽象这个事件,但是开发人员应该理解并为这种行为设计他们的应用程序,因为应用程序应该能预料到短暂的网络错误,并在渗透错误之前进行重试。
你可以通过在工作负载运行时诱导故障转移来测试应用程序的弹性。诱导故障转移最简单的方法是运行rs.stepDown()命令:
我喜欢的一个测试驱动程序的方式是通过编写一个简单的“永久”写入器应用。这将是一些简单的代码,它会持续写入数据库,除非被用户打断,并且它会打印所有遇到的异常,来帮助我们理解驱动程序和数据库的行为。我还对它写入的数据进行跟踪,以确保测试过程中没有未报告的数据丢失。下面是测试代码的相关部分,我们将使用它来测试我们的MongoDB的故障转移行为:
上述代码写入的条目看起来像这样:
处理ConnectionFailure异常
注意,我们捕获ConnectionFailure异常来处理由于故障转移我们可能遇到的所有与网络相关的问题——我们打印异常并继续尝试写入数据库。驱动程序文档建议你:
如果某个操作由于一个网络错误而失败,则会引发ConnectionFailure异常,并且客户端会在后台进行重新连接。应用程序代码应该处理这个异常(认识到操作失败),然后继续执行。
我们来运行它,并在它执行期间执行一个数据库故障转移。下面是这期间发生的事情:
注意,驱动程序需要大约12秒的时间来理解新拓扑,连接到新的Primary并继续写入。这里捕获的异常是errors.AutoReconnect,它是ConnectionFailure的子类。
你可以再运行几次,看看还有哪些异常出现。例如,下面是我遇到的另一个异常跟踪:
这个异常也是ConnectionFailure的子类。
‘retryWrites’参数
测试MongoDB故障转移行为的另一个领域是观察其他参数变化如何影响结果。一个与之相关的参数是'retryWrites':
retryWrites:(布尔型)在MongoDB3.6+上发生网络错误后,是否重试写入在这个MongoClient中执行的操作。默认值为False。
让我们看看这个参数在故障转移时是如何工作的。对代码进行的唯一更改是:
让我们现在运行它,然后执行一个数据库系统故障转移:
请注意,虽然故障转移后的插入大约需要12秒,但由于retryWrites参数会确保重试失败的写操作,所以插入成功。请记住,设置此参数并不免除您处理ConnectionFailure异常的责任—您需要担心读取和其他操作,因为它们的行为不受此参数影响。它不能完全解决问题,即使是对支持的操作来说——有时故障转移可能需要很长的时间来完成,仅仅进行retryWrites是不够的。
配置网络超时值
rs.stepdown()会引发一个相当快的故障转移,因为副本集的Primary会被强制变成一个Secondary,而Secondary会进行一次选举来确定新的Primary。在生产部署中,网络负载、分区和其他此类问题会延迟Primary服务器的不可用性检测操作,从而延长你的故障转移时间。你在网络故障或故障转移时也会经常遇到像errors.ServerSelectionTimeoutError、errors.NetworkTimeout等这类的错误。
如果这种情况经常发生,那你就必须调整超时参数。相关的MongoClient超时参数是serverSelectionTimeoutMS、connectTimeoutMS和socketTimeoutMS。其中,为serverSelectionTimeoutMS选择一个较大的值通常有助于在故障转移期间处理错误:
serverSelectionTimeoutMS:(整数)控制驱动程序需要等待多长时间(以毫秒为单位)以便找到一个可用且合适的服务器来执行数据库操作;在等待期间,控制驱动程序可以执行多个服务器监视操作,每个操作由connectTimeoutMS控制。默认值为30000(30秒)。
准备好在你的Python应用程序中使用MongoDB了吗? 请查看我们关于Python和MongoDB入门的文章,了解如何仅通过5个简单的步骤来启动和运行它们。ScaleGrid是惟一的MongoDB DBaaS提供者,它为你提供了对实例的完全SSH访问,因此您可以在与你的MongoDB服务器相同的机器上运行Python服务器。你可以在AWS、Azure或DigitalOcean上自动化进行MongoDB云部署,它们提供专用服务器、高可用性和灾难恢复等功能,这样你就可以专注于开发你的Python应用程序了。
英文原文:https://scalegrid.io/blog/pymongo-tutorial-testing-mongodb-failover-in-your-python-app/
译者:测试