Ubuntu 20.04 上 Kafka 3.6.0 深度部署与实战排雷手册
如果你正准备在 Ubuntu 20.04 上搭建 Kafka 3.6.0,并且已经看腻了那些“一帆风顺”的教程,那么你来对地方了。这篇文章不会只告诉你“输入什么命令”,而是会聚焦于那些让新手开发者抓狂的“坑”——从 Java 版本兼容性这个隐形杀手,到配置文件里一个标点符号引发的血案,再到端口冲突、权限不足这些看似简单却极易踩雷的环节。我们将以实战为导向,模拟一个真实的部署场景,手把手带你验证每一个关键步骤,并最终使用 Kafka Assistant 和 IDEA 两款工具,从不同维度验证你的消息队列服务是否真正健康、可用。无论你是为了本地开发测试,还是为生产环境做准备,这份避坑指南都能帮你节省大量排查问题的时间。
1. 环境预检:别让 Java 成为你的第一个“惊喜”
很多教程会轻描淡写地告诉你“需要 Java 环境”,但 Kafka 3.6.0 对 Java 版本有明确的要求。直接安装默认的 OpenJDK 11 可能没问题,但如果你系统里残留着其他版本,或者使用了某些特定的 JVM 参数,麻烦可能就开始了。
1.1 精准验证 Java 环境
首先,别急着 java -version 看一眼就过。我们需要进行更细致的检查。
# 检查默认 Java 版本和具体路径
java -version
which java
readlink -f $(which java)
这能帮你确认当前 shell 环境使用的到底是哪个 Java 安装。接下来,检查所有已安装的 Java 版本:
# 对于使用 update-alternatives 管理的系统(如 Ubuntu)
sudo update-alternatives --config java
你会看到一个选择列表。Kafka 官方推荐使用 Java 8、11、17 或 21。对于 Kafka 3.6.0,我个人在生产环境更倾向于使用 Java 11 (LTS),它在稳定性和性能上有一个不错的平衡。如果你需要安装或切换:
# 安装 OpenJDK 11
sudo apt update
sudo apt install openjdk-11-jdk -y
# 配置系统默认版本为 Java 11
sudo update-alternatives --config java
# 在弹出的菜单中选择对应的 Java 11 选项编号
注意:如果你在服务器上运行,请确保
JAVA_HOME环境变量已正确设置,因为某些脚本或服务可能会依赖它。可以通过echo $JAVA_HOME检查,如果为空,需要将其添加到~/.bashrc或/etc/environment中。
1.2 系统资源与依赖检查
Kafka 和 Zookeeper 在启动时会对系统资源有一定要求。一个常见的“坑”是默认的文件描述符限制太低,可能导致连接数上去后出现“Too many open files”错误。
# 查看当前用户的文件描述符限制
ulimit -n
# 如果数值较小(如1024),建议临时提高以进行测试,或永久修改系统限制
# 临时提高(仅当前会话有效)
ulimit -n 65536
对于生产环境,你还需要关注内存。Kafka 默认的 JVM 堆内存设置可能不适合你的数据量。我们可以在下载 Kafka 后,预先修改其启动脚本中的内存参数。
2. 获取与解压 Kafka:避开下载与路径的陷阱
直接从官网下载是最稳妥的方式,但网络环境可能导致下载缓慢或中断。这里有几个备选方案。
2.1 可靠下载与完整性校验
使用 wget 下载时,建议增加重试次数和超时设置,并务必校验文件完整性。
# 使用 wget 下载,增加稳健性
wget -c -t 3 -T 60 https://dlcdn.apache.org/kafka/3.6.0/kafka_2.12-3.6.0.tgz
# 下载完成后,强烈建议验证 SHA512 校验和(从官网获取对应版本的校验和文件)
wget https://downloads.apache.org/kafka/3.6.0/kafka_2.12-3.6.0.tgz.sha512
sha512sum -c kafka_2.12-3.6.0.tgz.sha512
如果校验失败,文件可能损坏,需要重新下载。-c 参数支持断点续传,这在网络不稳定时非常有用。
2.2 规划安装目录与权限
解压到哪个目录?这看似简单,却影响着后续的配置和运维。我不建议放在个人家目录下,特别是对于打算长期运行的服务。
# 假设我们规划 /opt 作为中间件目录
sudo mkdir -p /opt/kafka
sudo chown -R $USER:$USER /opt/kafka # 将所有权赋予当前用户,避免后续操作频繁使用sudo
# 解压到目标目录
tar -xzf kafka_2.12-3.6.0.tgz -C /opt/kafka --strip-components=1
cd /opt/kafka
使用 --strip-components=1 可以去掉压缩包最外层的版本号目录,让 /opt/kafka 直接就是 Kafka 的根目录,管理起来更清晰。现在,你的目录结构应该是这样的:
/opt/kafka/
├── bin/
├── config/
├── libs/
└── ...
3. 关键配置详解:每个参数都可能是个“坑”
config/server.properties 是 Kafka 的核心。网上很多教程给的配置示例过于简单,直接拷贝可能无法运行或存在安全隐患。
3.1 必须修改的核心参数
我们用 vim 或 nano 打开配置文件,重点关注以下几项:
# 重点配置项解析
broker.id=0 # 集群中每个 broker 的唯一 ID,单机可设为 0。
# 监听器配置 - 最容易出错的地方!
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://你的服务器IP:9092
listeners: Kafka 真正绑定监听的地址和端口。0.0.0.0表示监听所有网络接口,这样你才能从本机以外的机器连接。如果只设127.0.0.1,那么只有本机可以访问。advertised.listeners: 客户端(生产者、消费者)连接时使用的地址。如果这个地址客户端无法访问,连接就会失败。在单机测试时,可以都设为localhost:9092。但如果你的客户端运行在另一台机器(比如你的开发机),这里就必须填写服务器的 真实IP地址 或 可解析的主机名。
提示:如果你在云服务器(如 AWS EC2、阿里云 ECS)上部署,
advertised.listeners需要设置为云服务器的内网IP(供集群内通信)或公网IP(供外部客户端访问),并确保安全组/防火墙开放了 9092 端口。
3.2 数据目录与日志策略
默认日志目录在 /tmp 下,系统重启可能会被清理,必须修改。
# 修改日志存储目录
log.dirs=/opt/kafka/data-logs
创建这个目录并确保 Kafka 进程有写入权限:
mkdir -p /opt/kafka/data-logs
日志保留策略决定了你的数据能存多久、占多少空间。根据你的磁盘空间和业务需求调整:
# 日志保留策略:时间与大小限制,哪个先到就触发哪个
log.retention.hours=168 # 保留7天
log.retention.bytes=10737418240 # 单个分区日志段最大10GB
delete.topic.enable=true # 允许删除主题(谨慎开启,生产环境建议false)
3.3 Zookeeper 连接配置
Kafka 3.6.0 依然依赖 Zookeeper 进行元数据管理(虽然新版本在向 KRaft 模式迁移)。确保连接信息正确。
zookeeper.connect=localhost:2181
如果你将 Zookeeper 也部署在同一台机器,保持默认即可。如果 Zookeeper 是集群,格式应为 ip1:port1,ip2:port2,ip3:port3。
4. 启动与验证:从进程到端口的全面诊断
配置好后,启动顺序不能错:先 Zookeeper,后 Kafka。
4.1 启动服务并检查进程
建议在 screen 或 tmux 会话中启动,以便观察启动日志。
# 启动 Zookeeper (以后台方式运行,并将日志输出到文件)
nohup bin/zookeeper-server-start.sh config/zookeeper.properties > zookeeper.log 2>&1 &
# 等待几秒,确保 Zookeeper 启动完成,再启动 Kafka
sleep 5
nohup bin/kafka-server-start.sh config/server.properties > kafka.log 2>&1 &
现在,检查进程是否存活:
ps -ef | grep -E \"(zookeeper|kafka)\" | grep -v grep
你应该看到两个 Java 进程。如果只有 Zookeeper 没有 Kafka,或者进程很快消失,问题通常出在配置或端口冲突上。第一时间查看日志:
tail -f kafka.log
4.2 诊断端口冲突与网络连通性
Kafka 默认用 9092 端口,Zookeeper 用 2181 端口。它们可能被其他程序占用。
# 检查端口是否被监听,以及监听地址是否正确
sudo netstat -tlnp | grep -E \":(2181|9092)\"
# 或者使用更现代的 ss 命令
sudo ss -tlnp | grep -E \":(2181|9092)\"
期望的输出应该显示 Java 进程正在监听 0.0.0.0:9092 和 :::2181 或 0.0.0.0:2181。如果看到的是 127.0.0.1:9092,说明你的 listeners 配置没改对。
接下来,从本机测试连通性:
# 测试 Zookeeper 端口
telnet localhost 2181
# 输入 `stat` 后回车,能看到 Zookeeper 版本信息即表示连接正常。
# 测试 Kafka 端口
telnet localhost 9092
# 能连接上(看到空白屏幕或尝试输入字符)即可,然后按 Ctrl+] 再输入 quit 退出。
如果 telnet 连接失败,检查防火墙:
# 查看 Ubuntu 防火墙状态
sudo ufw status
如果防火墙是激活状态,需要开放端口:
sudo ufw allow 2181/tcp
sudo ufw allow 9092/tcp
5. 基础功能测试:用命令行验证核心流程
服务跑起来且端口可访问,只是第一步。我们需要用 Kafka 自带的命令行工具走一遍生产消费的全流程,这是验证服务是否“健康”的金标准。
5.1 创建主题(Topic)
主题是消息的逻辑分类。创建时需要考虑分区数和副本因子。
cd /opt/kafka
# 创建一个名为 `quickstart-events` 的主题,1个分区,1个副本(单机只能为1)
bin/kafka-topics.sh --create \
--bootstrap-server localhost:9092 \
--topic quickstart-events \
--partitions 1 \
--replication-factor 1
成功会提示 Created topic quickstart-events.。如果报错 Connection refused,回到上一步检查 Kafka 进程和端口。如果报错 Replication factor must be larger than 0,说明你的 --bootstrap-server 地址可能不对,或者 Kafka 还没完全启动好。
查看主题详情,确认创建成功:
bin/kafka-topics.sh --describe \
--bootstrap-server localhost:9092 \
--topic quickstart-events
输出应包含主题名、分区数、副本分布等信息。
5.2 生产与消费消息
现在打开两个终端窗口,模拟生产者和消费者。
终端 A (生产者):
cd /opt/kafka
bin/kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic quickstart-events
输入提示符 > 会出现,此时你可以输入几条消息:
>Hello, Kafka!
>This is a test message.
>Goodbye.
每输入一行按回车,消息就被发送到 Kafka 了。按 Ctrl+C 退出。
终端 B (消费者):
cd /opt/kafka
bin/kafka-console-consumer.sh \
--bootstrap-server localhost:9092 \
--topic quickstart-events \
--from-beginning
--from-beginning 参数表示从这个主题最早的消息开始消费。你应该会立刻看到在终端 A 中输入的所有消息。如果没有,检查两个终端连接的 --bootstrap-server 地址是否一致,并且确保消费者命令是在生产者发送消息之后启动的(或者使用了 --from-beginning)。
保持消费者终端运行,再回到生产者终端发送新消息,观察消费者终端是否能实时接收到。这是验证 Kafka 实时消息传递能力的关键。
6. 图形化工具实战:Kafka Assistant 与 IDEA 双保险
命令行测试通过,证明服务基础功能正常。但对于日常开发和调试,图形化工具更直观。我们分别用 Kafka Assistant(独立客户端)和 IDEA 插件来验证,这也能模拟不同客户端连接的情况。
6.1 使用 Kafka Assistant 进行管理
Kafka Assistant 是一款功能丰富的桌面客户端。连接时,最关键的点就是 Bootstrap Servers 地址。
- 连接配置:在连接设置中,输入
你的服务器IP:9092(例如192.168.1.100:9092)。如果是在本机,可以用localhost:9092。 - 验证连接:点击连接后,如果成功,左侧会列出所有 Topic,包括我们刚创建的
quickstart-events。 - 查看详情:
- 点击
quickstart-events,可以查看分区信息、消息数量。 - 在消息浏览器中,可以直接查看我们之前发送的
Hello, Kafka!等消息内容。 - 可以尝试在这里直接发送新消息,然后用命令行消费者验证是否能收到。
- 点击
注意:如果 Kafka Assistant 连接失败,而命令行工具可以连接,99% 的问题出在
advertised.listeners配置上。Kafka Assistant 作为外部客户端,会使用这个地址去连接,请确保这个地址在 Kafka Assistant 所在的机器上是可访问的。
6.2 在 IDEA 中集成测试
对于 Java 开发者,在 IDEA 里直接测试 Kafka 非常方便。你可以创建一个简单的 Java 测试类,使用 Kafka 客户端库。
首先,在你的 Maven 或 Gradle 项目中添加依赖:
<!-- Maven 依赖示例 -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.6.0</version>
</dependency>
然后,编写一个简单的生产者和消费者测试代码。这里的关键同样是 bootstrap.servers 配置属性。
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.clients.consumer.*;
import java.util.Properties;
import java.time.Duration;
import java.util.Collections;
public class SimpleKafkaTest {
private static final String BOOTSTRAP_SERVERS = "192.168.1.100:9092"; // 替换为你的地址
private static final String TOPIC = "idea-test-topic";
public static void main(String[] args) throws InterruptedException {
// 1. 创建主题(如果不存在,需确保允许自动创建,或先用命令行创建)
// 2. 运行生产者
runProducer();
// 3. 运行消费者
runConsumer();
}
static void runProducer() {
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
try (Producer<String, String> producer = new KafkaProducer<>(props)) {
ProducerRecord<String, String> record = new ProducerRecord<>(TOPIC, "key1", "Hello from IDEA!");
producer.send(record, (metadata, exception) -> {
if (exception == null) {
System.out.printf("Message sent to topic %s, partition %d, offset %d%n",
metadata.topic(), metadata.partition(), metadata.offset());
} else {
exception.printStackTrace();
}
});
producer.flush(); // 确保消息发送完成
}
}
static void runConsumer() {
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS);
props.put(ConsumerConfig.GROUP_ID_CONFIG, "idea-test-group");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); // 从最早的消息开始读
try (Consumer<String, String> consumer = new KafkaConsumer<>(props)) {
consumer.subscribe(Collections.singletonList(TOPIC));
ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(5));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("Consumed message: key = %s, value = %s, partition = %d, offset = %d%n",
record.key(), record.value(), record.partition(), record.offset());
}
}
}
}
在 IDEA 中运行这个程序。观察控制台输出,如果能看到 “Message sent…” 和 “Consumed message: … Hello from IDEA!” 的日志,恭喜你,从 Java 客户端到 Kafka 服务器的整个通路已经完全打通。
7. 进阶排查与优化建议
走完上述流程,你的 Kafka 应该已经稳定运行了。但在长期使用前,还有几个深水区需要注意。
7.1 常见错误与解决方案
这里汇总几个我遇到过的典型问题:
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
java.net.UnknownHostException | advertised.listeners 使用了主机名,但客户端无法解析。 | 在客户端机器的 hosts 文件中添加映射,或直接使用 IP 地址。 |
Connection refused | Kafka 进程未启动;防火墙阻止;listeners 绑定地址错误。 | 检查进程、端口监听状态 (netstat)、防火墙规则。 |
| 生产者发送成功,消费者收不到 | 消费者组 (group.id) 不同,且未设置 auto.offset.reset=earliest。 | 确保消费者能正确加入消费组,或指定从开始消费。 |
| 日志目录权限错误 | Kafka 进程用户对 log.dirs 目录没有写权限。 | 使用 chown 和 chmod 修正目录权限。 |
| 启动时报内存不足 | 默认 JVM 内存设置过小或过大。 | 修改 bin/kafka-server-start.sh 中的 KAFKA_HEAP_OPTS 变量。 |
7.2 性能与监控初探
对于单机开发环境,你可能不关心性能。但了解基本监控方式有益无害。
- 查看服务器状态:使用
jconsole或jvisualvm连接 Kafka 的 Java 进程,可以观察堆内存、线程状态。 - Kafka 自带工具:
这个命令的输出能告诉你消费组是否滞后(Lag),这是判断消费者是否健康的重要指标。# 查看所有消费组 bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list # 查看特定消费组的消费偏移量详情 bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group idea-test-group --describe
7.3 安全关闭服务
不要直接用 kill -9,这可能导致数据损坏。正确关闭顺序是:先停 Kafka,再停 Zookeeper。
# 在 Kafka 目录下
bin/kafka-server-stop.sh
# 等待一段时间(如30秒),再停止 Zookeeper
bin/zookeeper-server-stop.sh
可以用 ps -ef | grep 命令确认进程都已退出。
折腾完这一整套,从环境检查、配置调优、启动验证到多工具测试,你应该对 Kafka 在 Ubuntu 上的部署有了肌肉记忆。最深的体会就是,日志 (kafka.log 和 zookeeper.log) 是你最好的朋友,任何问题第一时间看日志,能解决 90% 的疑惑。另外,对于 listeners 和 advertised.listeners 的理解,是区分“照抄教程”和“真正掌握”的关键,特别是在涉及网络访问的时候。下次如果遇到客户端连不上的问题,先从这里开始排查,准没错。
456



被折叠的 条评论
为什么被折叠?



