首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Kafka Topic 中明明有可拉取的消息,为什么 poll 不到

编程知识
2024年08月28日 07:36

开心一刻

今天小学女同学给我发消息
她:你现在是毕业了吗
我:嗯,今年刚毕业
她给我发了一张照片,怀里抱着一只大橘猫
她:我的眯眯长这么大了,好看吗
我:你把猫挪开点,它挡住了,我看不到
她:你是 sb 吗,滚
我解释道:你说的是猫呀
可消息刚发出,就出现了红色感叹号,并提示:消息已发出,但被对方拒收了

你也没说猫叫眯眯呀

kafka搭建

出于简单考虑,基于 docker 搭建一个 kafka 节点;因为一些原因,国内的 Docker Hub 镜像加速器都不可用了,目前比较靠谱的做法是搭建个人镜像仓库,可参考:Docker无法拉取镜像解决办法,我已经试过了,是可行的,但还是想补充几点

  1. sync-image-example.yml 只需要修改最后的镜像拷贝,其他内容不需要改

    sync-image-example_改动点

    支持一次配置多个镜像的拷贝

  2. 镜像拷贝

    docker 镜像拷贝命令的格式

    skopeo copy docker://docker.io/命名空间/镜像名:TAG docker://阿里云镜像地址/命名空间/镜像名:TAG

    我们以 kafka 为例,去 Docker Hub 一搜,好家伙,搜出来上万个

    上万个kafka镜像

    我们将搜索条件精确化一些,搜 wurstmeister/kafka

    wurstmeister_kafka

    点进去,它在 Docker Hub 的地址是:

    https://hub.docker.com/r/wurstmeister/kafka

    那它的 docker 地址就是

    docker://docker.io/wurstmeister/kafka

    其他的镜像用类似的方式去找,所以最终的拷贝命令类似如下:

    skopeo copy docker://docker.io/wurstmeister/kafka:latest docker://registry.cn-hangzhou.aliyuncs.com/qingshilu/wurstmeister_kafka:latest

    如果一切顺利,那么在我们的阿里云个人镜像仓库就能看到我们拷贝的镜像了

    阿里云个人镜像
  3. 如何 pull

    在个人仓库点镜像名,会看到 操作指南

    如何pull

    我们只关注前两步,就可以将镜像 pull 下来

    镜像过滤_wurstmeister

镜像获取到之后,就可以搭建 kafka 了;因为依赖 zookeeper,我们先启动它

docker run -d --name zookeeper-test -p 2181:2181 \
--env ZOO_MY_ID=1 \
-v zookeeper_vol:/data \
-v zookeeper_vol:/datalog \
-v zookeeper_vol:/logs \
registry.cn-hangzhou.aliyuncs.com/qingshilu/wurstmeister_zookeeper

然后启动 kafka

docker run -d --name kafka-test -p 9092:9092 \
--env KAFKA_ZOOKEEPER_CONNECT=192.168.2.118:2181 \
--env KAFKA_ADVERTISED_HOST_NAME=192.168.2.118 \
--env KAFKA_ADVERTISED_PORT=9092  \
--env KAFKA_LOG_DIRS=/kafka/logs \
-v kafka_vol:/kafka  \
registry.cn-hangzhou.aliyuncs.com/qingshilu/wurstmeister_kafka

不出意外的话,都启动成功

kafka启动成功

如果出意外了,大家也别慌,用 docker log 去查看日志,然后找对应的解决方案

# 1.先找到启动失败的容器id
docker ps -a
# 2.用 docker log 查看容器启动日志
docker log 容器id

如果需要开启 kafkaSASL 认证,可参考:Docker-Compose搭建带SASL用户密码验证的Kafka 来搭建

Kafka Tool

详情可查看:kafka可视化客户端工具(Kafka Tool)的基本使用

kafka_tool连接成功

创建 Topic:test-topic,并发送一条消息

创建test_topic并发送一条消息

此时 test-topic 中有 1 条消息

消费者 poll

代码很简单

/**
 * @author: 青石路
 */
public class MsgConsumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(MsgConsumer.class);

    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.2.118:9092");
        props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "test_group");
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
        // 如果在kafka中找不到当前消费者的偏移量,则设置为最旧的
        props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 500);
        KafkaConsumer<String, String> consumer = new KafkaConsumer<String,String>(props);
        // 订阅主题
        consumer.subscribe(Collections.singleton("test-topic"));
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
        LOGGER.info("records count = {}", records.count());
        records.forEach(record -> LOGGER.info("{} - {} - {}", record.offset(), record.key(), record.value()));
        // consumer.commitAsync();
        consumer.close();
    }
}

我们执行下,输出日志如下

poll没拉取到消息_日志

竟然 poll 不到消息,为什么呀?

思考考

我们调整下代码,循环 poll

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    LOGGER.info("records count = {}", records.count());
    records.forEach(record -> LOGGER.info("{} - {} - {}", record.offset(), record.key(), record.value()));
}

我们再执行下,输出日志如下

while循环后日志

消费者 poll 的过程中会先判断当前消费者是否在 消费者组 中,如果不在,会先加入消费者组,在加入过程中,ConsumerCoordinator 会对这个消费者组 Rebalance,整个过程中该消费者组内的所有消费者都不能工作,而 poll 又配置了超时时间(100 毫秒),如果在超时时间内,当前消费者还未正常加入消费者组中,那么 poll 肯定是拉取不到数据的;根据日志可以看出,第 3 次 poll 的时候,消费者已经正常加入消费者组中,那么就能 poll 到数据了

