我正在使用Spring Cloud Stream,并希望以编程方式创建和绑定频道。我的用例是在应用程序启动期间,我收到了要订阅的Kafka主题的动态列表。如何为每个主题创建频道?
答案 0 :(得分:1)
我最近遇到了类似的情况,下面是我动态创建SubscriberChannels的示例。
ConsumerProperties consumerProperties = new ConsumerProperties();
consumerProperties.setMaxAttempts(1);
BindingProperties bindingProperties = new BindingProperties();
bindingProperties.setConsumer(consumerProperties);
bindingProperties.setDestination(retryTopic);
bindingProperties.setGroup(consumerGroup);
bindingServiceProperties.getBindings().put(consumerName, bindingProperties);
SubscribableChannel channel = (SubscribableChannel)bindingTargetFactory.createInput(consumerName);
beanFactory.registerSingleton(consumerName, channel);
channel = (SubscribableChannel)beanFactory.initializeBean(channel, consumerName);
bindingService.bindConsumer(channel, consumerName);
channel.subscribe(consumerMessageHandler);
答案 1 :(得分:0)
我必须为Camel Spring Cloud Stream组件做类似的事情。
也许是用于绑定目的地的消费者代码"实际上只是一个String
,表示频道名称"对你有用吗?
在我的情况下,我只绑定一个目的地,但我不能想象它在多个目的地的概念上有很大不同。
以下是它的要点:
@Override
protected void doStart() throws Exception {
SubscribableChannel bindingTarget = createInputBindingTarget();
bindingTarget.subscribe(message -> {
// have your way with the received incoming message
});
endpoint.getBindingService().bindConsumer(bindingTarget,
endpoint.getDestination());
// at this point the binding is done
}
/**
* Create a {@link SubscribableChannel} and register in the
* {@link org.springframework.context.ApplicationContext}
*/
private SubscribableChannel createInputBindingTarget() {
SubscribableChannel channel = endpoint.getBindingTargetFactory()
.createInputChannel(endpoint.getDestination());
endpoint.getBeanFactory().registerSingleton(endpoint.getDestination(), channel);
channel = (SubscribableChannel) endpoint.getBeanFactory().initializeBean(channel,
endpoint.getDestination());
return channel;
}
有关更多上下文的完整来源,请参阅here。
答案 2 :(得分:0)
我的任务是事先不知道主题。我通过一个输入通道解决了这个问题,它可以收听我需要的所有主题。
目的地
绑定的中间件上的通道的目标位置(例如RabbitMQ交换或Kafka主题)。如果将渠道绑定为使用者,则可以将其绑定到多个目标,并且目标名称可以指定为逗号分隔的字符串值。如果未设置,则使用频道名称。
所以我的配置
spring:
cloud:
stream:
default:
consumer:
concurrency: 2
partitioned: true
bindings:
# inputs
input:
group: application_name_group
destination: topic-1,topic-2
content-type: application/json;charset=UTF-8
然后,我定义了一个处理所有这些主题消息的使用者。
@Component
@EnableBinding(Sink.class)
public class CommonConsumer {
private final static Logger logger = LoggerFactory.getLogger(CommonConsumer.class);
@StreamListener(target = Sink.INPUT)
public void consumeMessage(final Message<Object> message) {
logger.info("Received a message: \nmessage:\n{}", message.getPayload());
// Here I define logic which handles messages depending on message headers and topic.
// In my case I have configuration which forwards these messages to webhooks, so I need to have mapping topic name -> webhook URI.
}
}
请注意,您的情况可能不是解决方案。我需要将消息转发到Web挂钩,这样我才能进行配置映射。
我也考虑了其他想法。 1)您的kafka客户使用者没有Spring Cloud。
2)创建预定义数量的输入,例如50。
input-1
intput-2
...
intput-50
然后为其中一些输入进行配置。
相关讨论 Spring cloud stream to support routing messages dynamically https://github.com/spring-cloud/spring-cloud-stream/issues/690 https://github.com/spring-cloud/spring-cloud-stream/issues/1089
我们使用Spring Cloud 2.1.1发布
答案 3 :(得分:0)
MessageChannel messageChannel = createMessageChannel(channelName);
messageChannel.send(getMessageBuilder().apply(data));
public MessageChannel createMessageChannel(String channelName) {
return (MessageChannel) applicationContext.getBean(channelName);}
public Function<Object, Message<Object>> getMessageBuilder() {
return payload -> MessageBuilder
.withPayload(payload)
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
.build();}
答案 4 :(得分:-1)
对于传入消息,您可以明确使用BinderAwareChannelResolver
来动态解析目标。您可以查看example router
接收器使用活页夹感知通道解析器的位置。