APR(Apache Portable Runtime Libraries)是用 C 语言实现的,其目的是向上层应用程序提供一个跨平台的操作系统接口库。

和 NioEndpoint 的区别

Tomcat 可以用它来处理包括文件和网络 I/O,从而提升性能。Tomcat 支持的连接器有 NIO、NIO.2 和 APR。跟 NioEndpoint 一样,AprEndpoint 也实现了非阻塞 I/O,区别是:
NioEndpoint 通过调用 Java 的 NIO API 来实现非阻塞 I/O
AprEndpoint 是通过 JNI 调用 APR 本地库而实现非阻塞 I/O
image.png

Acceptor 和 Poller 的实现和 NioEndpoint 不同。

Poller的不同

TCP 协议中的TCP_DEFER_ACCEPT,设置这个参数后,当 TCP 客户端有新的连接请求到达时,TCP 服务端先不建立连接,而是再等等,直到客户端有请求数据发过来时再建立连接。这样的好处是服务端不需要用 Selector 去反复查询请求数据是否就绪。

这是一种 TCP 协议层的优化,不是每个操作系统内核都支持,因为 Java 作为一种跨平台语言,需要屏蔽各种操作系统的差异,因此并没有把这个参数提供给用户;但是对于 APR 来说,它的目的就是尽可能提升性能,因此它向用户暴露了这个参数。

本地内存与JVM堆

JVM 本质也是一个进程。
JVM 用到的内存(包括堆、栈和方法区)就是从进程的虚拟地址空间上分配的。
请你注意的是,JVM 内存只是进程空间的堆区的一部分,除此之外进程空间内还有代码段、数据段、内存映射区、内核空间等。从 JVM 的角度看,JVM 内存之外的部分叫作本地内存,C 程序代码在运行过程中用到的内存就是本地内存中分配的。下面我们通过一张图来理解一下。
image.png

性能优化手段

通过 DirectByteBuffer 避免 JVM 堆与本地内存之间的内存拷贝;
通过 sendfile 特性避免内核与应用之间的内存拷贝以及用户态和内核态的切换。

很多高性能网络通信组件,比如 Netty,都是通过 DirectByteBuffer 来收发网络数据的。由于本地内存难于管理,Netty 采用了本地内存池技术。

https://time.geekbang.org/column/article/101201