我们有一个 Kafka 测试环境集群,部署在完全隔离的内网环境中,内网其他网络无法直接访问。
但我们的内网应用需要接入这个集群进行联调测试。于是尝试通过 Nginx 做反向代理,让内网应用“间接”消费 Kafka 数据。
客户端配置的
bootstrap.servers=nginx代理地址
例如 nginx-host:30001
UnknownHostException
、Connection refused
等类似网络不可达问题排查一圈,发现是 Kafka 自己搞自己。
Kafka 的机制是这样的:
你连上一个 broker 后,它会返回整个集群的元数据(metadata)也就是隔离局域网的地址,这样客户端就报错了
你连上去之后,它会告诉你:“我还有两个broker,一个叫
kafka-test2:30002
,一个叫kafka-test3:30003
,你们直接联系。”
但问题来了:
这些地址全是内网主机名! 外部系统根本找不到
kafka-test2
是谁,网络不通,直接报错
Nginx 只代理了第一个连接,后续 broker 直连失败
既然 Kafka 会返回多个 broker 地址,那我们就得让这些地址都能被代理。
思路是:
让内部应用系统访问 kafka-test1/kafka-test2/kafka-test3 时,全都走 Nginx 代理。 Nginx TCP 代理 + 客户端
hosts
Broker | 监听端口 |
---|---|
kafka-test1 | 30001 |
kafka-test2 | 30002 |
kafka-test3 | 30003 |
在 Nginx 的 stream
模块中为每个节点配置独立的 TCP 代理:
stream
)确保 Nginx 主配置文件中启用了 stream
模块
# /etc/nginx/nginx.conf
stream {
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
access_log logs/stream_access.log main;
include stream-conf.d/*.stream;
}
创建独立配置文件,例如 kafka-test1.stream
:
[root@a-1 proxy]# cat kafka-test1.stream
#kafka-test1
server {
listen 30001;
include /etc/nginx/conf.d/whitelist.conf;
deny all;
proxy_pass kafka-test1:30001;
}
#kafka-test2
server {
listen 30002;
include /etc/nginx/conf.d/whitelist.conf;
deny all;
proxy_pass kafka-test2:30002;
}
#kafka-test3
server {
listen 30003;
include /etc/nginx/conf.d/whitelist.conf;
deny all;
proxy_pass kafka-test3:30003;
}
nginx也要配置hosts 确保 Nginx 能解析
kafka-test1/2/3
主机名。
内网其他网络请求进来,先过 Nginx,再转发到真实的 Kafka 节点。
最关键的一步来了——
在应用端服务器的 hosts
文件里加上:
<nginxIP> kafka-test1
<nginxIP> kafka-test2
<nginxIP> kafka-test3
这样一来,
比如应用端访问 kafka-test1:30001
,其实是连到了 Nginx;
Kafka 返回 kafka-test2:30002
,应用端照样通过 hosts
解析到 Nginx IP
proxy_pass
转发到真实的 kafka-test2:30002
整个过程,应用端毫无感知
为了防止未授权访问,我们在 Nginx 中加入了 IP 白名单控制。
我们在 Nginx 里加了白名单控制:
只有在白名单内的 IP 才能访问,其他一律拒绝。
以30003端口配置为例
server {
listen 30003;
include /etc/nginx/conf.d/whitelist.conf; # 包含白名单文件
deny all; # 默认拒绝所有
proxy_pass kafkade-test3:30003;
}
include
是 Nginx 的模块化语法,提升配置可维护性。
whitelist.confallow x.x.x.x; #允许单个IP
allow x.x.x.x/24; #允许整个子网
每新增一个消费者,都要手动修改 hosts 文件
所以不建议在生产环境这么搞
这么折腾一圈,虽然只是在测试环境的临时方案,但实实在在搞懂了 Kafka 的通信机制,也顺手实践了 Nginx 的 stream
模块和 IP 白名单控制。
对于我们这种测试环境能凑合。
#Kafka
#Nginx