learn.lianglianglee.com/专栏/Kafka核心技术与实战/31 常见工具脚本大汇总.md.html
2022-08-14 03:40:33 +08:00

411 lines
33 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>31 常见工具脚本大汇总.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/Kafka核心技术与实战/00 开篇词 为什么要学习Kafka.md.html">00 开篇词 为什么要学习Kafka</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/01 消息引擎系统ABC.md.html">01 消息引擎系统ABC</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/02 一篇文章带你快速搞定Kafka术语.md.html">02 一篇文章带你快速搞定Kafka术语</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/03 Kafka只是消息引擎系统吗.md.html">03 Kafka只是消息引擎系统吗</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/04 我应该选择哪种Kafka.md.html">04 我应该选择哪种Kafka</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/05 聊聊Kafka的版本号.md.html">05 聊聊Kafka的版本号</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/06 Kafka线上集群部署方案怎么做.md.html">06 Kafka线上集群部署方案怎么做</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/07 最最最重要的集群参数配置(上).md.html">07 最最最重要的集群参数配置(上)</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/08 最最最重要的集群参数配置(下).md.html">08 最最最重要的集群参数配置(下)</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/09 生产者消息分区机制原理剖析.md.html">09 生产者消息分区机制原理剖析</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/10 生产者压缩算法面面观.md.html">10 生产者压缩算法面面观</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/11 无消息丢失配置怎么实现?.md.html">11 无消息丢失配置怎么实现?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/12 客户端都有哪些不常见但是很高级的功能?.md.html">12 客户端都有哪些不常见但是很高级的功能?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/13 Java生产者是如何管理TCP连接的.md.html">13 Java生产者是如何管理TCP连接的</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/14 幂等生产者和事务生产者是一回事吗?.md.html">14 幂等生产者和事务生产者是一回事吗?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/15 消费者组到底是什么?.md.html">15 消费者组到底是什么?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/16 揭开神秘的“位移主题”面纱.md.html">16 揭开神秘的“位移主题”面纱</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/17 消费者组重平衡能避免吗?.md.html">17 消费者组重平衡能避免吗?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/18 Kafka中位移提交那些事儿.md.html">18 Kafka中位移提交那些事儿</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/19 CommitFailedException异常怎么处理.md.html">19 CommitFailedException异常怎么处理</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/20 多线程开发消费者实例.md.html">20 多线程开发消费者实例</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/21 Java 消费者是如何管理TCP连接的.md.html">21 Java 消费者是如何管理TCP连接的</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/22 消费者组消费进度监控都怎么实现?.md.html">22 消费者组消费进度监控都怎么实现?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/23 Kafka副本机制详解.md.html">23 Kafka副本机制详解</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/24 请求是怎么被处理的?.md.html">24 请求是怎么被处理的?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/25 消费者组重平衡全流程解析.md.html">25 消费者组重平衡全流程解析</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/26 你一定不能错过的Kafka控制器.md.html">26 你一定不能错过的Kafka控制器</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/27 关于高水位和Leader Epoch的讨论.md.html">27 关于高水位和Leader Epoch的讨论</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/28 主题管理知多少.md.html">28 主题管理知多少</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/29 Kafka动态配置了解下.md.html">29 Kafka动态配置了解下</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/30 怎么重设消费者组位移?.md.html">30 怎么重设消费者组位移?</a>
</li>
<li>
<a class="current-tab" href="/专栏/Kafka核心技术与实战/31 常见工具脚本大汇总.md.html">31 常见工具脚本大汇总</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/32 KafkaAdminClientKafka的运维利器.md.html">32 KafkaAdminClientKafka的运维利器</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/33 Kafka认证机制用哪家.md.html">33 Kafka认证机制用哪家</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/34 云环境下的授权该怎么做?.md.html">34 云环境下的授权该怎么做?</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/35 跨集群备份解决方案MirrorMaker.md.html">35 跨集群备份解决方案MirrorMaker</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/36 你应该怎么监控Kafka.md.html">36 你应该怎么监控Kafka</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/37 主流的Kafka监控框架.md.html">37 主流的Kafka监控框架</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/38 调优Kafka你做到了吗.md.html">38 调优Kafka你做到了吗</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/39 从0搭建基于Kafka的企业级实时日志流处理平台.md.html">39 从0搭建基于Kafka的企业级实时日志流处理平台</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/40 Kafka Streams与其他流处理平台的差异在哪里.md.html">40 Kafka Streams与其他流处理平台的差异在哪里</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/41 Kafka Streams DSL开发实例.md.html">41 Kafka Streams DSL开发实例</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/42 Kafka Streams在金融领域的应用.md.html">42 Kafka Streams在金融领域的应用</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/加餐 搭建开发环境、阅读源码方法、经典学习资料大揭秘.md.html">加餐 搭建开发环境、阅读源码方法、经典学习资料大揭秘</a>
</li>
<li>
<a href="/专栏/Kafka核心技术与实战/结束语 以梦为马,莫负韶华!.md.html">结束语 以梦为马,莫负韶华!</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>31 常见工具脚本大汇总</h1>
<p>你好我是胡夕。今天我要跟你分享的主题是Kafka 常见的脚本汇总。</p>
<h2>命令行脚本概览</h2>
<p>Kafka 默认提供了很多个命令行脚本,用于实现各种各样的功能和运维管理。今天我以 2.2 版本为例,详细地盘点下这些命令行工具。下图展示了 2.2 版本提供的所有命令行脚本。</p>
<p><img src="assets/f74fe9a3aef75f8db6533e1011571eee.png" alt="img" /></p>
<p>从图中我们可以知道2.2 版本总共提供了 30 个 SHELL 脚本。图中的 windows 实际上是个子目录,里面保存了 Windows 平台下的 BAT 批处理文件。其他的.sh 文件则是 Linux 平台下的标准 SHELL 脚本。</p>
<p>默认情况下,不加任何参数或携带 --help 运行 SHELL 文件,会得到该脚本的使用方法说明。下面这张图片展示了 kafka-log-dirs 脚本的调用方法。</p>
<p><img src="assets/04953999a40ea439fce05a57b29714cc.png" alt="img" /></p>
<p>有了这些基础的了解,我来逐一地说明这些脚本的用途,然后再给你详细地介绍一些常见的脚本。</p>
<p>我们先来说说 connect-standalone 和 connect-distributed 两个脚本。这两个脚本是 Kafka Connect 组件的启动脚本。在专栏[第 4 讲]谈到 Kafka 生态时,我曾说过社区提供了 Kafka Connect 组件,用于实现 Kafka 与外部世界系统之间的数据传输。Kafka Connect 支持单节点的 Standalone 模式,也支持多节点的 Distributed 模式。这两个脚本分别是这两种模式下的启动脚本。鉴于 Kafka Connect 不在我们的讨论范围之内,我就不展开讲了。</p>
<p>接下来是 kafka-acls 脚本。它是用于设置 Kafka 权限的,比如设置哪些用户可以访问 Kafka 的哪些主题之类的权限。在专栏后面,我会专门来讲 Kafka 安全设置的内容,到时候我们再细聊这个脚本。</p>
<p>下面是 kafka-broker-api-versions 脚本。<strong>这个脚本的主要目的是验证不同 Kafka 版本之间服务器和客户端的适配性</strong>。我来举个例子,下面这两张图分别展示了 2.2 版本 Server 端与 2.2 版本 Client 端和 1.1.1 版本 Client 端的适配性。</p>
<p><img src="assets/594776ae03ca045b3203f873b75c3139.png" alt="img" /></p>
<p><img src="assets/a3604bb34011c372d7f63912ffdf0584.png" alt="img" /></p>
<p>我截取了部分输出内容,现在我稍微解释一下这些输出的含义。我们以第一行为例:</p>
<blockquote>
<p><em>Produce(0): 0 to 7 [usable: 7]</em></p>
</blockquote>
<p>“Produce”表示 Produce 请求,生产者生产消息本质上就是向 Broker 端发送 Produce 请求。该请求是 Kafka 所有请求类型中的第一号请求,因此序号是 0。后面的“0 to 7”表示 Produce 请求在 Kafka 2.2 中总共有 8 个版本,序号分别是 0 到 7。“usable7”表示当前连入这个 Broker 的客户端 API 能够使用的版本号是 7即最新的版本。</p>
<p>请注意这两张图中红线部分的差异。在第一张图中,我们使用 2.2 版本的脚本连接 2.2 版本的 Brokerusable 自然是 7表示能使用最新版本。在第二张图中我们使用 1.1 版本的脚本连接 2.2 版本的 Brokerusable 是 5这表示 1.1 版本的客户端 API 只能发送版本号是 5 的 Produce 请求。</p>
<p>如果你想了解你的客户端版本与服务器端版本的兼容性,那么最好使用这个命令来检验一下。值得注意的是,<strong>在 0.10.2.0 之前Kafka 是单向兼容的,即高版本的 Broker 能够处理低版本 Client 发送的请求,反过来则不行。自 0.10.2.0 版本开始Kafka 正式支持双向兼容,也就是说,低版本的 Broker 也能处理高版本 Client 的请求了</strong></p>
<p>接下来是 kafka-configs 脚本。对于这个脚本,我想你应该已经很熟悉了,我们在讨论参数配置和动态 Broker 参数时都提到过它的用法,这里我就不再赘述了。</p>
<p>下面的两个脚本是重量级的工具行脚本kafka-console-consumer 和 kafka-console-producer。在某种程度上说它们是最常用的脚本也不为过。这里我们暂时先跳过后面我会重点介绍它们。</p>
<p>关于 producer 和 consumer成组出现的还有另外一组脚本kafka-producer-perf-test 和 kafka-consumer-perf-test。它们分别是生产者和消费者的性能测试工具非常实用稍后我会重点介绍。</p>
<p>接下来的 kafka-consumer-groups 命令,我在介绍重设消费者组位移时稍有涉及,后面我们来聊聊该脚本的其他用法。</p>
<p>kafka-delegation-tokens 脚本可能不太为人所知,它是管理 Delegation Token 的。基于 Delegation Token 的认证是一种轻量级的认证机制,补充了现有的 SASL 认证机制。</p>
<p>kafka-delete-records 脚本用于删除 Kafka 的分区消息。鉴于 Kafka 本身有自己的自动消息删除策略,这个脚本的实际出场率并不高。</p>
<p>kafka-dump-log 脚本可谓是非常实用的脚本。它能查看 Kafka 消息文件的内容,包括消息的各种元数据信息,甚至是消息体本身。</p>
<p>kafka-log-dirs 脚本是比较新的脚本,可以帮助查询各个 Broker 上的各个日志路径的磁盘占用情况。</p>
<p>kafka-mirror-maker 脚本是帮助你实现 Kafka 集群间的消息同步的。在专栏后面,我会单独用一讲的内容来讨论它的用法。</p>
<p>kafka-preferred-replica-election 脚本是执行 Preferred Leader 选举的。它可以为指定的主题执行“换 Leader”的操作。</p>
<p>kafka-reassign-partitions 脚本用于执行分区副本迁移以及副本文件路径迁移。</p>
<p>kafka-topics 脚本你应该很熟悉了,所有的主题管理操作,都是由该脚本来实现的。</p>
<p>kafka-run-class 脚本则颇为神秘,你可以用这个脚本执行任何带 main 方法的 Kafka 类。在 Kafka 早期的发展阶段,很多工具类都没有自己专属的 SHELL 脚本,比如刚才提到的 kafka-dump-log你只能通过运行 kafka-run-class kafka.tools.DumpLogSegments 的方式来间接实现。如果你用文本编辑器打开 kafka-dump-log.sh你会发现它实际上调用的就是这条命令。后来社区逐渐为这些重要的工具类都添加了专属的命令行脚本现在 kafka-run-class 脚本的出场率大大降低了。在实际工作中,你几乎遇不上要直接使用这个脚本的场景了。</p>
<p>对于 kafka-server-start 和 kafka-server-stop 脚本,你应该不会感到陌生,它们是用于启动和停止 Kafka Broker 进程的。</p>
<p>kafka-streams-application-reset 脚本用来给 Kafka Streams 应用程序重设位移,以便重新消费数据。如果你没有用到 Kafka Streams 组件,这个脚本对你来说是没有用的。</p>
<p>kafka-verifiable-producer 和 kafka-verifiable-consumer 脚本是用来测试生产者和消费者功能的。它们是很“古老”的脚本了,你几乎用不到它们。另外,前面提到的 Console Producer 和 Console Consumer 完全可以替代它们。</p>
<p>剩下的 zookeeper 开头的脚本是用来管理和运维 ZooKeeper 的,这里我就不做过多介绍了。</p>
<p>最后说一下 trogdor 脚本。这是个很神秘的家伙,官网上也不曾出现它的名字。据社区内部资料显示,它是 Kafka 的测试框架,用于执行各种基准测试和负载测试。一般的 Kafka 用户应该用不到这个脚本。</p>
<p>好了Kafka 自带的所有脚本我全部梳理了一遍。虽然这些描述看起来有点流水账,但是,有了这些基础的认知,我们才能更好地利用这些脚本。下面我就来详细介绍一下重点的脚本操作。</p>
<h2>重点脚本操作</h2>
<h3>生产消息</h3>
<p>生产消息使用 kafka-console-producer 脚本即可,一个典型的命令如下所示:</p>
<pre><code>$ bin/kafka-console-producer.sh --broker-list kafka-host:port --topic test-topic --request-required-acks -1 --producer-property compression.type=lz4
&gt;
</code></pre>
<p>在这段命令中,我们指定生产者参数 acks 为 -1同时启用了 LZ4 的压缩算法。这个脚本可以很方便地让我们使用控制台来向 Kafka 的指定主题发送消息。</p>
<h3>消费消息</h3>
<p>下面再来说说数据消费。如果要快速地消费主题中的数据来验证消息是否存在,运行 kafka-console-consumer 脚本应该算是最便捷的方法了。常用的命令用法如下:</p>
<pre><code>$ bin/kafka-console-consumer.sh --bootstrap-server kafka-host:port --topic test-topic --group test-group --from-beginning --consumer-property enable.auto.commit=false
</code></pre>
<p>注意,在这段命令中,我们指定了 group 信息。如果没有指定的话,每次运行 Console Consumer它都会自动生成一个新的消费者组来消费。久而久之你会发现你的集群中有大量的以 console-consumer 开头的消费者组。通常情况下,你最好还是加上 group。</p>
<p>另外from-beginning 等同于将 Consumer 端参数 auto.offset.reset 设置成 earliest表明我想从头开始消费主题。如果不指定的话它会默认从最新位移读取消息。如果此时没有任何新消息那么该命令的输出为空你什么都看不到。</p>
<p>最后,我在命令中禁掉了自动提交位移。通常情况下,让 Console Consumer 提交位移是没有意义的,毕竟我们只是用它做一些简单的测试。</p>
<h3>测试生产者性能</h3>
<p>如果你想要对 Kafka 做一些简单的性能测试。那么不妨试试下面这一组工具。它们分别用于测试生产者和消费者的性能。</p>
<p>我们先说测试生产者的脚本:<strong>kafka-producer-perf-test</strong>。它的参数有不少,但典型的命令调用方式是这样的。</p>
<pre><code>$ bin/kafka-producer-perf-test.sh --topic test-topic --num-records 10000000 --throughput -1 --record-size 1024 --producer-props bootstrap.servers=kafka-host:port acks=-1 linger.ms=2000 compression.type=lz4
2175479 records sent, 435095.8 records/sec (424.90 MB/sec), 131.1 ms avg latency, 681.0 ms max latency.
4190124 records sent, 838024.8 records/sec (818.38 MB/sec), 4.4 ms avg latency, 73.0 ms max latency.
10000000 records sent, 737463.126844 records/sec (720.18 MB/sec), 31.81 ms avg latency, 681.00 ms max latency, 4 ms 50th, 126 ms 95th, 604 ms 99th, 672 ms 99.9th.
</code></pre>
<p>上述命令向指定主题发送了 1 千万条消息,每条消息大小是 1KB。该命令允许你在 producer-props 后面指定要设置的生产者参数,比如本例中的压缩算法、延时时间等。</p>
<p>该命令的输出值得好好说一下。它会打印出测试生产者的吞吐量 (MB/s)、消息发送延时以及各种分位数下的延时。一般情况下,消息延时不是一个简单的数字,而是一组分布。或者说,<strong>我们应该关心延时的概率分布情况,仅仅知道一个平均值是没有意义的</strong>。这就是这里计算分位数的原因。通常我们关注到<strong>99th 分位</strong>就可以了。比如在上面的输出中99th 值是 604ms这表明测试生产者生产的消息中有 99% 消息的延时都在 604ms 以内。你完全可以把这个数据当作这个生产者对外承诺的 SLA。</p>
<h3>测试消费者性能</h3>
<p>测试消费者也是类似的原理,只不过我们使用的是<strong>kafka-consumer-perf-test</strong>脚本,命令如下:</p>
<pre><code>$ bin/kafka-consumer-perf-test.sh --broker-list kafka-host:port --messages 10000000 --topic test-topic
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
2019-06-26 15:24:18:138, 2019-06-26 15:24:23:805, 9765.6202, 1723.2434, 10000000, 1764602.0822, 16, 5651, 1728.1225, 1769598.3012
</code></pre>
<p>虽然输出格式有所差别,但该脚本也会打印出消费者的吞吐量数据。比如本例中的 1723MB/s。有点令人遗憾的是它没有计算不同分位数下的分布情况。因此在实际使用过程中这个脚本的使用率要比生产者性能测试脚本的使用率低。</p>
<h3>查看主题消息总数</h3>
<p>很多时候我们都想查看某个主题当前的消息总数。令人惊讶的是Kafka 自带的命令竟然没有提供这样的功能,我们只能“绕道”获取了。所谓的绕道,是指我们必须要调用一个未被记录在官网上的命令。命令如下:</p>
<pre><code>$ bin/kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list kafka-host:port --time -2 --topic test-topic
test-topic:0:0
test-topic:1:0
$ bin/kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list kafka-host:port --time -1 --topic test-topic
test-topic:0:5500000
test-topic:1:5500000
</code></pre>
<p>我们要使用 Kafka 提供的工具类<strong>GetOffsetShell</strong>来计算给定主题特定分区当前的最早位移和最新位移将两者的差值累加起来就能得到该主题当前总的消息数。对于本例来说test-topic 总的消息数为 5500000 + 5500000等于 1100 万条。</p>
<h3>查看消息文件数据</h3>
<p>作为 Kafka 使用者,你是不是对 Kafka 底层文件里面保存的内容很感兴趣? 如果是的话,你可以使用 kafka-dump-log 脚本来查看具体的内容。</p>
<pre><code>$ bin/kafka-dump-log.sh --files ../data_dir/kafka_1/test-topic-1/00000000000000000000.log
Dumping ../data_dir/kafka_1/test-topic-1/00000000000000000000.log
Starting offset: 0
baseOffset: 0 lastOffset: 14 count: 15 baseSequence: -1 lastSequence: -1 producerId: -1 producerEpoch: -1 partitionLeaderEpoch: 0 isTransactional: false isControl: false position: 0 CreateTime: 1561597044933 size: 1237 magic: 2 compresscodec: LZ4 crc: 646766737 isvalid: true
baseOffset: 15 lastOffset: 29 count: 15 baseSequence: -1 lastSequence: -1 producerId: -1 producerEpoch: -1 partitionLeaderEpoch: 0 isTransactional: false isControl: false position: 1237 CreateTime: 1561597044934 size: 1237 magic: 2 compresscodec: LZ4 crc: 3751986433 isvalid: true
......
</code></pre>
<p>如果只是指定 --files那么该命令显示的是消息批次RecordBatch或消息集合MessageSet的元数据信息比如创建时间、使用的压缩算法、CRC 校验值等。</p>
<p><strong>如果我们想深入看一下每条具体的消息,那么就需要显式指定 --deep-iteration 参数</strong>,如下所示:</p>
<pre><code>$ bin/kafka-dump-log.sh --files ../data_dir/kafka_1/test-topic-1/00000000000000000000.log --deep-iteration
Dumping ../data_dir/kafka_1/test-topic-1/00000000000000000000.log
Starting offset: 0
baseOffset: 0 lastOffset: 14 count: 15 baseSequence: -1 lastSequence: -1 producerId: -1 producerEpoch: -1 partitionLeaderEpoch: 0 isTransactional: false isControl: false position: 0 CreateTime: 1561597044933 size: 1237 magic: 2 compresscodec: LZ4 crc: 646766737 isvalid: true
| offset: 0 CreateTime: 1561597044911 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 1 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 2 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 3 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 4 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 5 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 6 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 7 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 8 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 9 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 10 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 11 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 12 CreateTime: 1561597044932 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 13 CreateTime: 1561597044933 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
| offset: 14 CreateTime: 1561597044933 keysize: -1 valuesize: 1024 sequence: -1 headerKeys: []
baseOffset: 15 lastOffset: 29 count: 15 baseSequence: -1 lastSequence: -1 producerId: -1 producerEpoch: -1 partitionLeaderEpoch: 0 isTransactional: false isControl: false position: 1237 CreateTime: 1561597044934 size: 1237 magic: 2 compresscodec: LZ4 crc: 3751986433 isvalid: true
......
</code></pre>
<p>在上面的输出中,以竖线开头的就是消息批次下的消息信息。如果你还想看消息里面的实际数据,那么还需要指定 <strong>--print-data-log 参数</strong>,如下所示:</p>
<pre><code>$ bin/kafka-dump-log.sh --files ../data_dir/kafka_1/test-topic-1/00000000000000000000.log --deep-iteration --print-data-log
</code></pre>
<h3>查询消费者组位移</h3>
<p>接下来,我们来看如何使用 kafka-consumer-groups 脚本查看消费者组位移。在上一讲讨论重设消费者组位移的时候,我们使用的也是这个命令。当时我们用的是 <strong>--reset-offsets 参数</strong>,今天我们使用的是 <strong>--describe 参数</strong>。假设我们要查询 Group ID 是 test-group 的消费者的位移,那么命令如图所示:</p>
<p><img src="assets/f4b7d92cdebff84998506afece1f61ee.png" alt="img" /></p>
<p>图中的 CURRENT-OFFSET 表示该消费者当前消费的最新位移LOG-END-OFFSET 表示对应分区最新生产消息的位移LAG 列是两者的差值。CONSUMER-ID 是 Kafka 消费者程序自动生成的一个 ID。截止到 2.2 版本,你都无法干预这个 ID 的生成过程。如果运行该命令时,这个消费者程序已经终止了,那么此列的值为空。</p>
<h2>小结</h2>
<p>好了,我们小结一下。今天我们一起梳理了 Kafka 2.2 版本自带的所有脚本,我给出了常见的运维操作的工具行命令。希望这些命令对你操作和管理 Kafka 集群有所帮助。另外,我想强调的是,由于 Kafka 依然在不断演进,我们今天提到的命令的用法很可能会随着版本的变迁而发生变化。在具体使用这些命令时,你最好详细地阅读一下它们的 Usage 说明。</p>
<p><img src="assets/5b0daf262cde0c853a5cf9fbc9dfa332.jpg" alt="img" /></p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/Kafka核心技术与实战/30 怎么重设消费者组位移?.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/Kafka核心技术与实战/32 KafkaAdminClientKafka的运维利器.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"7099721139163d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>