如何实现Kafka使用者使用spring-cloud-stream来按需处理事件?

时间:2019-03-29 02:23:28

标签: spring-cloud-stream

我正在尝试实现一个PollableConsumer,该PollableConsumer在特定条件下(在这种情况下,当我在SpringBoot应用程序中命中一个端点时)开始从Kafka轮询消息。

我尝试了在特定条件下触发轮询器的多种方法,但显然只有在它不断从kafka主题中轮询时,它才起作用。 (就像spring-cloud-stream文档中的所有示例一样)

我正在寻找这样的东西:

public interface CustomProcessor {
    @Input
    PollableMessageSource input();
}
 public void run() {
        boolean result = true;
        while (result) {
            result = input.poll(m -> {
                Event event = (Event) m.getPayload();
                GenericMessage<Event> genericMessage = new GenericMessage<>(event, m.getHeaders());
                eventMessageConsumer.consume(genericMessage);
            }, new ParameterizedTypeReference<Event>() {
            });

            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
            if (result) {
                System.out.println("Success");
            }
        }
    }

当我碰到这样的端点时,可能会触发该事件:

@GetMapping("/process")
public void process() {
   SomeClass.run();
}

2 个答案:

答案 0 :(得分:0)

显然,目前无法使用spring-cloud-stream暂停PollableConsumer,因此我转回基于事件的消息使用方式,并使用执行器来控制绑定状态。在strategy线程和spring-cloud-stream this之后,我注入了BindingsEndpoint并按如下所示更改了绑定状态:

@RestController
public class EventController {
    @Autowired
    public EventController(BindingsEndpoint bindingsEndpoint) {
        this.bindingsEndpoint = bindingsEndpoint;
    }
    @GetMapping("/changeState")
    public void sendMessage(@RequestParam("state") String state) {
        if (state.equals("paused")) {
            bindingsEndpoint.changeState("MY_BINDING", 
                           BindingsEndpoint.State.PAUSED);
        }
        if (state.equals("resumed")) {
            bindingsEndpoint.changeState("MY_BINDING", 
                           BindingsEndpoint.State.RESUMED);
        }
    }

这不是我想要实现的目标,但已经足够接近了。

答案 1 :(得分:-1)

在您的代码示例中,我不确定input.poll返回的结果,因为您将结果分配给了boolean,而不是KafkaConsumer.poll方法返回的结果。

Kafka Consumer可以按需暂停和重新启动,这不成问题。

来自最新的KafkaConsumer javadoc:

  

消费流控制

     

...

     

Kafka通过使用 pause(Collection) resume(Collection)在指定的已分配分区上暂停消耗并在磁盘上恢复消耗来支持对消耗流的动态控制。在以后的poll(Duration)调用中分别指定暂停的分区。

然后来自pause方法说明:

  

请注意,此方法不会影响分区订阅。特别是,使用自动分配时不会导致组重新平衡

https://kafka.apache.org/22/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html

因此,在您的情况下,您可以简单地使用一个volatile boolean isPaused标志,如果更改了该标志,则可以根据需要发出pauseresume命令。 KafkaConsumer将完成其余的工作。

另外,请注意,KafkaConsumer不是线程安全的,因此您应该在轮询数据的同一线程上发出这些命令。