在微服务之间共享大量数据

4
我正在设计一个微服务架构的评论分析平台。
应用程序工作方式如下:
- 从电商网站A(site-a)检索所有产品评论,并以excel文件形式上传。 - 评论通过excel文件上传到系统中。 - 分析代理可以列出所有评论,编辑其中一些评论,删除或批准。 - 分析代理可以导出site-a的所有评论。 - 对每个上传和编辑的评论都应用基于正则表达式的自动化检查。
我有3个微服务:
- Reviews:负责评论CRUD操作以及类似批准/拒绝的操作。 - Validations:负责定义和应用评论上的验证规则。 - Export/Import:导出服务根据网站名称(如site-a)导出大型文件。
问题在于,某些时候,验证服务需要获取site-a的所有评论,应用验证规则并生成错误(如果有)。我知道共享数据库模式和实体会破坏微服务架构。
一种可能的解决方案是,每当验证服务需要site-a的评论时,它请求网关,网关将请求重定向到Reviews服务并获取响应。

这种方法可能存在的两个缺点是:

  • 验证服务是否了解网关?这会带来依赖性吗?
  • 如果我有10亿条站点评论,通过rest请求获取所有评论可能是一个问题。(或者不是,我可以从验证服务到网关进行分页请求。)

那么,在不共享实体并且不重复数据的情况下,共享大量数据的最佳做法是什么?

  • 使用消息队列的做法很多,但我认为在我的情况下,使用消息队列分享吉格字节的数据并不好。

编辑1:是否可以使用带有REST API的数据存储解决问题,而不是共享实体? 假设我正在使用MongoDB,我可以使用mongo的rest接口(http://restheart.org/)而不是在微服务之间共享实体对象,并尽可能查询数据。


你可以尝试企业集成模式。我不知道有没有一个能解决这个特定用例的模式,但应该在其中得到涵盖。 - k1133
2个回答

11

你的问题不在于“共享大量数据”,而在于你选择基于哪些边界来分离你的微服务。

从你的需求中可以看出,你选择分离的3个微服务(评论、验证、导入/导出)实际上是在相同的上下文和业务领域中运作,即评论。

我建议你重新考虑设计决策,将评论作为一个单独的微服务来处理所有评论操作和逻辑,作为一个黑盒子。


是的,@Bishoy,你可能是对的。但当我开始将在同一业务领域运作的服务组合起来时,它就变成了单块架构。对我来说,验证完全是不同的逻辑和领域。实际上,这个服务并不知道它是否正在验证评论,它只是在某些字段上应用正则表达式。 - ygk
这里有一个关于如何决定微服务应该有多大的好文章:http://www.ben-morris.com/how-big-is-a-microservice/ - Bishoy
我真的认为验证不应该是一个不同的服务,因为它并不是一个不同的领域。验证规则等不是特定于领域吗?我认为试图将其拆分会使所有事情变得过于复杂。@ygok - Kaj
是的,@Kaj,我同意它们可能在同一个微服务中。但如果我有两个真正明确定义的微服务需要共享大量数据怎么办?我们能否制定一项限制规定“如果两个微服务共享大量数据,则它们应该成为单个服务”?我不这么认为。 - ygk

0

我假设评论是相互独立的,因此验证评论只需要该评论本身,而不需要其他评论。

您不希望共享实体,这排除了诸如共享数据库、Hadoop集群或Redis之类的数据存储。您也不希望重复数据,因此排除了纯文件复制或基于触发器的数据库级别复制。

总之,我认为您的目标应该是一个流。让验证器从有关A站点的评论中请求所有内容,但不是一次性全部请求,而是以单个或小批量评论的流形式。

现在,验证器可以逐个处理评论,保持内存和处理器消耗的恒定。为了提高性能,您可以创建多个验证器实例,同时拉取不同的、不相交的流片段。同样地,如果单个评论微服务无法快速回答拉取请求,您可以创建多个评论微服务实例。

验证器不会持久化此流,它仅生成错误并将其存储或发送到某个地方;这应该满足您的不共享不重复要求。


实际上,我们首先实现了通过文件服务共享数据。源微服务将文件导出并上传到文件服务,然后将文件的URL发送给目标微服务。这种方法工作稳定,但由于其设计复杂,添加一个新服务就成为了一个问题。开发和测试的工作量很大。现在我们转而使用队列进行流式处理。我们最初使用了RabbitMQ,但计划也切换到Kafka :)总之,我们正在应用您的建议。 - ygk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接