我们有一个用于对象之间关系建模的微服务。在主对象和次对象之间定义具有基数约束的关系,如1-1、1-N、N-N等。微服务提供创建关系、查找关系、获取次要对象、获取初级对象等API。
Get secondary查询接口获取一个主对象,并返回所有相关的次对象。因为相关的辅助对象可能很大,所以结果是分页的。
我们还有另一个微服务,它很好地利用了这个关系微服务来处理关系。此消费服务接受类似的分页选项,如页面索引和编号,并将其传递给关系服务,并将从关系服务获得的页面结果返回给调用应用程序。到目前为止一切都很好。
我们最近发现,消费微服务与关系微服务有点闲聊,因为如果有多个主对象必须为其获取辅助对象,则它必须多次调用"Get secondaries“API。
因此,我们想让"Get Secondaries“API成为一个批量API,让它接受多个主对象作为输入。但是后来我们被分页的工作方式所困扰。API将为每个主对象返回相关的辅助对象,但会像前面一样将辅助对象限制为页面大小。
这对于第一个调用似乎很好,但我们不确定这在后续调用中会有什么表现。如果一个或多个主对象的辅助对象数量少于页面大小,那么后续调用的输入应该是什么。我需要再次传递这些主要对象吗?
这就是我们寻找关于如何设计这个批量API的建议的地方。欢迎任何意见。
发布于 2018-11-24 09:50:36
基本上,您应该有一些方法来确保关系服务在接收分页请求时知道原始查询是什么。
您的关系服务处理此问题的一种简单且可维护的方法是通过以某种方式对请求的主对象进行排序来预处理请求(即,.按Id的字母顺序排序),然后简单地遍历主对象,向响应添加辅助对象,直到响应满为止。
客户端要做的最简单的事情是始终使用相同的批处理请求,只需向请求添加索引号或页面令牌。
我推荐一个页面标记,它提到了最后看到的项目(例如,lastSeen=primaryId,secondaryId (您应该以某种方式混淆它,以避免泄漏的抽象)。然后,服务可以查看原始请求,并知道在何处恢复对所有主要对象的迭代。
或者,您可以将足够的信息编码到页面令牌中,以便可以根据原始请求重构所需的任何内容。这允许您对后续请求的查询进行一些调整。(例如,如果客户端请求主A-Z,而您在第一个响应中返回辅助对象A1 - J5,则可以将请求修改为J-Z; already seen J5,对其进行编码以避免泄露实现细节,然后将其作为页面令牌返回给客户端。)然后,客户机不再使用original request + page number进行响应,而只是使用页面令牌进行响应。
无论哪种方式,关系服务的客户端都不应该必须“弄清楚”对下一页的请求应该是什么。分页应该只要求使用者递增一个数字,或者使用关系服务提供给它的页面令牌进行响应。
另一个考虑因素是您正在使用的数据库。例如,在DynamoDB中,对于像select * from secondaries where primaryId='ABC'这样的查询,获取第100个条目的方法要求您读取第100个条目之前的所有条目。如果您有一个NoSQL数据库,或者您认为将来可能会转移到NoSQL数据库,您可能会发现页面令牌使维护您在结果集中的位置变得更加简单(与索引号相比)。
当我自己学习分页时,我发现this article非常有帮助,我推荐阅读它。它主要处理UI的分页问题,但基本原理是相同的。
TLDR:不要让消费者做任何工作。使用者应使用添加的索引号或页面标记重复原始请求,或者使用者应发送仅包含页面标记的请求。
https://stackoverflow.com/questions/53361185
复制相似问题