用于微服务间通信的apache kafka;在什么级别将主题Map到事件?

col17t5w  于 2021-06-08  发布在  Kafka
关注(0)|答案(2)|浏览(293)

我正在使用一个中型的web应用程序,它被分成几个微服务。目前,服务之间的通信方式是一个不可持续的混乱局面,因此我正在寻找其他解决方案。
对我来说非常有吸引力的一种方法是使用消息代理,其中每个服务发送和侦听消息。apachekafka引起了我的注意,看起来是一个非常有前途的软件选择。
然而,我不确定我该如何使用Kafka的主题,或者更具体地说,在什么层次上将事件Map到主题。我已经确定了三个主要的粒度级别,如下所述。
出于演示目的,请考虑一个假设的在线商店,它由许多服务组成,如shoppingcart、帐单和送货。
整个应用程序使用一个主题。
一个单独的主题,例如。 my-app-events ,用于传递服务发送和接收的所有事件。事件可能如下所示: {"from": "shopping-cart", "name": "PRODUCT_ADDED", "payload": {"product_id": 137}} .
每个微服务都使用自己的主题。
单独的主题,例如 shopping-cart-events , billing-events , shipping-events 等等。现在是世界上的一件大事 shopping-cart-events 主题可能看起来像 {"name": "PRODUCT_ADDED", "payload": {"product_id": 137}} .
每个事件类型都使用自己的主题。
这里每个可能的消息都有自己的主题。我认为在主题名称中包含事件的生产者是有意义的,这样可以调用主题 shopping-cart.product-added . 在这种情况下,消息内容将只是有效负载,例如。 {"product_id": 137} .
我希望我把这三种方法的区别弄清楚了。你有什么建议?您是否以这种方式成功地使用了kafka(或任何其他消息代理)?每种解决方案的优点和缺点是什么?

eqzww0vc

eqzww0vc1#

整个应用程序使用一个主题。
我真的觉得这没什么好处
每个微服务都使用自己的主题。
如果您需要在发生在同一实体上的事件之间排序,这是一种方法。e、 g.对于相同购物车id的事件,如shopping-cart.product-added、shopping-cart.product-removed,为了保持一致性,应该保留排序。这意味着它们去同一个分区,因此是同一个主题。
每个事件类型都使用自己的主题。
这种方法的好处是类型安全,因为在每个主题中只获得一种类型的消息,所以反序列化和下游处理不太容易出错。但是,不能保留发生在同一实体上的不同事件之间的顺序。
总而言之,我建议每个实体类型有一个主题(实体是发生事件的实体,用ddd术语来说,这将被称为聚合),例如购物车。如果您的服务非常精细,以至于每个服务只有一个实体类型,那么可以归结为每个服务一个主题。

7dl7o3gd

7dl7o3gd2#

关于Kafka:
首先,考虑是否真的要将kafka作为消息代理运行。
Kafka很快,但它背后有很多微妙之处,使得它比你想象的更难使用。如果您只运行web服务,那么其他pub/sub技术可能更合适。
Kafka本身就是一个主题,所以我将简短地谈谈你应该更密切关注的问题。这是自以为是的,从我自己的技术经验来看:
您无法轻松地阅读、浏览或删除主题中的消息,如果您没有执行正确的日志记录,那么祝您好运找到一条错误消息
分区系统需要额外的管理工作,因为它们使用的服务器api与公共库用于主题的服务器api不同。如果您只运行几个使用者,那么每个主题使用一个分区就可以了。
offset commit特性:当您希望确保没有丢失一条消息时,它非常重要,因此您可能希望禁用autocommit并执行偏移量的手动验证
除非你保证幂等性,否则你必须自己实现一个“恰好一次”的特性,因为kafka是“至少一次”:你不想借那个客户两次款,或者再次发货,或者因为你错误地处理了kafka的可重放性特性而导致垃圾邮件泛滥。
kafka consumers类通常会“阻止”读取,直到它们发生事件,如果您运行单线程进程并需要监视其他内容,这可能不太理想。。。您可能最终会执行polls(),但这些实现可能会因您的客户机库而异。
对Kafka来说,最好的监控工具是由雅虎制作的,并由社区维护。Kafka的官方管理和监督工具很差,令人可笑。
Kafka还不成熟,我不会说它是生产安全,但由于0.10的事情更好。
我现在不知道,但是,几个月前,大多数客户端js库要么已经过时(kafka<=0.8),要么文档记录不好,要么使用起来很痛苦。
关于主题架构:
首先,@michal borowiecki给出了一些值得考虑的好观点。
根据我自己的经验,你会发现每种事件类型都有一个主题很方便:每当你打开主题时,你就知道你会在其中找到什么。
如果你需要消费不同的事件类型,你可以同时消费多个主题(注意,Kafka的消费者并不擅长平衡,如果你消费5个主题,其中一个主题被淹没,你可能会陷入消费所有来自那里的信息,而没有从其他主题获得任何数据,直到事情平静下来。。。React性可能受到影响)。
每个事件类型的一个主题不应阻止您对单个事件类型使用不同的事件名称,如果您的服务删除/过滤事件,则可以。
例如:可以使用事件类型“user connexion”,并将“loggin in”和“logging out”作为该事件类型的事件名称,所有这些都在同一主题(user connexion)中—事件名称嵌入到事件的元数据中。这是有意义的,因为您希望确保按顺序处理这些消息:登录必须在注销之前进行,并且不允许已注销的用户执行特权操作。
如果您想更全面地了解事件是如何关联的,或者基于集群范围的顺序重放事件,那么您可能需要实现关联ID、向量时钟或间隔树时钟以及消息的适当存储,以便于操作和检查(例如:将主题转储到mongodb…)。
另外,如果您使用mongodb,请查看mongodb的findandmodify()特性,它允许您一致地用唯一的集群范围id标记每条消息。

相关问题