英文:
Error in Azure App Service: java.lang.UnsatisfiedLinkError: failed to load the required native library
问题
我有一个 Spring Boot 应用程序,我想将其部署到 Azure App Service 作为一个 war 包。该 Spring Boot 应用程序具有 REST API。App Service 的配置如下:
- 操作系统:Linux
- 发布方式:代码
- 运行时栈:Tomcat 9
我的 pom.xml 文件如下所示:
<!-- 在这里是您的 pom.xml 内容 -->
当我在我的笔记本电脑上运行该应用程序时,它能够正常工作。但是,在将应用程序部署到 Azure 后,出现了问题。虽然部署成功,但当我访问应用程序的某个 API 时,我收到以下错误:
{
"timestamp": "2020-09-12T15:06:06.732+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/api/get" //由于安全原因已编辑
}
以下是部分日志内容:
2020-09-12T15:35:31.508024047Z: [INFO]
2020-09-12T15:35:31.508053247Z: [INFO] java.lang.UnsatisfiedLinkError: 无法加载所需的本机库
2020-09-12T15:35:31.508057547Z: [INFO] at io.netty.handler.ssl.OpenSsl.ensureAvailability(OpenSsl.java:474) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508080348Z: [INFO] at io.netty.handler.ssl.ReferenceCountedOpenSslContext.<init>(ReferenceCountedOpenSslContext.java:196) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508084948Z: [INFO] at io.netty.handler.ssl.ReferenceCountedOpenSslContext.<init>(ReferenceCountedOpenSslContext.java:185) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508089148Z: [INFO] at io.netty.handler.ssl.OpenSslContext.<init>(OpenSslContext.java:34) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508093148Z: [INFO] at io.netty.handler.ssl.OpenSslClientContext.<init>(OpenSslClientContext.java:189) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508097248Z: [INFO] at io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:827) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508101248Z: [INFO] at io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:576) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
我不知道问题出在哪里。
英文:
I have a Spring Boot App which I want to deploy to Azure App Service as a war.
The spring boot app has REST APIs. And the App Service is configured as below:
- OS: Linux
- Publish: Code
- Runtime Stack: Tomcat 9
My pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sdk-hlf</groupId>
<artifactId>sdk-hlf-1.4.4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<tomcat.version>9.0.20</tomcat.version>
<start-class>com.example.app.MainClass</start-class> <!-- edited for security reasons -->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway-java</artifactId>
<version>1.4.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>demo</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<finalName>demo</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
When I run the App in my laptop, it works fine.
But the problem occurs after deploying the app to Azure. It is deployed successfully, but when I hit an API of my app I get the below error:
{
"timestamp": "2020-09-12T15:06:06.732+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/api/get" //edited for security reasons
}
Below is a portion of the logs:
2020-09-12T15:35:31.508024047Z: [INFO]
2020-09-12T15:35:31.508053247Z: [INFO] java.lang.UnsatisfiedLinkError: failed to load the required native library
2020-09-12T15:35:31.508057547Z: [INFO] at io.netty.handler.ssl.OpenSsl.ensureAvailability(OpenSsl.java:474) ~[netty-handler-4.1.49
.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508080348Z: [INFO] at io.netty.handler.ssl.ReferenceCountedOpenSslContext.<init>(ReferenceCountedOpenSslContex
t.java:196) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508084948Z: [INFO] at io.netty.handler.ssl.ReferenceCountedOpenSslContext.<init>(ReferenceCountedOpenSslContex
t.java:185) ~[netty-handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508089148Z: [INFO] at io.netty.handler.ssl.OpenSslContext.<init>(OpenSslContext.java:34) ~[netty-handler-4.1.4
9.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508093148Z: [INFO] at io.netty.handler.ssl.OpenSslClientContext.<init>(OpenSslClientContext.java:189) ~[netty-
handler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508097248Z: [INFO] at io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:827) ~[netty-ha
ndler-4.1.49.Final.jar:4.1.49.Final]
2020-09-12T15:35:31.508101248Z: [INFO] at io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:576) ~[netty-handler
-4.1.49.Final.jar:4.1.49.Final]
I dont know whats the problem here?
答案1
得分: 1
我找到了问题,'fabric gateway' 依赖于 'boring ssl',而 'boring ssl' 则依赖于在 Windows 环境下的 DLL 文件和在 Linux 环境下的 SO 文件。在我的依赖列表中,我看到在 'netty-tcnative-boringssl-static-2.0.26.Final.jar\META-INF\native' 文件夹中打包了这两种 SO 和 DLL 文件。这个文件夹中有以下文件。
libnetty_tcnative_linux_x86_64.so
libnetty_tcnative_osx_x86_64.jnilib
netty_tcnative_windows_x86_64.dll
JVM 应该从 META-INF/native 文件夹中选择所需的本地文件(根据主机操作系统选择 DLL 或 SO 文件),但在 Windows 下只选择了 DLL 文件,而在 Linux 下却没有。因此,为了解决这个问题,我从 jar 文件中提取了 SO 文件,将其放在 Linux 主机上的一个文件夹中,并使用以下方式通过 System.load 加载了 SO 文件。这解决了问题。
static {
try {
String path = "/apps/config/libnetty_tcnative_linux_x86_64.so";
Path soPath = Paths.get(path);
if (Files.exists(soPath)) {
System.load(path);
System.out.println("Native library loaded successfully");
}
} catch (Throwable e) {
System.out.println("Native library load failed");
e.printStackTrace();
}
}
静态代码块会在类加载时首先加载,因此我在“入口点”Java类中包含了上述的静态代码块,以确保在加载任何 Java 类之前先加载 SO 文件。
现在,应该根据你的主机操作系统来包含正确的 'boring ssl' jar 文件。请阅读以下文档,了解如何在你的 pom.xml 中指定相关的 JAR 文件。如果适当的 JAR 文件的本地库(SO 或 DLL)未能加载并导致链接错误,那么可以像上面一样进行手动加载。
https://netty.io/wiki/forked-tomcat-native.html
英文:
I found the issue, 'fabric gateway' depends on 'boring ssl', and 'boring ssl' depends on a DLL file in case on Windows and an SO file in case of Linux. In my dependencies list, I see both SO and DLL files packed in 'netty-tcnative-boringssl-static-2.0.26.Final.jar\META-INF\native' folder. This folder has following files.
> libnetty_tcnative_linux_x86_64.so
> libnetty_tcnative_osx_x86_64.jnilib
> netty_tcnative_windows_x86_64.dll
JVM is supposed to pick the necessary native file (DLL or SO file based on host OS) from META-INF/native folder, but picks only in case of Windows, but not linux. So, for this, I've picked up the SO file from jar, put it in a folder on Linux box and 'loaded' the SO file using System.load as follows. This has resolved the issue.
static{
try{
String path="/apps/config/libnetty_tcnative_linux_x86_64.so";
Path path = Paths.get(path);
if (Files.exists(path)) {
System.load(path);
System.out.println("Native library loaded successfully");
}
}catch (Throwable e){
System.out.println("Native library load failed");
e.printStackTrace();
}
}
Static blocks load first when the class is being loaded, so, I've included above static block in the 'entry point' Java class, which ensures that SO file is loaded before any Java class is loaded.
Now, the 'boring ssl jar' that should be included is based on your host OS, read the following documentation on how you can specify stuff in your pom.xml for appropriate JAR to be included. If the appropriate JAR's native library (SO or DLL) does not load and results into link error, then 'load' as above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论