Java 生产者不能将消息分发给多个消费者?
我正在尝试使用docker compose的Java 生产者不能将消息分发给多个消费者?,java,spring-boot,docker,apache-kafka,messaging,Java,Spring Boot,Docker,Apache Kafka,Messaging,我正在尝试使用docker compose的--scale标志和docker-compose.yaml中的转发端口(如“8070-8072:8070”)自动缩放java spring framework kafka消费者。所以,当我触发端点以发布消息时,它的性能很好。但在消费者端,只有一个消费者消费所有消息。我有3个具有相同组id和不同客户端id的消费者。我想要的是分布式消息传递。我读了一些关于分区的文章,并查阅了我的日志。似乎只有一个分区。这是原因吗?我怎样才能做到这一点?我将添加日志、使用者
--scale
标志和docker-compose.yaml中的转发端口(如“8070-8072:8070”)自动缩放java spring framework kafka消费者。所以,当我触发端点以发布消息时,它的性能很好。但在消费者端,只有一个消费者消费所有消息。我有3个具有相同组id和不同客户端id的消费者。我想要的是分布式消息传递。我读了一些关于分区的文章,并查阅了我的日志。似乎只有一个分区。这是原因吗?我怎样才能做到这一点?我将添加日志、使用者配置、发布者配置和docker compose文件。首先是这个问题。似乎只有三分之一有分区
命令:
docker-compose up --build --scale nonwebapp=3 --scale webapp=3
docker-compose.yaml
kafka:
image: confluentinc/cp-kafka:latest
depends_on:
- zookeeper
ports:
- 9092:9092
environment:
KAFKA_LOG_DIRS: "/kafka/kafka-logs"
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
webapp:
build: benchmark.web
command: bash -c "while !</dev/tcp/kafka/29092; do >&2 echo 'Waiting for kafka to up...' sleep 1; done;"
ports:
- "8070-8072:8070"
volumes:
- ./logs:/logs
- ${GCP_KEY_PATH}:/root/keys/keyfile.json:ro
depends_on:
- kafka
environment:
SPRING_KAFKA_BOOTSTRAPSERVERS: kafka:29092
TZ: "Asia/Istanbul"
GOOGLE_APPLICATION_PROJECT_ID: apt-cubist-282712
GOOGLE_APPLICATION_CREDENTIALS: /root/keys/keyfile.json
restart: always
nonwebapp:
build: benchmark.nonweb
command: bash -c "while !</dev/tcp/kafka/29092; do >&2 echo 'Waiting for kafka to up...' sleep 1; done;"
depends_on:
- kafka
volumes:
- ${GCP_KEY_PATH}:/root/keys/keyfile.json:ro
ports:
- "8060-8062:8060"
environment:
SPRING_KAFKA_BOOTSTRAPSERVERS: kafka:29092
GOOGLE_APPLICATION_PROJECT_ID: apt-cubist-282712
GOOGLE_APPLICATION_CREDENTIALS: /root/keys/keyfile.json
TZ: "Asia/Istanbul"
restart: always
卡夫卡:
图片:confluentinc/cp卡夫卡:最新
取决于:
-动物园管理员
端口:
- 9092:9092
环境:
卡夫卡日志目录:“/KAFKA/KAFKA日志”
卡夫卡经纪人编号:1
卡夫卡大学动物园管理员连接:动物园管理员:2181
KAFKA_播发的_监听器:明文://KAFKA:29092,明文://localhost:9092
卡夫卡侦听器安全协议映射:明文:明文,明文主机:明文
卡夫卡·国际经纪人·听众·姓名:明文
卡夫卡偏移量主题复制系数:3
卡夫卡自动创建主题启用:“真”
卷数:
-/var/run/docker.sock:/var/run/docker.sock
重新启动:始终
网络应用程序:
构建:benchmark.web
命令:bash-c“while!&2 echo‘等待卡夫卡起床……’”睡眠1;完成
端口:
- "8070-8072:8070"
卷数:
-/日志:/logs
-${GCP_KEY_PATH}:/root/keys/keyfile.json:ro
取决于:
-卡夫卡
环境:
SPRING_KAFKA_BootstrapServer:KAFKA:29092
TZ:“亚洲/伊斯坦布尔”
谷歌应用程序项目ID:apt-cubist-282712
GOOGLE\u应用程序\u凭据:/root/keys/keyfile.json
重新启动:始终
非网络应用程序:
构建:benchmark.nonweb
命令:bash-c“while!&2 echo‘等待卡夫卡起床……’”睡眠1;完成
取决于:
-卡夫卡
卷数:
-${GCP_KEY_PATH}:/root/keys/keyfile.json:ro
端口:
- "8060-8062:8060"
环境:
SPRING_KAFKA_BootstrapServer:KAFKA:29092
谷歌应用程序项目ID:apt-cubist-282712
GOOGLE\u应用程序\u凭据:/root/keys/keyfile.json
TZ:“亚洲/伊斯坦布尔”
重新启动:始终
生产者配置
@Bean
ProducerFactory<String, byte[]> producerFactory(){
Map<String, Object> configProps = new HashMap<>();
configProps.put(
ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaInContainerAdress);
/*
configProps.put(
ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaInLocal);
*/
configProps.put(
ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
StringSerializer.class
);
configProps.put(
ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
ByteArraySerializer.class
);
return new DefaultKafkaProducerFactory<>(configProps);
}
@Bean
public KafkaTemplate<String,byte[]> kafkaTemplate(){
return new KafkaTemplate<>(producerFactory());
}
@Bean
ProducerFactory ProducerFactory(){
Map configProps=new HashMap();
配置props.put(
ProducerConfig.BOOTSTRAP\u服务器\u配置,
卡夫卡因服装);
/*
配置props.put(
ConsumerConfig.BOOTSTRAP\u服务器\u配置,
卡夫卡因(当地);
*/
配置props.put(
ProducerConfig.KEY\u序列化程序\u类\u配置,
StringSerializer.class
);
配置props.put(
ProducerConfig.VALUE\u序列化程序\u类\u配置,
ByteArraySerializer.class
);
返回新的DefaultKafkaProducerFactory(configProps);
}
@豆子
公共卡夫卡模板卡夫卡模板(){
返回新的卡夫卡模板(producerFactory());
}
消费者配置
@Bean
public ConsumerFactory<String, byte[]> consumerFactory() {
Map<String, Object> props = new HashMap<>();
props.put(
ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaInContainerAdress);
/*
props.put(
ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaInLocal);
*/
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
"org.apache.kafka.clients.consumer.RoundRobinAssignor");
props.put(ConsumerConfig.CLIENT_ID_CONFIG, r.nextInt());
props.put(
ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
StringDeserializer.class);
props.put(
ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
ByteArrayDeserializer.class);
props.put("group.id","topic_trial_consumers");
return new DefaultKafkaConsumerFactory<>(props);
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, byte[]>
kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, byte[]> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
@Bean
公共消费者工厂消费者工厂(){
Map props=newhashmap();
道具(
ConsumerConfig.BOOTSTRAP\u服务器\u配置,
卡夫卡因服装);
/*
道具(
ConsumerConfig.BOOTSTRAP\u服务器\u配置,
卡夫卡因(当地);
*/
props.put(ConsumerConfig.PARTITION\u ASSIGNMENT\u STRATEGY\u CONFIG,
“org.apache.kafka.clients.consumer.RoundRobinAssignor”);
put(ConsumerConfig.CLIENT_ID_CONFIG,r.nextInt());
道具(
ConsumerConfig.KEY\u反序列化程序\u类\u配置,
StringDeserializer.class);
道具(
ConsumerConfig.VALUE\u反序列化程序\u类\u配置,
ByteArraydSerializer.class);
props.put(“group.id”、“topic\u-trial\u-consumers”);
返回新的默认卡夫卡消费工厂(道具);
}
@豆子
公共并发KafkalistenerContainerFactory
kafkaListenerContainerFactory(){
ConcurrentKafkalistener集装箱工厂=
新的ConcurrentKafkaListenerContainerFactory();
setConsumerFactory(consumerFactory());
返回工厂;
}
似乎只有一个分区。这是原因吗
是的,如果只有一个分区,则只有一个使用者(来自使用者组)可以使用它,而其他使用者(来自同一组)即使已启动,也将处于空闲状态
似乎只有三分之一有分区
从您的图片中,我可以看到主题\u-trial-0
。因此,这是主题的第一个分区
例如,将分区数量增加到3个,并使用相同的group.id
启动三个使用者,负载应该得到分配(每个分区一个)
似乎只有一个分区。这是原因吗
是的,如果只有一个分区,则只有一个使用者(来自使用者组)可以使用它,而其他使用者(来自同一组)即使已启动,也将处于空闲状态
似乎只有三分之一有分区
从您的图片中,我可以看到主题\u-trial-0
。因此,这是主题的第一个分区
例如,将分区数增加到3,并启动三个具有相同group.id的使用者,负载应该得到分配(每个分区一个)。是的,你是对的,但我不知道如何为主题增加分区。是