最近小白项目上对Java平台的服务进行一次大换血:从Oracle JVM 迁移到OpenJDK。老的项目一直使用Oracle官方JDK8版本,自2019年起官方新版本开始商业收费以来,因此考虑不必要的商业版权风险以及项目的演进,决定对项目服务进行大改版之际,将Java平台从原有旧JDK8版本迁移至OpenJDK 11+。
进过几个月的代码调试,项目主体代码大体适配OpenJDK 11版本。之后,小白开始着手迁移平台。其中风险比较大的一块是项目依赖的第三方的开源服务,目前主要涉及到的是Zookeeper以及消息队列RocketMQ。今天在对Zookeeper在OpenJDK11版本调测时,虽然有过部署经验,但是还是意外忘记了其中的一些步骤。所以不得不记录一下步骤,以备不时之需。
环境以及软件要求
- Ubuntu服务器操作系统(18 LTS)
- OpenJDK 11
- Zookeeper 3.6.2 官方最新版本
迁移调测的目标点
- 测试Zookeeper能否在无Jre的OpenJDK 11版本上运行。
- 如果目标1验证失败,测试Zookeeper能否用Jlink生成jre的OpenJDK11版本上运行。
- 在目标1或者目标2成功后,测试Zookeeper在OpenJDK 11版本上主体功能的正常运行。
OpenJDK安装
-
通过wget或者curl下载OpenJDK 11运行包-openjdk-11+28_linux-x64_bin.tar.gz。
-
通过tar解压到安装目录。
-
在/etc/profile中配置JAVA_HOME以及PATH环境变量。
export JAVA_HOME=/opt/openjdk export PATH=JAVA_HOME/bin
-
使用source命令使得/etc/profile文件变更生效。
-
通过java -version命令检测OpenJDK是否安装生效。
Zookeeper安装
- 通过wget或者curl下载最新Zookeeper 3.6.2运行包-apache-zookeeper-3.6.2-bin.tar.gz
- 通过tar解压到安装目录。
- 配置Zookeeper,制作zoo.cfg:
-
拷贝zoo_sample.cfg生成目标zoo.cfg
sudo cp zoo_sample.cfg zoo.cfg
-
使用vi打开编辑zoo.cfg
sudo vi zoo.cfg
-
修改默认zookeeper客户端监听端口:
clientPort=xxxx
-
添加digest验证:
DigestAuthenticationProvider.superDigest=super:xxxxxxxxxxxxxx
添加digest验证可以加强Zookeeper的安全性,虽然从根本上说并没软用。如果需要保障Zookeeper的安全性就两条:不要暴露到公共网络环境下,还有就是使用SSL或者SASL。另外,digest配置文本可以通过DigestAuthenticationProvider.generateDigest()方法生成。
Zookeeper单例调测
运行“bin/zkServer.sh start”运行Zookeeper.
Permission Denied的坑
依据官方文档通过上述命令,可能会获得成功,当然更有可能获得的是一个坑:
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
mkdir: cannot create directory ‘/opt/zookeeper/bin/../logs’: Permission denied
Starting zookeeper ... bin/zkServer.sh: line 158: /opt/zookeeper/bin/../logs/zookeeper-ubuntu-server-VM-0-3-ubuntu.out: No such file or directory
FAILED TO START
权限问题很好理解,无非授权足够的权限。这个问题其实很简单,正常我们使用非自建服务器或者云服务器时候,通常使用的是管理员账号例如ubuntu,而不是超级管理员root。但是Zookeeper的目录是root。如果你使用的是超级管理员,那么你应该已经成功运行Zookeeper。不信你看:
drwxr-xr-x 6 root root 4096 Oct 16 23:25 zookeeper
- Permission Denied解决方案1
使用’sudo bin/zkServer.sh start’启动Zookeeper
- Permission Denied解决方案2
变更zookeeper安装目录及内部文件所属用户和用户组:
sudo chown -R xxx zookeeper
sudo chgrp -R xxx zookeeper
使用sudo运行Zookeeper的坑
使用’sudo bin/zkServer.sh start’启动Zookeeper,不好意思,这里还有一个坑:
Error: JAVA_HOME is not set and java could not be found in PATH.
使用sudo一个问题很大的问题是,zookeeper运行脚本找不到JAVA_HOME环境变量。你会奇怪,我明明设置了JAVA_HOME环境变量,不信你使用env命令查看。但是sudo命令相当让zookeeper脚本像在另一个账户下运行,而且找不到JAVA_HOME环境变量。
解决方案
找到zookeeper的bin目录下的zkEnv.sh脚本,并用vi打开编辑。在文件开头,添加自定义的JAVA_HOME环境变量:
export JAVA_HOME=/opt/openjdk
ZOOBINDIR="${ZOOBINDIR:-/usr/bin}"
ZOOKEEPER_PREFIX="${ZOOBINDIR}/.."
变更用户和用户组的坑
通过chown和chgrp命令变更zookeeper的用户组和用户组时,都不好意思告诉你, 查看logs下的日志,这里也是坑等着你:
2020-10-17 00:35:10,799 [myid:] - ERROR [main:ZooKeeperServerMain@80] - Unable to access datadir, exiting abnormally
org.apache.zookeeper.server.persistence.FileTxnSnapLog$DatadirException: Cannot write to data directory /tmp/zookeeper/version-2
at org.apache.zookeeper.server.persistence.FileTxnSnapLog.<init>(FileTxnSnapLog.java:140)
at org.apache.zookeeper.server.ZooKeeperServerMain.runFromConfig(ZooKeeperServerMain.java:137)
at org.apache.zookeeper.server.ZooKeeperServerMain.initializeAndRun(ZooKeeperServerMain.java:112)
at org.apache.zookeeper.server.ZooKeeperServerMain.main(ZooKeeperServerMain.java:67)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:140)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:90)
Unable to access datadir, exiting abnormally
为什么呢?大概是datadir出问题。好吧,把它找出来。首先看一下zoo.cfg文件,dataDir=/tmp/zookeeper. 根据日志,访问这个文件夹出错。找到这个文件夹下再看一下:
drwxr-xr-x 2 root root 4096 Oct 17 00:29 version-2
解决方案:
答案显而易见,这也是一个权限问题。那么变更dataDir目录或者授权呗。变更后使用‘bin/zkServer.sh start’运行,记得不要用sudo。
总的来说,最后验证最新版的zookeeper是可以在OpenJDK 11下运行的。可能部分功能需要依赖JMX不能使用,因为OpenJDK默认没有啊。Zookeeper主体功能还是能使用的。真是感谢上帝了。