我继承了一个成熟的基于烧瓶的API服务,该服务广泛使用了mongoengine。我们正在将这个单数据库API变成多租户服务,并且不清楚最佳实践。由于许多原因,租户数据将被物理地隔离到不同的数据库中,每个租户一个db。(一些文档还连接到“core”db )。
用例工作流很简单:
request
实现这一点的最好方法似乎是使用别名,但是当我切换上下文时,我需要disconnect('tenant_db')然后是connect(alias='tenant_db')。这感觉不对。
无论如何,代码实际上是有效的,但是现在我有了一个单元测试问题。在测试和使用(每个文档) mongomock://localhost连接时,代码实际上会超时尝试连接到本地主机上运行的真实mongodb。我怀疑所有这些都与模拟连接没有适当的作用域有关,但我无法找到关于使用模拟数据库进行测试的大量文档。
很抱歉,在一个问题中有两个问题:
pytest+mongoengine+mongomock的
disconnect,然后是re-connect别名模式,正确的方法不是一个有吡喃类药物的专家,也不是一个新手。坚实的与pymongo,但全新的mongoengine。
谢谢!
发布于 2021-03-09 15:30:04
没有得到蒙古引擎社区的任何回应,有点失望--也许它没有我所希望的那么活跃。
这是进一步调查的结果和我们决定的方法。
第一个尖峰--一个tenant_db别名,并在每个请求中更改底层连接。优点:这使得现有的代码可以在不进行大量重构的情况下工作。缺点:如果没有disconnect和reconnect,更改注册连接的细节是不可能的,并且不可能触发有关默认数据库的警告(没有“默认”,这是每个请求,但需要“默认”)。这是混乱的,没有成功。
第二个尖峰-咬子弹,并重构每个文档实例化在with switch_db(alias)模式中,使用每个租户的唯一别名。优点:它的明确性质使人更有信心文档操作将发生在正确的数据库中。Pro 2,关于“默认”数据库的不断警告实际上对我们有利--任何不在switch_db上下文中的流氓文档操作都会引发错误。缺点:在disconnect上下文之前仍然需要with和reconnect。
第三种情况--我们考虑了分叉mongoengine,并将Document类修改为更纯--允许注入db连接,而不是依赖注册连接的外部堆栈。优点:我们将完全控制db连接逻辑。缺点: db的东西深入到了mongoengine的DNA中--如果不付出很大的努力,这看起来是不可能成功的。
我们选了斯派克二号。
由于gunicorn->wsgi->flask为我们提供了可靠的每个请求隔离,而租户的新“默认”连接是在请求成功后发生的,所以利用with switch_db(alias)工作。这允许我们短期修复使这个单租户代码库以多租户的方式运行。
我们也没有100%的信心,我们理解底层pymongo将如何连接池的性能。在那里要做更多的研究。
最后,关于pytest的混淆。在Spike中,由于设备、作用域、断开/重新连接等原因,使用模拟测试是不可能的。除了我们必须在实际代码中添加一个环境变量,如果我们处于"unit_test_mode“中,它就不会尝试建立真正的连接。
https://stackoverflow.com/questions/66461142
复制相似问题