深入拆解 Tomcat & Jetty
李号双
eBay 技术主管
38890 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
开篇词 (1讲)
深入拆解 Tomcat & Jetty
15
15
1.0x
00:00/00:00
登录|注册

16 | AprEndpoint组件:Tomcat APR提高I/O性能的秘密

解决静态文件处理中的内存拷贝问题
DirectByteBuffer避免了JVM堆与本地内存之间的内存拷贝
HeapByteBuffer vs DirectByteBuffer
配置deferAccept参数
通过JNI调用APR实现的epoll API
通过JNI调用APR中的poll方法
通过JNI调用APR实现的四个API
调用操作系统API:Socket、Bind、Listen和Accept
为什么不同的操作系统都有自己的Java虚拟机
sendfile特性避免了内存拷贝和用户态和内核态的切换
DirectByteBuffer避免了内存拷贝
TLS协议握手过程中的多次网络交互
频繁与操作系统进行交互
sendfile
JVM堆 VS 本地内存
Poller
Acceptor
LimitLatch
APR通过JNI调用APR本地库实现非阻塞I/O
NIO、NIO.2和APR
用于处理文件和网络I/O,提升性能
跨平台的操作系统接口库
用C语言实现
课后思考
性能提升原因
APR提升性能的秘密
AprEndpoint工作过程
Tomcat连接器
APR(Apache Portable Runtime Libraries)
Tomcat APR提高I/O性能的秘密

该思维导图由 AI 生成,仅供参考

