Linux下 tomcat8使用APR提高并发性能

APR(Apache Portable Runtime) 是apache的一个项目,目的是创建和维护为特定平台底层实现的软件库并提供一致接口。Tomcat 查能通过JNI方式调用APR,提供卓越的可扩展性、性能以及与本机服务器技术更好的集成。

APR 有很多用途,包括访问高级 IO 功能(例如 sendfile、epoll 和 OpenSSL)、操作系统级功能(随机数生成、系统状态等)和本地进程处理(共享内存、NT pipes 和 Unix socket)。
有些东西也不知道是撒, 反正很好的样子, 下面看看怎么用起来

环境

  • CentOS 7.9
  • Tomcat 8.5
  • Java 7

安装

下载tomcat8.5 并解压好。后面用$TOMCAT_PATH 表示tomcat 目录

要开启APR需要要安装3个本地组件:

  1. APR 库: apr-devel
  2. OpenSSL 库: openssl-devel
  3. Tocmat 调用APR的 JNI 封装: libtcnative (tomcat自带, 位置: $TOMCAT_PATH/bin/tomcat-native.tar.gz

环境依赖:

  1. GNU 开发环境(gcc,make)
  2. JDK1.4+

首先安装依赖的库和工具:

1
yum install -y openssl-devel apr-devel gcc make

然后, 开始安装tomcat JNI 封装(也就是Tomcat native library), 先解压并进入tomcat-native目录:

1
2
3
4
cd $TOMCAT_PATH/bin
tar zxvf tomcat-native.tar.gz
cd tomcat-native-1.2.31-src/native
./configure && make && make install

编译安装 tomcat-native:

1
./configure && make && make install

如果没有设置JAVA_HOME环境变量, 可能需要在编译配置里指定java目录, 例如:

1
./configure --with-java-home=/usr/java/jdk1.7.0_80/ && make && make install

安装完成会看到如下输出结果:

Libraries have been installed in:
/usr/local/apr/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR’
flag during linking and do at least one of the following:

  • add LIBDIR to the `LD_LIBRARY_PATH’ environment variable
    during execution
  • add LIBDIR to the `LD_RUN_PATH’ environment variable
    during linking
  • use the `-Wl,-rpath -Wl,LIBDIR’ linker flag
  • have your system administrator add LIBDIR to `/etc/ld.so.conf’

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.

写明了tomcat native library 安装的目录:/usr/local/apr/lib, 后面会用到。

下面开始配置使用

使用APR

方式一: tomcat自动选择

  1. 修改 conf/server.xml, 设置Connector 的protocol值为 ‘HTTP/1.1’。

    1
    2
    3
    4
    5
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443"
    URIEncoding="UTF-8"
    />

    protocol='HTTP/1.1'时,tomcat自动选择 Java NIO 或者 APR/native 来作为底层连接器。

    选择逻辑:如果 LD_LIBRARY_PATH(linux下)环境变量包含了 Tomcat native library, 并且AprLifecycleListeneruseAprConnector属性值为true, 就会使用APR/native 连接器。 相反,找不到库或者这个属性没有设置,就用 JAVA NIO。

  2. 设置LD_LIBRARY_PATH环境变量。把上文提到的Tomcat native library 的安装目录/usr/local/apr/lib 添加到LD_LIBRARY_PATH环境变量里。

    1
    2
    echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib' >> /etc/profile
    source /etc/profile
  3. 修改 conf/server.xml,把AprLifecycleListeneruseAprConnector属性值为true。

    1
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" useAprConnector="true" />

    另外: 由于不使用https , 所以我这里把SSLEngine 设置为了 off

方式二: 指定使用APR

  1. 修改 conf/server.xmlprotocol设置为org.apache.coyote.http11.Http11AprProtocol 强制使用 APR

    1
    2
    3
    4
    5
    <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
    connectionTimeout="20000"
    redirectPort="8443"
    URIEncoding="UTF-8"
    />
  2. 通过JAVA选项指定 tomcat native library的位置,设置自定义选项建议使用$TOMCAT_PATH/bin/setenv.sh:

    1
    2
    #!/bin/bash
    JAVA_OPTS="$JAVA_OPTS -Djava.library.path=/usr/local/apr/lib"

验证

在tomcat日志里看到org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-apr-8080"] ,注意如果是http-apr- 说明启用APR成功了,如果是http-nio就说明还是用的 java nio。 大致启动信息如下:

1
2
3
4
5
6
7
8
9
10
10-Mar-2022 17:29:18.011 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本: Apache Tomcat/8.5.76
...
10-Mar-2022 17:29:18.015 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent 使用APR版本[1.4.8]加载了基于APR的Apache Tomcat本机库[1.2.31]。
10-Mar-2022 17:29:18.015 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR功能:IPv6[true]、sendfile[true]、accept filters[false]、random[true]。
10-Mar-2022 17:29:18.015 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL配置:useAprConnector[true],useOpenSSL[true]
10-Mar-2022 17:29:18.098 信息 [main] org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-apr-8080"]
...
10-Mar-2022 17:29:18.125 信息 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 495 ms
10-Mar-2022 17:29:18.149 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina]
10-Mar-2022 17:29:18.149 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/8.5.76]