Spring boot 2.4.2 redisson报错问题排查

发布时间:2021-01-31 20:27:12阅读:(5007)

这几天我把项目里的spring boot升级到了最新版本:2.4.2,然后启动的时候发现redisson报错了,确切的说是redisson依赖的netty报错了。报错内容如下:

2021-01-31 20:01:30.788  WARN 1764 --- [           main] i.n.r.d.DnsServerAddressStreamProviders  : Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS.

java.lang.ClassNotFoundException: io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_251]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_251]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) ~[na:1.8.0_251]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_251]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_251]
at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_251]
at io.netty.resolver.dns.DnsServerAddressStreamProviders$1.run(DnsServerAddressStreamProviders.java:50) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_251]
at io.netty.resolver.dns.DnsServerAddressStreamProviders.<clinit>(DnsServerAddressStreamProviders.java:46) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at org.redisson.connection.MasterSlaveConnectionManager.<init>(MasterSlaveConnectionManager.java:203) [redisson-3.15.0.jar:3.15.0]
at org.redisson.connection.MasterSlaveConnectionManager.<init>(MasterSlaveConnectionManager.java:155) [redisson-3.15.0.jar:3.15.0]
at org.redisson.connection.SingleConnectionManager.<init>(SingleConnectionManager.java:34) [redisson-3.15.0.jar:3.15.0]
....

乍一看ClassNotFoundException很明显是少包了,但是maven导入都是正常的,于是我去找这个class在哪个包下,最终找到了这个包:

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-native-macos</artifactId>
</dependency>

然而,问题就这么解决了吗?显然不是。当我导完包一运行,发现报了另一个异常:

2021-01-31 20:11:18.987  WARN 1949 --- [           main] i.n.r.d.DnsServerAddressStreamProviders  : Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS.

java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_251]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_251]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_251]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_251]
at io.netty.resolver.dns.DnsServerAddressStreamProviders.<clinit>(DnsServerAddressStreamProviders.java:64) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at org.redisson.connection.MasterSlaveConnectionManager.<init>(MasterSlaveConnectionManager.java:203) [redisson-3.15.0.jar:3.15.0]
at org.redisson.connection.MasterSlaveConnectionManager.<init>(MasterSlaveConnectionManager.java:155) [redisson-3.15.0.jar:3.15.0]
....
Caused by: java.lang.UnsatisfiedLinkError: io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.resolvers()[Lio/netty/resolver/dns/macos/DnsResolver;
....

然后我去追了一下源码:

MacOSDnsServerAddressStreamProvider.class

/**
* {@link DnsServerAddressStreamProvider} implementation which makes use of the same mechanism as
* <a href="https://opensource.apple.com/tarballs/mDNSResponder/">Apple's open source mDNSResponder</a> to retrieve the
* current nameserver configuration of the system.
*/
public final class MacOSDnsServerAddressStreamProvider implements DnsServerAddressStreamProvider{
private static void loadNativeLibrary() {
String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim();
if (!name.startsWith("mac")) {
throw new IllegalStateException("Only supported on MacOS");
}
String staticLibName = "netty_resolver_dns_native_macos";
String sharedLibName = staticLibName + '_' + PlatformDependent.normalizedArch();
ClassLoader cl = PlatformDependent.getClassLoader(MacOSDnsServerAddressStreamProvider.class);
try {
NativeLibraryLoader.load(sharedLibName, cl);
} catch (UnsatisfiedLinkError e1) {
try {
NativeLibraryLoader.load(staticLibName, cl);
logger.debug("Failed to load {}", sharedLibName, e1);
} catch (UnsatisfiedLinkError e2) {
ThrowableUtil.addSuppressed(e1, e2);
throw e1;
}
}
}
// ...
private static native DnsResolver[] resolvers();
}

可以看到报错的resolvers()是一个native方法。看类名这个类应该是在MacOS系统中解析Dns的一个类,看注释应该会调用mDNSResponder服务,但为啥会调用不到呢?重启项目,跟一下loadNativeLibrary这个方法,发现里面两处load逻辑全部抛异常了,很显然,应该是native库丢了。于是我去netty的github上找这个库。在resolve-dns-native-macos这个包下面找到了源码:

https://github.com/netty/netty/tree/4.1/resolver-dns-native-macos/src/main/c

于是我又翻了下netty-all这个包,发现这个库在netty-all下是有的。

我又看了下下面那几个库,发现也都是只在netty-all这个包下有,而在独立的包中都没有。所以当netty遇到无法加载原生库时,一定要引入netty-all这个包。最终,问题解决。当然,如果不想引入netty-all这么重的包,也可以把里面的library复制出来放到自己项目的classpath下META-INF/native/目录下,然后引入netty-resolver-dns-native-macos这个包即可。

我们再来分析下为啥老版本中不会报错呢?新版本的netty修改了什么?

我把spring-boot的版本调整为2.4.1,果然,这个版本并没有报这个错,看一下这两个版本下netty版本的区别

spring-boot:2.4.1 -> netty 4.1.55.Final

spring-boot:2.4.2 -> netty 4.1.58.Final

对比了一下两个版本中的io.netty.resolver.dns.DnsServerAddressStreamProviders类,发现了一下区别:

public final class DnsServerAddressStreamProviders {
static {
Constructor<? extends DnsServerAddressStreamProvider> constructor = null;
if (PlatformDependent.isOsx()) {
try {
// ....
} catch (Throwable cause) {
// 这是4.1.58.Final版本下的日志输出
LOGGER.warn(
"Unable to load {}, fallback to system defaults. {}", MACOS_PROVIDER_CLASS_NAME,
"This may result in incorrect DNS resolutions on MacOS.", cause);
// 这是4.1.55.Final版本下的日志输出
LOGGER.debug(
"Unable to use MacOSDnsServerAddressStreamProvider, fallback to system defaults", cause);
constructor = null;
}
}
STREAM_PROVIDER_CONSTRUCTOR = constructor;
}
}

可以看到,4.1.58.Final版本将错误日志级别从debug调整到了warn,所以在老版本内并不是没有报错,只是debug日志默认没有输出而已。

找了一下,发现是在这个pullrequest中调整的https://github.com/netty/netty/pull/10848。

因此,这个异常我认为也大概也可以忽略吧,而且这个问题只会在MacOS平台复现,一般生产环境不会是MacOS,所以也不影响线上运行。如果实在看着别扭,就把DnsServerAddressStreamProviders这个类的日志输出级别调整为ERROR吧。

发表评论

评论列表(有0条评论5007人围观)
暂无评论