我们在使用 Tomcat 时,会在启动日志里看到这样的提示信息:
The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: ***
这句话的意思就是推荐你去安装 APR 库,可以提高系统性能。那什么是 APR 呢?
APR(Apache Portable Runtime Libraries)是 Apache 可移植运行时库,它是用 C 语言实现的,其目的是向上层应用程序提供一个跨平台的操作系统接口库。Tomcat 可以用它来处理包括文件和网络 I/O,从而提升性能。我在专栏前面提到过,Tomcat 支持的连接器有 NIO、NIO.2 和 APR。跟 NioEndpoint 一样,AprEndpoint 也实现了非阻塞 I/O,它们的区别是:NioEndpoint 通过调用 Java 的 NIO API 来实现非阻塞 I/O,而 AprEndpoint 是通过 JNI 调用 APR 本地库而实现非阻塞 I/O 的。
那同样是非阻塞 I/O,为什么 Tomcat 会提示使用 APR 本地库的性能会更好呢?这是因为在某些场景下,比如需要频繁与操作系统进行交互,Socket 网络通信就是这样一个场景,特别是如果你的 Web 应用使用了 TLS 来加密传输,我们知道 TLS 协议在握手过程中有多次网络交互,在这种情况下 Java 跟 C 语言程序相比还是有一定的差距,而这正是 APR 的强项。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Tomcat APR提高I/O性能的秘密 Tomcat APR提高I/O性能的秘密在于其利用APR库实现非阻塞I/O,通过JNI调用本地库,提升系统性能。APR连接器通过Acceptor和Poller组件实现操作系统API的调用,同时提供TCP协议层的优化参数`deferAccept`,从而提高性能。此外,文章还介绍了JVM堆与本地内存的关系,以及DirectByteBuffer和HeapByteBuffer的区别,指出Tomcat的AprEndpoint通过DirectByteBuffer来接收数据,而NioEndpoint和Nio2Endpoint则使用HeapByteBuffer。另外,文章还介绍了AprEndpoint利用操作系统层面的sendfile特性来解决静态文件处理中的内存拷贝问题。总结来看,APR提升性能的秘密包括利用DirectByteBuffer避免内存拷贝,以及通过sendfile特性避免内存拷贝和用户态与内核态的切换。这些技术特点有助于提高系统性能,尤其适用于需要处理大量网络I/O的应用场景。文章还提到了Netty等高性能网络通信组件的相关技术,为读者提供了进一步探索的思路。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Tomcat & Jetty 》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(35)

  • 最新
  • 精选
  • YF
    老师,为什么从本地内存到 JVM 堆的拷贝过程中 JVM 可以保证不做 GC呢?那为什么从内核拷贝到JVM堆中就不能保证做GC呢?

    作者回复: 这是HotSpot VM层面保证的,具体来说就是HotSpot不是什么时候都能GC的,需要JVM中各个线程都处在“safepoint”时才能GC, 本地内存到JVM 堆的拷贝过程中是没有“safepoint”的,所以不会GC,至于什么是“safepoint”,你可以搜索一下。

    2019-06-15
    44
  • -W.LI-
    NIO 的 Buffer 除了做了缓冲块优化之外,还提供了一个可以直接访问物理内存的类 DirectBuffer。普通的 Buffer 分配的是 JVM 堆内存,而 DirectBuffer 是直接分配物理内存。 我们知道数据要输出到外部设备,必须先从用户空间复制到内核空间,再复制到输出设备,而 DirectBuffer 则是直接将步骤简化为从内核空间复制到外部设备,减少了数据拷贝。 李老师好!上面是隔壁班刘超老师的原话。好像和您讲的优点冲突。请问答题时写哪个答案啊?

    作者回复: Directbytebuffer是通过Unsafe类来分配本地内存的,实际上调用了C语言中的allocate来分配内存,是属于用户空间的。 base = unsafe.allocateMemory(size); 从用户空间到内核空间中需要有一次数据拷贝,应用程序不能直接操作内核空间。知乎上也有人问了这个问题: https://www.zhihu.com/question/269052579/answer/354173816

    2019-06-20
    3
    28
  • 飞翔
    老师 能不能讲讲什么时候用apr 什么时候用nio2 nio?

    作者回复: 如果web应用使用tls通信,对性能响应时间要求比较高,而用户又愿意花时间去配置APR,推荐APR。 NIO和NIO2其实差别不是很大,如果硬要区分,NIO适合处理比较轻的,数据传输量比较少的请求,AIO适合比较重,数据传输量比较大的请求。 这是因为NIO本质还是同步,数据从用户空间和内核空间之间的拷贝还是阻塞的。

    2019-06-16
    16
  • 鱼仔💪
    看老师课收获很多,老师讲的很好,这一讲有个问题: 之前讲到 同步和异步,是指应用程序在与内核通信时,数据从内核空间到应用空间的拷贝,是由内核主动发起还是由应用程序来触发。 JVM 内存只是进程空间的一部分,除此之外进程空间内还有代码段、数据段、内存映射区、内核空间等。 从内核空间到应用空间的拷贝是 应用程序本地内存向JVM堆上的拷贝;还是内核缓冲区向 应用程序本地内存的拷贝?

    作者回复: 是内核缓冲区向应用程序本地内存的拷贝

    2019-07-16
    11
  • 一道阳光
    java语言有个特性,一次编译到处执行,而class文件需要通过虚拟机编译成操作系统指令。不同操作系统的指令不一样,所以有对应的虚拟机来简化代码开发。c语言好像是直接调用操作系统指令,代码开发中调用一个方法,不同的操作系统可能不一样,还得准备两份。老师,说的对吗?

    作者回复: 对的

    2019-06-15
    9
  • 粉条炒肉
    老师,请教一个问题,每次服务的访问高峰期重启或者发布tomcat服务,都会出现阻塞线程过多 这种情况是不是容器初始化的时候需要预热很多资源,从而响应不过来请求而导致阻塞,关于这种情况,有什么好的解决办法。

    作者回复: 服务没有启动完成的时候,不要把流量送过来。

    2019-06-15
    8
  • gameboy120
    请问从本地内存拷贝到jvm堆不会引起gc是在哪里有说明?

    作者回复: 文中没有说明,展开会收不住,你可以搜索hotspot vm的safepoint是怎么回事

    2019-07-10
    7
  • 陆离
    虚拟机只是抽象了操作系统,但并不是虚拟机也是一套的。 jvm的解释器在不同操作系统下是不同的,因为要将字节码解释生成本地机器码。 这么简单个问题,感觉还是解释不清楚,这个要和操作系统原理联系起来了。 烦请老师做一个详细的简单!

    作者回复: JVM为了跟操作系统打交道,必须调用操作系统提供的API,而每个操作系统提供的API都不同,所以必须针对不同的操作系统实现不同的JVM,这样位于JVM之上的Java字节码才可以实现跨平台。

    2019-06-15
    7
  • 尔冬橙
    老师,tomcat解决了NIO的epoll空轮询么?

    作者回复: 没有,Tomcat只是使用了epoll

    2019-08-09
    6
  • -W.LI-
    老师好! 网卡->内核->用户空间->内核->网卡。 IO读写都需要拷贝两次。 之前一直不理解为啥不直接到用户空间,看完老师的解释才知道是因为网卡直接到用户空间,容易GC,GC后内存映射地址改变。所以多了一次内核空间做桥接。大部分基于虚拟机的语言都会有这个问题?

    作者回复: 跟GC的实现有关,GC有多种算法,有的需要移动对象,有的不需要,如果不需要移动对象就没有问题。

    2019-06-20
    4
    5
收起评论
显示
设置
留言
35
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部