很多小伙伴可能可能会有这样的疑问

平时在项目中使用的时候,从来没有感受到这样的问题,为什么呢

原因有以下几点

  1. poll 的超时时间设置比较长,超时时间内消费者能够正常加入到消费者组中
  2. 消费者随项目的启动创建,存活周期与项目一致,那么只有前几次 poll 的时候,可能会因为消费者未加入到消费者组中而拉取不到数据,而一旦消费者成功加入到消费者组之后,那么只要 Topic 中有数据,poll 肯定能拉取到数据;从整个次数占比来看,poll 拉取不到数据的异常情况(Topic 中有可拉取的数据,但 poll 不到)占比非常小,小到可以忽略不计了

所以你们感受不到这样;但如果某些场景下,比如 DataX 从 kafka 读数据

异源数据同步 → DataX 为什么要支持 kafka?

消费者要不断新建,那么 poll 不到数据的异常情况的占比就会上来了,那就需要通过一些机制来降低其所造成的的影响了,比如说重试机制

总结

  1. 示例代码:kafka-demo
  2. 如果大家平时用 docker 比较多,推荐通过搭建个人镜像仓库来解决镜像拉取超时的问题
  3. kakfa 消费者 poll 的时候,消费者如果不在消费者组中,会先加入消费者组,那么超时时间内可能 poll 不到数据,可以通过增大超时时间,或者重试机制来降低 poll 不到数据的异常次数(Topic 中没有可拉取的数据而 poll 不到的情况不算异常情况)
From:https://www.cnblogs.com/youzhibing/p/18383403
本文地址: http://www.shuzixingkong.net/article/1505
0评论
提交 加载更多评论
其他文章 全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用
在 Python 中,枚举(Enumeration, Enum)是一种复合数据类型,用于表示一组相关但不同的常量值。枚举类型允许我们使用人类可读的名称代替代码中的魔法数字或字符串,Python 提供了 enum 模块来实现枚举类型。
全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用 全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用 全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用
Java元注解介绍
Java四种元注解相关介绍 概述 注解从Java1.5引入以来,不断地简化我们编写代码的流程,逐渐的也成为了我们必学的一项技术。我们学习了各种注解,学习了他们的用法,学习了他们的限制,是否想过他们的组成呢,下面我将我对元注解的理解分享给大家。 元注解是用来修饰注解的注解,在java.lang.ann
Java元注解介绍 Java元注解介绍 Java元注解介绍
大厂员工,手把手教你开发一个高并发、高可用的营销活动
前言 这几年工作中做过不少营销活动,无论是电商业务、支付业务、还是信贷业务,营销在整个业务发展过程中都是必不可少的。如果前期营销宣传到位,会给业务带来一波不小的流量。那么作为技术,如何接住这波流量,而不是服务被打挂。今天大厂员工,手把手教你开发出一个高并发、高可用的营销活动。 体验 点我 - 体检地
大厂员工,手把手教你开发一个高并发、高可用的营销活动 大厂员工,手把手教你开发一个高并发、高可用的营销活动 大厂员工,手把手教你开发一个高并发、高可用的营销活动
注解是如何实现的?
注解是否支持继承 不支持继承 不能使用关键字extends来继承某个@interface,但注解在编译后,编译器会自动继承java.lang.annotation.Annotation接口. 虽然反编译后发现注解继承了Annotation接口,但即使Java的接口可以实现多继承,但定义注解时依然无法
《HelloGitHub》第 101 期
每月 28 号更新的开源月刊,这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、Java、Go、C/C++、Swift...让你在短时间内感受到开源的魅力,对编程产生兴趣!
《HelloGitHub》第 101 期 《HelloGitHub》第 101 期 《HelloGitHub》第 101 期
巴特沃斯LPF设计(硬件电路实现)
高阶 (2n) VSVC单位增益巴特沃斯低通滤波器设计,可分解为 n 个二阶低通;本文通过对二阶巴特沃斯低通的硬件电路设计,后期多组组合优化,构建高阶滤波器,优化滤波器的低通特性和稳定性。
巴特沃斯LPF设计(硬件电路实现) 巴特沃斯LPF设计(硬件电路实现) 巴特沃斯LPF设计(硬件电路实现)
推荐一款开源一站式SQL审核查询平台!功能强大、安全可靠!
1、前言 在当今这个数据驱动的时代,数据库作为企业核心信息资产的载体,其重要性不言而喻。随着企业业务规模的不断扩大,数据库的数量和种类也日益增多,这对数据库的管理与运维工作提出了前所未有的挑战。在这样的背景下,一款高效、易用的数据库管理工具显得尤为重要。Archery,作为一款开源的数据库管理平台,
推荐一款开源一站式SQL审核查询平台!功能强大、安全可靠! 推荐一款开源一站式SQL审核查询平台!功能强大、安全可靠! 推荐一款开源一站式SQL审核查询平台!功能强大、安全可靠!
使用FastAPI来开发项目,项目的目录结构如何规划的一些参考和基类封装的一些处理
使用FastAPI开发项目时,良好的目录结构可以帮助你更好地组织代码,提高可维护性和扩展性。同样,对基类的封装,也可以进一步减少开发代码,提供便利,并减少出错的几率。