我的一位同事最近要求我将Spring应用程序部署到运行cPanel / WHM和Apache的CentOS服务器。 由于这种构建要求并不十分明显,因此我想我将分享经验作为简单的操作指南。 请注意,这只是一个操作方法,而不是最佳实践指南,因此,如果您需要强化安全性的解决方案,我建议您查看TomcatExpert以获取权威的操作方法。 话虽如此,让我们开始吧。
首选个人工具
由于我更喜欢使用GNU工具并且在本地运行Windows,因此我使用了基于Arch Linux的Cygwin衍生的工具包,称为MSYS2和ConEmu – Windows的出色控制台仿真器。
技能与依存关系列表
为了使这个构建工作正常,我假设您至少对Linux基本命令,shell访问和对Vim编辑器的了解非常熟悉。 如果不是,我将在继续操作时显示命令,但是这些技能不在本指南的范围内。 如果您不习惯使用Vim,则可以将此任务委托给对自己的技能更有信心的人,或者使用其他编辑器,例如Nano或Emacs 。 有关更多信息,您可以分别从StackOverflow Wiki, SSH , Linux和Vim获得有关每种技术的不错的引导课程。 此外,显然我们将需要Java和Tomcat,因此让我们从安装或更新到最新版本开始。 (当前为Java 8 1.8.0_45,Tomcat v8.0.21)。
安装/更新到最新的Java 8版本
为了安装二进制文件,我们将以root身份通过SSH进入服务器,并使用GNU Wget下载依赖项。 我正在将Java安装到/ usr / local,但是如果您愿意,可以替换其他位置,例如/ opt或/ usr / share。 请注意,当您看到开头带有#
井号的命令行时,这是Unix标准,表示您以“作为root用户”身份登录。 但是,如果你不是以root用户,所有的命令显示井号登录, #
需要“须藤”的权限。 $
符号分别表示您是普通用户。 有关sudo
命令和以root用户身份运行的更多信息,您可以签出手册页或CentOS Wiki 。
因此,让我们cd
到你的目标目录的根和获取最新的Java版本...
请注意,该条目最初发布于2015年4月,因此您可能要下载Java和Tomcat的最新版本并相应地更新要求。
cd /usr/local/ && wget --no-check-certificate -c \
--header "Cookie: oraclelicense=accept-securebackup-cookie" \
http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz
档案下载后,它可能已保存并附加了查询字符串AuthParam。 如果是这样,只需重命名存档,使其以tar.gz
扩展名结尾。
ls -l | grep jdk
注意:要重命名文件,您只需键入
jdk
并按两次tab
键即可完成文件名,而不必键入整个文件名。
mv jdk-8u45-linux-x64.tar.gz\?AuthParam\=1429150407_03533c0686909067456bf8c408ad56c9 jdk-8u45-linux-x64.tar.gz
接下来,我们需要使用tar将档案提取到目标目录中。 同样,如果您没有安装到/usr/local
更新路径。
tar xvzf jdk-8u45-linux-x64.tar.gz
ln -s /opt/apache-tomcat-8.0.21 tomcat
为了使将来的JDK更新更加容易,我想创建一个引用当前JDK的符号链接 ,以便所有Java二进制文件都可以通过Linux Alternatives二进制版本管理器自动重新指向当前JDK。 下面,我仅使符号链接引用新提取的JDK。
ln -s /usr/local/jdk1.8.0_45 jdk
并非严格要求下一系列命令。 但是,如果您当前未在系统上安装Java,则可以确保以后的更新更加容易,因此,我建议您遵循以下步骤,以便下次更新JDK时换掉JDK符号链接。 但是,如果您需要更新current
Java版本,则CentOS Wiki上的“ 替代方法”可以使您快速完成任务。
假设您没有Java的替代设置,接下来的命令将安装JDK二进制文件的替代链接。
update-alternatives --install /usr/bin/java java /usr/local/jdk/bin/java 1
update-alternatives --install /usr/bin/javac javac /usr/local/jdk/bin/javac 1
update-alternatives --install /usr/bin/javaws javaws /usr/local/jdk/bin/javaws 1
发出这些命令后,您可以通过将--display
参数传递给Alternatives系统来验证版本。
update-alternatives --display java
update-alternatives --display javac
update-alternatives --display javaws
安装并确认替代方法后,只需发出java -version
即可确认系统正在找到JDK。
如果没有收到有效的答复,请从头开始,并确认您已正确执行每个步骤。 在安装Java和在Linux环境中工作都容易犯一些简单的错误。
java -version
如果您已经做到了,那么恭喜! 您已经拥有生产Java服务器的一半,但是现在还不庆祝,安装JDK很容易,现在我们必须安装和配置Tomcat。
安装Tomcat 8
我个人喜欢将Tomcat安装到
/opt
目录。 因此,与JDK的位置一样,如果您没有安装到/opt
更新路径。
首先,我们需要考虑我们目前正在计划做的事情。 在非特权帐户上运行Tomcat是众所周知的最佳实践,因此,我们将创建一个没有登录外壳的Tomcat用户。 另外,对于此构建,我计划在Apache 2.2之后运行Tomcat的多个实例,并为Apache保留所有静态HTTP请求。 Tomcat根本不会运行HTTP。 因此,我们将通过AJP代理到Tomcat 。 该工作流程基本上看起来像下面的描述。
AJP不是唯一的解决方案,我们“可以”使用Mod Proxy HTTP将所有请求代理到另一个端口上的Tomcat。 但是,这不是理想的解决方案,因为您实际上将使用两个HTTP服务器,并且在两个端口上都可以看到您的站点。 同样,也有解决方法,但为简单起见,我想完全禁用Tomcat HTTP服务器,并使用来自Apache的AJP连接器通过AJP向Tomcat传递来自Tomcat的请求,并让Apache处理HTTP。
因此,让我们开始下载Tomcat。 我正在直接从该站点使用Apache下载,但是如果您想要更近的镜像,则可以在Tomcat站点上找到一个
cd /opt && wget http://archive.apache.org/dist/tomcat/tomcat-8/v8.0.21/bin/apache-tomcat-8.0.21.tar.gz
在继续前进之前,我们需要验证二进制发行版md5的完整性。 对于此版本,总和如下,但是您也可以在Tomcat站点的tar.gz下载链接旁边找到md5链接。 如果md5不匹配,请下载另一个存档,因为二进制文件在传输过程中很容易损坏。
md5sum apache-tomcat-8.0.21.tar.gz
如果md5sum匹配,则将存储和symlink tomcat提取到/opt
目录中,类似于我们先前对JDK所做的操作。
tar xvzf apache-tomcat-8.0.21.tar.gz
ln -s /opt/apache-tomcat-8.0.21 tomcat
接下来,我们需要设置我们的tomcat用户,进行分组,并将二进制文件的所有权更改为新的tomcat用户。
groupadd tomcat
useradd -g tomcat -s /usr/sbin/nologin -m -d /opt/tomcat tomcat
chown -R tomcat.tomcat /opt/tomcat
现在,让我们确认Tomcat用户已添加到系统中。
cat /etc/passwd | grep tomcat
如果您的输出显示了tomcat用户,则可以安全地继续构建Tomcat APR本机库
构建Tomcat APR本机库
接下来,我们将构建Tomcat本机库以获得最佳性能。 本机APR库通过增加对保持活动请求的非阻塞I / O的支持来提高性能。 因此,这是直接从Tomcat Native Library网站上获得的要点,内容是Tomcat Native如何提高性能。
“ Apache Tomcat本机库是与Apache Tomcat一起使用的可选组件,它允许Tomcat使用某些本机资源来提高性能,兼容性等。
具体来说,Apache Tomcat本机库为Tomcat提供了对Apache可移植运行时(APR)库网络连接(套接字)实现和随机数生成器的访问权限。 请参阅Apache Tomcat文档,以获取有关如何配置Tomcat以使用APR连接器的更多信息。”
尽管不需要执行此步骤,但它使Tomcat的性能更好,并且我们喜欢性能,因此让我们开始吧。
在基于RPM的发行版CentOS上,我们将使用Yum安装Tomcat Native所需的两个必需依赖项– OpenSSL和APR库。 如果您使用基于Debian的发行版(Ubuntu,Linux Mint等),则可以轻松地使用Aptitude或Apt等。
yum install -y apr-devel openssl-devel
一旦Yum完成库的安装, cd
进入基本的Tomcat二进制目录,并提取tomcat本机存档。
cd /opt/tomcat/bin && tar xvzf tomcat-native.tar.gz
接下来,将cd
插入tomcat-native- {version} -src / jni目录,并按照您所看到的完全发出以下命令。 请注意,。/ configure脚本非常擅长采用大多数标准的OpenSSL实现,因此您无需显式设置ssl的路径。
cd /opt/tomcat/bin/tomcat-native-1.1.33-src/jni
./configure --with-apr=/usr/local/apr \
--with-java-home=/usr/local/jdk \
--with-ssl=yes \
--prefix=/opt/tomcat
配置构建后,运行make和make install。
make && make install
现在,您应该在/usr/local/apr/lib
目录中构建了libtcnative二进制文件。 只需确认ls
目录即可。 如果在构建tomcat本机二进制文件时遇到麻烦,请检查安装以确保正确找到了所有必需的依赖项。 最常见的困难是找到APR库。
ls /usr/local/apr/lib
为了确认APR库是否正确加载,让我们通过设置环境变量,添加APR库路径并测试配置来运行快速测试。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib
export JAVA_HOME=/usr/local/jdk
cd /opt/tomcat/bin && ./configtest.sh
发出./configtest.sh之后,您要滚动显示输出以确认APR库已正确加载。
INFO: Loaded APR based Apache Tomcat Native library 1.1.33 using APR version 1.2.7.
如果您至今仍在我身边,那就太好了! 现在,让我们继续并配置单独的实例。
注意:如果此时遇到任何问题,例如“找不到基于APR的Apache Tomcat本机库”,请检查/ opt / tomcat / lib或/ usr / local / apr / lib下的内容,以确定您是否确实拥有传统二进制。
配置Tomcat的多个实例
当前,我们的Tomcat运行时文件位于/ opt / tomcat下。 但是,对于此构建,我们希望能够管理多个实例-为每个实例提供单独的JVM。 这样,如果应用程序在一个实例上崩溃,则不会关闭另一个实例上的应用程序。 尽管是理想的情况,但是它确实需要大量配置才能进行设置。 因此,让我们开始吧。
Tomcat文档显示了安装多个实例的基础知识,但是如果没有演练,它就不是很直观。
简而言之,基本方向建议保持核心安装$CATALINA_HOME
并创建包含每个实例所需资产的单独实例目录$CATALINA_BASE
。 这就是我们要做的。
因此,现在让我们创建单独的实例,将所需文件复制到每个实例,然后从$CATALINA_HOME
删除无关的文件。
cd /opt/tomcat && mkdir tomcat_1 tomcat_2
cp -R bin conf logs temp webapps work tomcat_1
cp -R bin conf logs temp webapps work tomcat_2
rm -rf conf logs temp webapps work
现在, /opt/tomcat
目录应具有以下目录结构。
ls -l /opt/tomcat
为了抽象起见,我将使用example1.com和example2.com作为参考,但是当然您必须使用实际的主机域来更新它们。 为了配置我们的实例,将对每个实例的server.xml文件中的几个元素进行一些修改。 您需要提供的两个变量是域的网络IP地址和域名。 否则,每个服务器实例需要七个项目。
- 专用的服务器关闭端口。
- 禁用HTTP连接器。
- 专用的服务器AJP连接器端口。
- 定义的AJP连接器地址。
- 定义的默认主机。
- 定义的主机元素。
- Valve元素的日志记录前缀已定义。
(可选)您还可以通过添加带有算法值的摘要属性来更新UserDatabaseRealm
以使用摘要身份验证。 我个人更喜欢使用SHA-256。
因此,让我们开始吧……打开vim,对/opt/tomcat/tomcat_1/conf/server.xml进行更改,以项目4的域网络IP地址和项目5,6,7的域更新项目。 没有您自己的变量,server.xml应该类似于以下内容。
cd /opt/tomcat/tomcat_1/conf && vim server.xml
保存第一个实例后,server.xml让我们继续更新第二个实例。 这次,我们将进行与第一个server.xml相同的更改,但对项目1和3进行了一些额外更改。由于两个实例不能共享相同的关闭端口,请更新服务器元素端口属性以使用其他端口。比一审。 在此示例中,我使用8006,从第一个实例的shutdown端口增加一个。 按照项目3的要求,我还将更新AJP Connector元素的port属性以使用端口8010,再次从第一个实例AJP端口简单地增加一个。
cd /opt/tomcat/tomcat_2/conf && vim server.xml
第二个实例的server.xml应该如下所示。
在conf目录中工作时,让我们继续进行操作,并为每个实例更新tomcat-users.xml文件。 从/opt/tomcat/tomcat_1/conf/tomcat-users.xml开始,在文件末尾添加以下角色和用户标签,然后关闭tomcat-users标签。 使用您现在想要的任何内容更新用户名和密码值。
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="admin" password="admin" roles="manager-gui,manager-script,manager-jmx,manager-
status,admin-gui,admin-script"/>
现在,我们需要通过创建位于实例bin目录下的环境文件来配置每个实例的初始化。 分别是/opt/tomcat/{instance}/bin/setenv.sh
我已经为此目的特别定制了一个,因此您可以根据需要简单地复制我的。 尽管很明显,但是您需要为instance_2更新$CATALINA_BASE
和$CATALINA_PID
。 此外,如果要安装两个以上的实例,请遵循以下步骤。 注意,以下选项适用于我自己的服务器配置。 YMMV。
#!/bin/sh
# Edit this file to set custom options
#
# Notes:
#
# * Tomcat accepts the JAVA_OPTS and CATALINA_OPTS parameters
# * JAVA_OPTS are used during START/STOP/RUN
# Edit this file to set custom options
# Edit this file to set custom options
#
# Notes:
#
# * Tomcat accepts the JAVA_OPTS and CATALINA_OPTS parameters
# * JAVA_OPTS are used during START/STOP/RUN
# * CATALINA_OPTS are used during START/RUN
# * This script is sourced by catalina.sh when it placed inside
# * $CATALINA_BASE/bin (instance specify setup) or $CATALINA_HOME/bin directories.
# ------------------------------------------------------------
JAVA_HOME="/usr/local/jdk"
CATALINA_HOME="/opt/tomcat"
CATALINA_BASE="/opt/tomcat/tomcat_1"
CATALINA_PID="$CATALINA_BASE/temp/tomcat_1.pid"
#################################
# *** JAVA OPTIONS SETTINGS *** #
#################################
JVM_MODE="-server"
HEADLESS_MODE="-Djava.awt.headless=true"
BIT_MODE="-d64"
HEAP_OPTS="-Xms128m -Xmx768m"
GC_OPTS="-XX:+AlwaysPreTouch -XX:+AggressiveOpts -XX:+UseG1GC -XX:ReservedCodeCacheSize=256m -XX:+UseCompressedOops -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -Djsse.enableSNIExtension=false -XX:SoftRefLRUPolicyMSPerMB=50"
#
# Example:
# conf/jmxremote.access
# john readwrite
# conf/jmxremote.password
# john johnpasswd
# Make sure both jmxremote.{access,passsword} files only readable/writeable (600) by the owner, and
# jxmremote.port must be unique for each server instance.
#
#JMXREMOTE_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false
#-Dcom.sun.management.jmxremote.authenticate=true -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.password.file
#=$CATALINA_BASE/conf/jmxremote.password -Dcom.sun.management.jmxremote.access.file=$CATALINA_BASE/conf/jmxremote.access"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib
JAVA_OPTS="$JVM_MODE $HEADLESS_MODE $BIT_MODE $HEAP_OPTS $GC_OPTS"
接下来,更改所有权并为每个setenv.sh实例设置可执行位,然后我们将进行一些Apache配置。
chown tomcat.tomcat /opt/tomcat/tomcat_1/bin/setenv.sh && chmod +x /opt/tomcat/tomcat_1/bin/setenv.sh
chown tomcat.tomcat /opt/tomcat/tomcat_2/bin/setenv.sh && chmod +x /opt/tomcat/tomcat_2/bin/setenv.sh
配置Apache虚拟主机包括
接下来,我们需要确保Apache在加载到Tomcat的同时加载了mod_proxy
和mod_proxy_ajp
。 只需发出以下命令来验证两个模块是否均已加载。
httpd -M | grep -i 'proxy'
您应该在输出中看到两个模块。
...
proxy_module (static)
proxy_ajp_module (static)
...
尽管默认情况下几乎所有cPanel / WHM配置文件都同时激活两个模块,但是如果您在输出中看不到两个模块,则需要参考cPanel / WHM文档以包括这些模块。
接下来,我们需要以特定的方式为每个域包括一个tomcat配置文件,以便通过cPanel / WHM进行修改时,它们不会覆盖我们的配置。 为此,我们将为两个域添加特定的目录结构和tomcat.conf文件。
我们不需要更新默认的/usr/local/apache/conf/httpd.conf即可包含我们的配置。 如果您更新默认的/usr/local/apache/conf/httpd.conf,则在更新更新cPanel / WHM之后,所做的更改将丢失。 考虑一下自己被警告。
为了包括我们的配置,目录结构必须反映正确的用户和域结构,以便apache加载配置文件。 同样,我以domain1.com,domain2.com为例。 为了进一步说明,要包括针对user1,domain1.com和user2,domain2.com的新tomcat.conf,我们需要使用以下结构创建tomcat.conf。
/usr/local/apache/conf/userdata/std/2/user1/domain1.com/tomcat.conf
/usr/local/apache/conf/userdata/std/2/user2/domain2.com/tomcat.conf
因此,让我们开始吧。 首先,将cd
输入到user1
使用的用户名的正确位置,然后创建目录。 如果您仅使用一个用户和两个域,那么现在就去那里。 否则,请相应地更新您的路径。
cd /usr/local/apache/conf/userdata/std/2 && mkdir user1/domain1.com && mkdir user2/domain2.com
创建目录后,为第一个用户创建一个tomcat.conf文件,添加以下Proxy语句并保存该文件。
cd /usr/local/apache/conf/userdata/std/2/user1/domain1.com && \
touch tomcat.conf && vim tomcat.conf
ProxyRequests off
ProxyPreserveHost on
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPass / ajp://domain1.com:8009/
ProxyPassReverse / ajp://domain1.com:8009/
对第二个用户重复相同的操作,用第二个域替换必要的值。
cd /usr/local/apache/conf/userdata/std/2/user2/domain2.com && \
touch tomcat.conf && vim tomcat.conf
ProxyRequests off
ProxyPreserveHost on
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPass / ajp://domain2.com:8010/
ProxyPassReverse / ajp://domain2.com:8010/
接下来,我们需要调用脚本来更新httpd.conf配置。 执行以下命令即可。
/usr/local/cpanel/bin/apache_conf_distiller --update
/scripts/rebuildhttpdconf
service httpd restart
此时,我们现在应该具有Apache对Tomcat的代理请求,但是我们尚未将服务器配置为自动启动Tomcat实例。 同样,我创建了一个服务脚本,您可以根据需要将其用于每个实例。 在/etc/init.d目录下创建具有以下内容的名为tomcat_1
的文件。 创建tomcat_1之后,只需将其复制为tomcat_2,并像以前使用setenv.sh
配置一样更新$CATALINA_BASE
和$CATALINA_PID
值。
#!/bin/bash
# chkconfig: 2345 20 80
# description: Tomcat 8 start/stop/status init.d script
JAVA_HOME=/usr/local/jdk
export JAVA_HOME
#Add Java binary files to PATH
PATH=$JAVA_HOME/bin:$PATH
export PATH
#CATALINA_HOME is the location of the bin files of Tomcat
CATALINA_HOME=/opt/tomcat
export CATALINA_HOME
#CATALINA_BASE is the location of the configuration files of this instance of Tomcat
CATALINA_BASE=$CATALINA_HOME/tomcat_1
export CATALINA_BASE
#CATALINA_PID is the Tomcat instance process ID.
CATALINA_PID="$CATALINA_BASE/temp/tomcat_1.pid"
export CATALINA_PID
#TOMCAT_USER is the default user of tomcat
TOMCAT_USER=tomcat
export TOMCAT_USER
#TOMCAT_USAGE is the message if this script is called without any options
TOMCAT_USAGE="Usage: $0 {\e[00;32mstart\e[00m|\e[00;31mstop\e[00m|\e[00;31mkill\e[00m|\e[00;32mstatus\e[00m|\e[00;31mrestart\e[00m}"
#SHUTDOWN_WAIT is wait time in seconds for java proccess to stop
SHUTDOWN_WAIT=20
tomcat_pid() {
echo ps -fe | grep $CATALINA_BASE | grep -v grep | tr -s " "|cut -d" " -f2
}
#USER LEVEL CHECK
if [[ $EUID -ne 0 ]]; then
echo "basename $0 requires root privileges." 1>&2
exit 1
fi
start() {
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo -e "\e[00;31mTomcat is already running (pid: $pid)\e[00m"
else
# Start tomcat
echo -e "\e[00;32mStarting tomcat\e[00m"
if [ user_exists $TOMCAT_USER = "1" ]
then
/bin/su - $TOMCAT_USER -s /bin/bash -c $CATALINA_BASE/bin/startup.sh
else
sh $CATALINA_BASE/bin/startup.sh
fi
status
fi
return 0
}
status(){
pid=$(tomcat_pid)
if [ -n "$pid" ]; then echo -e "\e[00;32mTomcat is running with pid: $pid\e[00m"
else echo -e "\e[00;31mTomcat is not running\e[00m"
fi
}
terminate() {
echo -e "\e[00;31mTerminating Tomcat\e[00m"
kill -9 $(tomcat_pid)
}
stop() {
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo -e "\e[00;31mStoping Tomcat\e[00m"
sh $CATALINA_BASE/bin/shutdown.sh
let kwait=$SHUTDOWN_WAIT
count=0;
until [ ps -p $pid | grep -c $pid = '0' ] || [ $count -gt $kwait ]
do
echo -n -e "\n\e[00;31mwaiting for processes to exit\e[00m";
sleep 1
let count=$count+1;
done
if [ $count -gt $kwait ]; then
echo -n -e "\n\e[00;31mkilling processes didn't stop after $SHUTDOWN_WAIT seconds\e[00m"
terminate
fi
else
echo -e "\e[00;31mTomcat is not running\e[00m"
fi
return 0
}
user_exists(){
if id -u $1 >/dev/null 2>&1; then
echo "1"
else
echo "0"
fi
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
kill)
terminate
;;
*)
echo -e $TOMCAT_USAGE
;;
esac
exit 0
创建实例服务文件后,我们需要设置执行位并将文件添加到chkconfig应用程序中,以设置Tomcat将在其上运行的系统运行级别。
chmod +x /etc/init.d/tomcat_1 && chmod +x /etc/init.d/tomcat_2
chkconfig --add tomcat_1 && chkconfig --add tomcat_2
chkconfig --level 2345 tomcat_1 on && chkconfig --level 2345 tomcat_2 on
现在,我们应该能够使用系统服务命令来查询Tomcat服务器实例状态。
service tomcat_1
Usage: /etc/init.d/tomcat_1 {start|stop|kill|status|restart}
现在,我们可以简单地调用每个脚本来初始化Tomcat实例,重新启动Apache,每个域都将转发到它自己的Tomcat实例。
service tomcat_1 start && service tomcat_2 start && service httpd restart
恭喜! 现在,您已经在Java 8上安装了Tomcat 8的多个实例,该实例在具有cPanel / WHM的Centos上的Apache Web服务器后面运行。
直到下次…
翻译自: https://www.javacodegeeks.com/2015/09/tomcat-8-on-java-8-behind-apache-on-centos.html