繁体   English   中英

Spring Cloud Stream不使用Kafka频道绑定器发送消息

[英]Spring Cloud Stream doesn't use Kafka channel binder to send a message

我正在尝试实现以下目标:

使用带有Kafka活页夹的Spring Cloud Stream 2.1.3.RELEASE将消息发送到输入通道,并实现发布订阅行为,在该行为中,将通知每个消费者,并能够处理发送到Kafka主题的消息。

我了解,在卡夫卡,如果每个消费者都属于其自己的消费者组,则他们将能够阅读主题中的每条消息。 在我的情况下,spring为我的spring boot应用程序运行的每个实例创建了一个匿名的唯一使用者组。 Spring Boot应用程序只有一个配置为侦听输入通道的流侦听器。

测试案例:

使用绑定到Kafka主题的输入通道配置了示例Spring Cloud Stream应用程序。 使用spring rest控制器将消息发送到输入通道,以期望该消息将传递到每个正在运行的spring boot应用程序实例。 在两个应用程序启动时,我都能看到kafka分区已正确分配。

问题:

但是,当我使用output()。send()发送消息时,spring甚至不会向配置的Kafka主题发送消息,而是在同一线程中触发同一应用程序实例的@StreamListener方法。

在调试期间,我看到spring代码具有两个消息处理程序。 StreamListenerMessageHandler和KafkaProducerMessageHandler。 Spring只是将它们链接在一起,如果第一个处理程序以成功结束,那么它甚至不会走得更远。 StreamListenerMessageHandler只需在同一线程中调用我的@StreamListener方法,消息就永远不会到达Kafka。

题:

这是设计使然,为什么呢? 如何实现帖子开头提到的行为?

PS。 如果我使用KafkaTemplate和@KafkaListener方法,那么它将按我的要求工作。 消息发送到Kafka主题,并且两个应用程序实例都接收消息,并使用Kafka侦听器注释的方法处理消息。

码:

流侦听器方法按以下方式配置:

@SpringBootApplication
@EnableBinding(Processor.class)
@EnableTransactionManagement
public class ProcessorApplication {

private Logger logger = 
LoggerFactory.getLogger(this.getClass().getName());

private PersonRepository repository;

public ProcessorApplication(PersonRepository repository) {

    this.repository = repository;
}

public static void main(String[] args) {
    SpringApplication.run(ProcessorApplication.class, args);

}

@Transactional
@StreamListener(Processor.INPUT)
@SendTo(Processor.OUTPUT)
public PersonEvent process(PersonEvent data) {
    logger.info("Received event={}", data);
    Person person = new Person();
    person.setName(data.getName());

    logger.info("Saving person={}", person);

    Person savedPerson = repository.save(person);

    PersonEvent event = new PersonEvent();
    event.setName(savedPerson.getName());
    event.setType("PersonSaved");
    logger.info("Sent event={}", event);
    return event;
   }
  }

将消息发送到输入通道:

@RestController()
@RequestMapping("/persons")
public class PersonController {

@Autowired
private Sink sink;


  @PostMapping("/events")
  public void createPerson(@RequestBody PersonEvent event) {

      sink.input().send(MessageBuilder.withPayload(event).build());
  }


}

Spring Cloud Stream配置:

spring:
  cloud.stream:
    bindings:
        output.destination: person-event-output
        input.destination: person-event-input

sink.input().send

您将完全绕开活页夹,并将其直接发送到流侦听器。

您需要将消息发送到kafka(到person-event-input主题),然后每个流侦听器都将从kafka接收消息。

您需要配置另一个output绑定,然后将其发送到那里,而不是直接发送到输入通道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM