论如何解决类似如 '''使用 openresty 库 lua-resty-kafka 对接kafka 报错 no resolver defined to resolve "xxx" ''' 的问题

始苦寻无果,终幸得其所

参考项目的issue

https://github.com/doujiang24/lua-resty-kafka/issues/5

这个issue已经将问题说的很明白了
在我电脑上当时的表现就是lua从kafka获取到的broker的host一直是ubuntu
而我明明给lua中配置的host是ip地址。
而ubuntu这个域名在/etc/hosts中有设置,但是在我去掉域名解析,重启电脑之后,还是没有解决。
因为有这个被动ip转成了本地域名的灵异现象存在,使得lua-resty-kafka库无法解析域名,导致生产者无法向kafka推送数据。

而解决办法则是在kafka的配置文件 server.properties中设置

host.name= {你的ip或域名}


更新: 原因研究

根据:kafka主机名解析hostname

我们查看zookeeper中关于kafka的brokers的信息

[zk: localhost:2181(CONNECTED) 0] get /brokers/ids/0
{“listener_security_protocol_map”:{“PLAINTEXT”:“PLAINTEXT”},“endpoints”:[“PLAINTEXT://ubuntu:9092”],“jmx_port”:-1,“host”:“ubuntu”,“timestamp”:“1584515322686”,“port”:9092,“version”:4}

从中果然发现了ubuntu:9092,所以问题出在zookeeper。

然后继续搜索,找到
如何避免将Kafka broker机器的hostname注册进zookeeper

其中提到了配置文件的注释提示信息,翻回去一看

# Hostname and port the broker will advertise to producers and consumers. If not set,
# it uses the value for “listeners” if configured. Otherwise, it will use the value
# returned from java.net.InetAddress.getCanonicalHostName().
#advertised.listeners=PLAINTEXT://your.host.name:9092

果然,如果没有配置就使用java.net.InetAddress.getCanonicalHostName()获得。
到服务器上使用命令执行一看

java> java.net.InetAddress.getLocalHost().getCanonicalHostName();
java.lang.String res0 = "ubuntu"

果然如此!


那么getLocalHost又是怎么得到的hostname呢,根据IDE的调试功能最终得到
public native String getLocalHostName() throws UnknownHostException;
定义,这是一个native方法,调用的是Java_java_net_Inet6AddressImpl_getLocalHostName方法

根据:JVM源码系列: java InetAddress.getLocalHost() 在linux里实现

得知是根据系统的hostname决定的

使用了hostname xxx临时改变机器hostname之后,测试发现果然如此。

java得到的hostname也变了。


那么要亲眼看一下:
下载openjdk的jdk8源码,查看到 jdk-83bbe56ecea1\src\solaris\native\java\net\Inet6AddressImpl.c文件下的68行为
Java_java_net_Inet6AddressImpl_getLocalHostName

JNIEXPORT jstring JNICALL
Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) 

其中有一个JVM_GetHostName是被博客们广泛查看的。
那么找到这个函数的定义,在jdk-83bbe56ecea1\src\share\javavm\export\jvm.h
中第1302行

JNIEXPORT int JNICALL
JVM_GetHostName(char* name, int namelen);

但是要继续寻找就不能在这里了。
在查看了JNI/NDK开发指南(一)—— JNI开发流程及HelloWorld 之后得知要想明白这个方法更具体的定义要去Java编译器中,那么让我们去下载JVM虚拟机中的源码。


从openjdk官网下载java8的 hotspot源码。
经过查找,发现在hotspot-d17814ea88e3\src\share\vm\prims\jvm.cpp的第4062行

JVM_LEAF(int, JVM_GetHostName(char* name, int namelen))
  JVMWrapper("JVM_GetHostName");
  return os::get_host_name(name, namelen);
JVM_END

也就是博客们俗称的宏定义,怪我,完全不知道这玩意在这种地方。
其中我们发现一个os域下的get_host_name方法。
然后寻找到hotspot-d17814ea88e3\src\share\vm\runtime\os.hpp中的第753行。

static int get_host_name(char* name, int namelen);


hotspot-d17814ea88e3\src\os\linux\vm\os_linux.inline.hpp中第225行

inline int os::get_host_name(char* name, int namelen) {
  return ::gethostname(name, namelen);
}

问题就出在这个::gethostname(name, namelen)函数
这是一个系统级的函数


待查

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值