关键词: kafka , ubuntu , frp

参考的文章

背景

我有一台公网机器,但是机器的性能不好,无法安装 kafka,但是我的工作中又有大量的需要用到 kafka 的时候,家里有一台性能还不错的工作站,装的是 ubuntu 20.04, 之前的文章里提到了用 frp 内网穿透在工作站部署服务,通过外网服务器提供服务,既然 http 服务可以这么处理,那么其他类型的服务应该也可以,所以打算在内网部署一套 kafka 供工作服务测试使用。

现把步骤梳理一下,先不讲解为什么一些步骤要按照这样搞,最后写原因。

frp

frp 如何安装以及配置在之前的文章里也写过了,这里不过多的赘述, 当涉及到 frp 的时候,我就只贴配置了

公网机器

frp

公网 frp 的配置见之前的文档

hosts

#  配置映射
#  x.x.x.x 为阿里云服务器的内网 ip 
#  y.y.y.y 为阿里云服务器的公网 ip 
#  kafka.com 为内网环境 kafka ——> advertised.listeners 配置的内网域名
x.x.x.x kafka.com
y.y.y.y kafka.com

内网机器

frp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[common]
server_addr = y.y.y.y 
server_port = 7000
token = 123456

[kafka]
type = tcp
local_ip = z.z.z.z
local_port = 9092
remote_port = 9092

hosts

#  配置映射
#  z.z.z.z 为内网环境 kafka 的 ip, 可以认为就是内网机器的内网 ip
#  kafka.com 为内网环境 kafka ——> advertised.listeners 配置的内网域名
z.z.z.z kafka.com

docker-comose.yaml

我为了方便,在内网中使用了 docker-compse 部署了 kafka,贴一下对应的配置。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.7'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    volumes:
      - ./data:/data
    ports:
      - 2182:2181

  kafka9094:
    image: wurstmeister/kafka
    ports:
      - 9092:9092
    environment:
      KAFKA_BROKER_ID: 0
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka.com:9092  ## 特别注意这里用的是 kafka.com 域名,就是我们 hosts 里配的域名
      KAFKA_CREATE_TOPICS: ""
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
    volumes:
      - ./kafka-logs:/kafka
    depends_on:
      - zookeeper

然后 docker-compose up -d 启动就好,注意一定要在 hosts 里配置好内网域名对应 kafka.com 后才能启动,不然一定会出错。

producer & consumer 机器

hosts

#  y.y.y.y 为阿里云服务器的公网 ip 
#  kafka.com 为内网环境 kafka ——> advertised.listeners 配置的内网域名
y.y.y.y kafka.com

一定要配置好公网 ip 对应 kafka 的域名。

然后 producer & consumer 调用时用 kafka.com 即可

producer & consumer

1
brokerList = kingpin.Flag("brokerList", "List of brokers to connect").Default("kafka.com:9092").Strings()

理顺

当我们在 producer 发送消息时,用了 kafka.com 根据 hosts 会路由到 y.y.y.y 机器,也就是我们的公网机器,然后公网机器因为部署了内网穿透,所以 9092 端口会发送到内网机器的 9092 端口,同时因为公网机器的 hosts 里也配置了 y.y.y.y 到 kafka.com 映射,因此到了内网后还是用的 kafka.com 进行的,而内网也配置了 z.z.z.z 到 kafka.com 的映射,因此访问的就是 z.z.z.z,这样整个流程就串起来了。

原理

advertised.listeners=PLAINTEXT://kafka.com:9092 配置的地址必须要能连通,一般配置为外网地址,因为 kafka 会将这个 ip 和 port 记录在 zookeeper 上,当外网访问时直接通过这个地址连接(如果未配置这个参数,则外网会拿到内网的 IP,从而无法访问)

   但是由于 frp 的特殊性,frp 映射之后,只能外网的服务器本身能访问,因为防火墙只开放了 22 远程端口 ,9092 并未开放 ,因此内网的 kafka 无法访问。所以需要配置一个内网域名 kafka.com,在内网服务器中配置映射(z.z.z.z kafka.com), 在 kafka 启动的时候,会去连接 kafka.com:9092 ,正常访问。而外网服务器在zookeeper 中找到 kafka.com:9092 的连接地址,也需要映射 (y.y.y.y  kafka.com) , 使得外网服务器也能通过 9092 端口正常访问,问题解决。

    kafka 端口 9092 必须与 frp 映射的一致。

advertised.listeners 在 kafka 启动时,必须要能连接,所以一定要配置成域名,然后在 host 配置映射。当在外网访问时,拿到这个域名,并且在外网本机配置 host 映射,从而正确访问。