Apache camel 对于SpringCloudStream,我应该为每种事件类型配置通道吗?

Apache camel 对于SpringCloudStream,我应该为每种事件类型配置通道吗?,apache-camel,messaging,microservices,spring-cloud-stream,event-driven-design,Apache Camel,Messaging,Microservices,Spring Cloud Stream,Event Driven Design,我正在做一个使用springboot、SpringCloudNetflix等构建微服务的项目 对于一些异步通信,我使用SpringCloudStream来生成和使用事件。e、 g.在合同服务中起草业务合同后,该服务将发布合同创建事件(审计服务将使用该事件)以初始化审计流程。此外,用户服务将使用该事件为相关方创建通知 场景是我有许多事件,消费者将根据事件类型订阅感兴趣的事件。 我遇到的问题是,我有很多事件类型,很快,我的配置文件中充斥着通道配置。e、 g spring.cloud.stream.b

我正在做一个使用springboot、SpringCloudNetflix等构建微服务的项目

对于一些异步通信,我使用SpringCloudStream来生成和使用事件。e、 g.在合同服务中起草业务合同后,该服务将发布合同创建事件(审计服务将使用该事件)以初始化审计流程。此外,用户服务将使用该事件为相关方创建通知

场景是我有许多事件,消费者将根据事件类型订阅感兴趣的事件。 我遇到的问题是,我有很多事件类型,很快,我的配置文件中充斥着通道配置。e、 g

spring.cloud.stream.bindings.creation.destination=contract-creation
spring.cloud.stream.bindings.revocation.destination=contract-revocation
spring.cloud.stream.bindings.termination.destination=contract-termination
...
我做错了什么?我正在考虑这些替代方案:

  • !!有一个按类型有选择地使用事件的示例。这是一个很好的解决方案,但我在想,SpringCloudStream是否有本机解决方案
  • 我应该使用ApacheCamel还是Spring集成?我没有复杂的路由规则,这些框架看起来有些过分了

  • 我是一个信息新手,希望这里的人能给我指出一个正确的方向。

    David博客文章中提到的
    条件
    表达式属性被烘焙到
    @StreamListener
    注释中,因此,您可以将不同的事件类型从同一目的地路由到不同的侦听器。

    David博客文章中提到的
    条件
    表达式属性被烘焙到
    @StreamListener
    注释中,因此您可以将不同的事件类型从同一目的地路由到不同的侦听器。

    这取决于,非常抱歉,我开始回答这个问题

    使用带有选择器的单一频道是最简单的选择,但需要注意的是,每个消费者都将使用来自该目的地的所有消息。如果这是您的用例,那么就开始吧

    另一个用例是事件源类型,其中大多数消费者只对事件的子集感兴趣,而您最好将事件(或更好的聚合根)放置在每个目标上。这将允许您更好地扩展,并避免经纪人与消费者之间不必要的闲聊

    在您的示例中,您可以使用如下内容:

    public interface Contracts {
    
        @Output("contract-creation") MessageChannel creation();
        @Output("contract-revogation") MessageChannel revogation();
        @Output("contract-termination") MessageChannel termination();
    
    } 
    
    public interface Events {
        @Output MessageChannel user();
        @Output MessageChannel contract();
    }
    
    这将为每个事件类型创建一个主题,可能有点过分了

    也许您应该创建一个带有
    类型的
    接口
    事件
    ,并让事件从中派生出来,然后改为:

    public interface Contracts {
    
        @Output("contract-creation") MessageChannel creation();
        @Output("contract-revogation") MessageChannel revogation();
        @Output("contract-termination") MessageChannel termination();
    
    } 
    
    public interface Events {
        @Output MessageChannel user();
        @Output MessageChannel contract();
    }
    
    现在,所有合同事件(创建、撤销、终止)都将转到同一个目的地。在接收端,您可以创建选择器来选择要应用的选择器:

    @StreamListener(target = "contract", condition = "payload.type=='created'")
        public void contractCreated(@Payload ContractCreatedEvent){
    
        }
    
        @StreamListener(target = "contract", condition = "payload.type=='terminated'")
        public void contractTerminated(@Payload ContractTerminatedEvent){
    
        }
    

    这要看情况而定,我很抱歉开始回答这个问题

    使用带有选择器的单一频道是最简单的选择,但需要注意的是,每个消费者都将使用来自该目的地的所有消息。如果这是您的用例,那么就开始吧

    另一个用例是事件源类型,其中大多数消费者只对事件的子集感兴趣,而您最好将事件(或更好的聚合根)放置在每个目标上。这将允许您更好地扩展,并避免经纪人与消费者之间不必要的闲聊

    在您的示例中,您可以使用如下内容:

    public interface Contracts {
    
        @Output("contract-creation") MessageChannel creation();
        @Output("contract-revogation") MessageChannel revogation();
        @Output("contract-termination") MessageChannel termination();
    
    } 
    
    public interface Events {
        @Output MessageChannel user();
        @Output MessageChannel contract();
    }
    
    这将为每个事件类型创建一个主题,可能有点过分了

    也许您应该创建一个带有
    类型的
    接口
    事件
    ,并让事件从中派生出来,然后改为:

    public interface Contracts {
    
        @Output("contract-creation") MessageChannel creation();
        @Output("contract-revogation") MessageChannel revogation();
        @Output("contract-termination") MessageChannel termination();
    
    } 
    
    public interface Events {
        @Output MessageChannel user();
        @Output MessageChannel contract();
    }
    
    现在,所有合同事件(创建、撤销、终止)都将转到同一个目的地。在接收端,您可以创建选择器来选择要应用的选择器:

    @StreamListener(target = "contract", condition = "payload.type=='created'")
        public void contractCreated(@Payload ContractCreatedEvent){
    
        }
    
        @StreamListener(target = "contract", condition = "payload.type=='terminated'")
        public void contractTerminated(@Payload ContractTerminatedEvent){
    
        }
    

    是否最好将类型信息放在消息头中,并使用@StreamListener(target=ConsumerChannels.CONSUMER,condition=“headers['type']=='contract-created')?这样,如果我不需要实体的“type”字段,我可以得到一个更干净的实体。使用头是另一种选择,但我不会说它更好,因为它取决于域设计。如果您正在对类型对存储和检索非常重要的事件进行建模,那么在基类中有一个名为type的属性并不构成污染。嗨,Vinicius当我使用您的代码condition=“payload.type=='terminated',并将type字段放入payload中时,我无法找到与id为xxxxx的消息相匹配的@StreamListener。但是使用header['type'],并在header中输入type就可以了。那么,是否可以在条件spel中使用有效负载?本文可以帮助实现上述方法,将类型信息放在消息头中,并使用@StreamListener(target=ConsumerChannels.CONSUMER,condition=“headers['type']='contract-created')会更好吗?这样,如果我不需要实体的“type”字段,我可以得到一个更干净的实体。使用头是另一种选择,但我不会说它更好,因为它取决于域设计。如果您正在对类型对存储和检索非常重要的事件进行建模,那么在基类中有一个名为type的属性并不构成污染。嗨,Vinicius当我使用您的代码condition=“payload.type=='terminated',并将type字段放入payload中时,我无法找到与id为xxxxx的消息相匹配的@StreamListener。但是使用header['type'],并在header中输入type就可以了。所以,有可能在条件spel中使用有效负载吗?本文可以帮助实现上述方法