最近要在国产专用安全操作系统银河麒麟上部署nacos,先是启动脚本不能运行,后来又遇到加载librocksdbjni时的UnsatisfiedLinkError: /tmp/librocksdbjnixxxx.so错误,中间的坎坷就不讲了,直接上干货
nacos要通过jni的方式调用rocksdb,我用的nacos是2.2.4,通过查看nacos-server.jar可以看到,依赖的是rocksdbjni-7.7.3,打开rocksdbjni-7.7.3.jar,可以看到根目录有各个平台的so文件和dll文件
nacos启动时候,rocksdk中的RocksDB类会被初始化,其中有一个static块,会调用RocksDB.loadLibrary()进行初始化,也就是初始化jni本地库。最终的初始化动作在NativeLibraryLoader中完成,初始化的时候有以下几步
1、先尝试从系统中加载rocksdbjni
2、如果第1步加载失败,尝试加载rocksdbjni-xxx,其中xxx代表了当前平台的名字,比如linux32,linux64,linux-aarch64等
3、如果前两步都失败了,说明在系统的默认环境中是没有这些库的,就从rocksdbjni的jar包中将对应当前平台的so或dll文件释放到某一个目录,然后再加载,这个目录可以通过环境变量ROCKSDB_SHAREDLIB_DIR来指定,如果没有指定,就是系统的tmp目录,linux下是/tmp/,启动时释放文件,停止时自动删除。
那么如何保证在银河麒麟安全版上部署nacos呢?
需要保证以下几点
1、startup.sh中对LD_LIBRARY_PATH环境变量进行设置指向固定目录,因为我打包是安装在/opt/nacos下,所以LD_LIBRARY_PATH我设置为/opt/nacos/jnilib,并将so文件拷到/opt/nacos/jnilib目录下,注意,这一步非常重要,否则打包安装后如果再修改sh文件,就不能运行了,同样,如果so文件有任何改动,也是无法被调用的,包括文件的复制
2、将修改后的nacos目录打成rpm或deb,并通系统的安装配置工具进行签名安装,这样sh和so文件就可以运行和调用了
需要注意的是,在安全版的操作系统中,由于权限非常严格,不能通过释放jar包中so文件的方式运行,所以不要尝试设置ROCKSDB_SHAREDLIB_DIR变量改变释放的位置,无用。还有另一种思路,就是把对应平台的so文件单独安装到系统/usr/lib/下,当然这种方式不能像传统linux一样拷贝安装,应该也需要打成rpm或deb,有兴趣的同学可以尝试一下,另外,对安装后的so文件,可以用ldd librocksdbjni-xxx.so来验证是否有被调用的权限,如果运行成功则有。