我正在Google App Engine数据存储区上构建服务,这是最终一致的数据存储区。对于我的应用程序,这很好。
但是,我正在开发测试,这些测试执行的操作类似PUT对象,然后执行GET对象,并检查返回对象的属性。不幸的是,因为数据存储最终是一致的,所以这些简单的测试无法重现。
您如何测试最终一致的服务?
How can I reproducibly test an eventually consistent service? -不能。您必须删除“可复制”或“最终”一词;你不能两者兼得。
我正在Google App Engine数据存储区上构建服务,这是最终一致的数据存储区。对于我的应用程序,这很好。
但是,我正在开发测试,这些测试执行的操作类似PUT对象,然后执行GET对象,并检查返回对象的属性。不幸的是,因为数据存储最终是一致的,所以这些简单的测试无法重现。
您如何测试最终一致的服务?
How can I reproducibly test an eventually consistent service? -不能。您必须删除“可复制”或“最终”一词;你不能两者兼得。
Answers:
您真的希望您的测试快速而一致。如果您开始创建可能由于最终一致性而偶尔失败的测试,则在测试失败时将忽略该测试,那么它有什么用?
创建一个伪造的服务来处理PUT和GET请求,但是还要执行其他操作以使其一致。然后,您的测试是:
datastore.do_put(myobj);
datastore.make_consistent();
validate(datastore.do_get(), myobj);
这使您可以在GET成功检索PUT对象时测试软件的行为。当GET由于服务不一致而找不到对象(或正确的对象)时,它还允许您测试软件的行为。只需忽略对的呼叫即可make_consistent()。
与真实服务交互的测试仍然值得,但是它们应该在您正常的开发工作流之外运行,因为它们永远不会100%可靠(例如,如果服务关闭)。这些测试应用于:
好吧 关键问题是“您正在测试什么”。
在这种情况下,您应该嘲笑Google服务,并始终返回响应。
在这种情况下,您应该模拟Google服务,并始终在正确响应之前返回短暂错误
您应该注入真实的Google服务并运行测试。但!您要测试的代码应该内置了Transient Error处理(重试)功能。因此,您应该得到一致的答复。(除非Google行为举止很差)
据我了解,Google Cloud数据存储区允许强一致性查询和最终一致性查询。
折衷方案是,高度一致的查询非常严格地限制了速率(在测试过程中您可以接受)。
一种可能是将查询放在包装器中的数据存储中,以实现测试目的的强一致性。
例如,您可以使用称为start_debug_strong_consistency()和的方法end_debug_strong_consistency()。
start方法将创建一个可用作所有后续查询的祖先键的键,而end方法将删除该键。
您正在测试的实际查询的唯一更改将是调用setAncestor(your_debug_key)该键(如果存在)。
诸如Google App Engine数据存储区之类的服务基于跨多个全球分布的存在点(POP)的数据复制。任何针对最终一致服务的集成测试实际上都是对该服务在其POP组之间的复制率的测试。取决于许多因素,例如复制方法和各种Internet传输问题,内容在给定服务中传播给每个POP的速率与服务中每个POP的传播速率将不会相同—这是两个示例在任何最终一致的数据存储服务中,报告占大多数报告(至少这是我在主要CDN上工作时的经验)。
为了有效地测试对象在给定平台上的复制,您需要将测试设置为从服务的每个POP中特别请求最近放置的同一对象。我建议测试POP列表1-5次,或者直到POP列表中的所有POP报告包含对象为止。您可以自由调整以下一组执行测试的时间间隔:将其放在数据存储区后的1、5、60分钟,12小时,25小时。关键是记录每个时间间隔的结果,以供以后查看和分析,以了解给定服务的全局复制对象的能力。通常,数据存储区服务仅在本地请求后才将本地副本拉到POP [路由是通过BGP协议完成的,这就是为什么您的测试必须从每个特定POP请求对象才能使其在给定平台上全局有效] 。对于Google的数据存储区,您将要设置测试以从“遍布33个国家/地区的70多个存在点”查询给定对象;您可能必须从Google支持部门获取POP特定的地址网址列表[参考:https://cloud.google.com/about/locations/ ];如果Google使用Fastly进行复制,请快速支持[ https://www.fastly.com/resources ]。
此方法的几个优点:1)您将对给定服务的复制平台有所了解,并在全球范围内整体上了解其优势和弱点(就像在集成测试中一样)。2)对于您测试的任何对象,您都可以使用一种工具来预热内容[发出第一个请求,以给定的本地POP创建副本] –因此,您可以通过一种方法来确保内容在客户请求之前在全球范围内传播地球上任何地方。
我有使用Google App Engine数据存储的经验。令人惊讶的是,在本地运行通常比“一致”更“最终”。最简单的示例:创建一个新实体,然后检索它。在过去的5年中,我经常看到本地运行的SDK不会立即找到新实体,而是大约半秒钟后才找到它。
但是,在真正的Google服务器上运行时,我还没有看到这种行为。他们试图使您的数据存储区客户端始终在同一侧与同一服务器上运行,因此通常所有更改都会立即反映在查询中。
我对集成测试的建议是在真实服务器上运行它们,然后您可能无需进行任何虚假的轮询或延迟即可获得结果。