由于项目需求,需要跨集群向kafka发数据,发数据程序所在集群没有配置目标kafka集群的主机名,所以只能使用目标集群的ip地址。经测试两个集群网络通信是没有问题的。但是发kafka数据程序运行一直报错,显示无法解析kafka主机名。
约定:由于跨集群发kafka数据,程序运行所在集群和目标kafka集群属于2个不同集群。为方便描述,程序运行所在集群简称为A集群,目标kafka集群为B集群。
final static String KAFKA_BROKER_LIST
= "172.25.102.70:9092,172.25.102.71:9092,172.25.102.72:9092,172.25.102.75:9092,172.25.102.76:9092";
Properties props = buildKafkaProperties(KAFKA_BROKER_LIST);
KafkaProducer producer = new KafkaProducer(props);
String to_topic = "liu-text-20200507";
String record = "message record";
producer.send(new ProducerRecord(to_topic,
null,
record));
producer.close();
//构造kafka配置参数
public static Properties buildKafkaProperties(String kafka_broker_list){
Properties props = new Properties();
props.put("bootstrap.servers", kafka_broker_list);
props.put("acks", "all"); //是否成功的标准
props.put("retries", "3"); //重试次数
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
return props;
}
由代码中可知,我传入的地址是ip,而不是目标kafka主机域名。
2020-05-07 11:41 WARN kafka-producer-network-thread | producer-1 clients.NetworkClient:873 - [Producer clientId=producer-1] Error connecting to node kafka-05:9092 (id: 115 rack: null)
java.io.IOException: Can't resolve address: kafka-05:9092
at org.apache.kafka.common.network.Selector.doConnect(Selector.java:235)
at org.apache.kafka.common.network.Selector.connect(Selector.java:214)
at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:864)
at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:265)
at org.apache.kafka.clients.producer.internals.Sender.sendProducerData(Sender.java:266)
at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:238)
at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:176)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.nio.channels.UnresolvedAddressException
at sun.nio.ch.Net.checkAddress(Net.java:101)
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:622)
at org.apache.kafka.common.network.Selector.doConnect(Selector.java:233)
... 7 more
错误提示未解析的地址异常,不认识主机域名 kafka-05!
注意:A,B集群为上文约定的简称
应当是构造kafkaproducer的时候,和B集群通信时,在B集群根据ip地址反解析了B集群的主机名列表,拿回到A集群,然后作为kafkaproducer的通信地址,结果查询A集群hosts,并没有找到这些主机名对应的ip地址,因此才报出错误。
debug程序时发现
a) 构造kafkaproducer的时候,的确会有反解析主机名的操作,不过时根据A集群本身的hosts配置,如果自己hosts并没有配置这些ip域名,则仍然使用ip列表作为地址。所以问题并不发生在本阶段
b) send数据时,kafkaproducer会和B集群kafka的broker进行通信,在B集群拿到了B集群的kafka主机域名,并更新kafkaproducer本身的通信地址。到真正发数据时,在A集群查询kafka主机域名时,发现并没有找到,然后又尝试一步步查询外网所有DNS域名服务器(这一步非常耗时!),结果还是没有查到,导致解析主机名失败,抛出异常!
注:kafkaproducer根据ip到达B集群,查询kafka broker元数据时,查询的是kafka配置的zookeeper,我们进入B集群的zookeeper,可以查看kafka元数据信息。
进入zookeeper命令窗口后,进行下列操作
[zk: localhost:2181(CONNECTED) 0] ls /brokers/ids
[201, 202, 203, 204, 205]
[zk: localhost:2181(CONNECTED) 1] get /brokers/ids/201
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://kafka-01:9092"],"jmx_port":9393,"host":"kafka-01","timestamp":"1585815634552","port":9092,"version":4}
可以看到每个kafka broker都可以查到host主机名和port端口号
在A集群上所有计算节点配上B集群kafka所有主机名映射ip,避免B集群反解析出域名,返回A集群解析这些kafka主机名失败。然后就可以愉快的向B集群kafka发数据了!