Spring Cloud Stream-第一个Kafka消息获取错误“调度程序没有订阅者”

时间:2019-07-08 22:49:52

标签: spring spring-kafka spring-cloud-stream

我的应用程序成功发送了Kafka消息,但仅在初始化Kafka之后。在此之前,我收到错误消息“调度程序没有订阅者”。如何等待订户完成频道注册?

以下是事件顺序的跟踪信息(以秒为单位计时):

  • 创建了17.165 SenderClass
  • 17.816初始化类@PostConstruct启动PollingTask
  • 24.781 PollingTask发送第一个Kafka消息
  • 24.816第一个错误:“调度程序没有订阅者”
  • 25.778注册MessageChannel我的频道
  • 仍然看到调度程序错误
  • 27.067我的频道“频道”有1位订阅者
  • 此后没有更多错误,消息可以正常发送

我不确定该如何处理。大胆的猜测包括:

  1. 将发送代码放在@PostConstruct
  2. 将@AutoConfigureBefore(BindingServiceConfiguration.class)添加到发件人
  3. 将@AutoConfigureAfter(BindingServiceConfiguration.class)添加到SenderClass
  4. 将@AutoConfigureBefore(BindingServiceConfiguration.class)添加到Main
  5. 在任务上放置@DependsOn({“ EnableBindingClass”}}
  6. 将@DependsOn({“ ApplicationLifeCycle”}})放在SchedulerClass上,其中ApplicationLifeCycle是一个只做任何事情的类 使用getPhase返回MAX_INT来实现SmartLifecycle
  7. 确保整个程序都打开ComponentScan(其他SO线程的建议)
  8. 上述各种组合

创建了一个新应用,使其变得尽可能简单

public interface Source {
  @Output(channelName)
  MessageChannel outboundChannel();
}
@EnableBinding(Source.class)
@Component
public class Sender {
  @Autowired
  private Source source;

  public boolean send(SomeObject object) {
    return source.outboundChannel().send(MessageBuilder.withPayload(object).build());
  }
@Service
public class Scheduler {
  @Autowired
  Sender sender;
  @Autowired
  ThreadPoolTaskScheduler taskScheduler;

  @PostConstruct
  public void initialize() {
    taskScheduler.schedule(new PollingTask(), nextTime);
  }

  private class PollingTask implements Runnable {
    @Override
    public void run() {
      List<SomeObject> objects = getDummyData();
      for(SomeObject object : objects)
      {
        sender.send(interval);
      }

      Instant nextTime = Instant.now().plusMillis(1_000L);
      try {
        taskScheduler.schedule(new PollingTask(), nextTime);
      } catch (Exception e) {
        logger.error(e);
      }
    }
}

编辑以添加解决方案

现在可以使用!在启动发送消息的事物的调度程序中,我从@PostConstruct的事物切换为SmartLifecycle :: start()。

@Service
public class Scheduler implements SmartLifecycle {
  @Autowired
  Sender sender;
  @Autowired
  ThreadPoolTaskScheduler taskScheduler;

  @Override
  public void start() {
    taskScheduler.schedule(new PollingTask(), nextTime);
  }

  private class PollingTask implements Runnable {
    @Override
    public void run() {
      List<SomeObject> objects = getDummyData();
      for(SomeObject object : objects)
      {
        sender.send(interval);
      }

      Instant nextTime = Instant.now().plusMillis(1_000L);
      try {
        taskScheduler.schedule(new PollingTask(), nextTime);
      } catch (Exception e) {
        logger.error(e);
      }
    }
}

1 个答案:

答案 0 :(得分:0)

@PostConstruct太早发送消息了;仍在构建上下文。.隐含SmartLifecycle,将bean置于较高阶段(Integer.MAX_VALUE),然后在start()中进行发送。

或者在ApplicationRunner中进行发送。