共计 5079 个字符,预计需要花费 13 分钟才能阅读完成。
本系列代码地址:https://github.com/HashZhang/…
Undertow 的配置能够参考 Undertow 的 Builder,并且其中也有一些默认的配置参数:
Undertow
private Builder() {ioThreads = Math.max(Runtime.getRuntime().availableProcessors(), 2);
workerThreads = ioThreads * 8;
long maxMemory = Runtime.getRuntime().maxMemory();
//smaller than 64mb of ram we use 512b buffers
if (maxMemory < 64 * 1024 * 1024) {
//use 512b buffers
directBuffers = false;
bufferSize = 512;
} else if (maxMemory < 128 * 1024 * 1024) {
//use 1k buffers
directBuffers = true;
bufferSize = 1024;
} else {
//use 16k buffers for best performance
//as 16k is generally the max amount of data that can be sent in a single write() call
directBuffers = true;
bufferSize = 1024 * 16 - 20; //the 20 is to allow some space for protocol headers, see UNDERTOW-1209
}
}
- ioThreads 大小为可用 CPU 数量 * 2,即 Undertow 的 XNIO 的读线程个数为可用 CPU 数量,写线程个数也为可用 CPU 数量。
- workerThreads 大小为 ioThreads 数量 * 8.
- 如果内存大小小于 64 MB,则不应用间接内存,bufferSize 为 512 字节
- 如果内存大小大于 64 MB 小于 128 MB,则应用间接内存,bufferSize 为 1024 字节
- 如果内存大小大于 128 MB,则应用间接内存,bufferSize 为 16 KB 减去 20 字节,这 20 字节用于协定头。
DefaultByteBufferPool
结构器:
public DefaultByteBufferPool(boolean direct, int bufferSize, int maximumPoolSize, int threadLocalCacheSize, int leakDecetionPercent) {
this.direct = direct;
this.bufferSize = bufferSize;
this.maximumPoolSize = maximumPoolSize;
this.threadLocalCacheSize = threadLocalCacheSize;
this.leakDectionPercent = leakDecetionPercent;
if(direct) {arrayBackedPool = new DefaultByteBufferPool(false, bufferSize, maximumPoolSize, 0, leakDecetionPercent);
} else {arrayBackedPool = this;}
}
其中:
- direct:是否应用间接内存,咱们须要设置为 true,来应用间接内存。
- bufferSize:每次申请的 buffer 大小,咱们次要要思考这个大小
- maximumPoolSize:buffer 池最大大小,个别不必批改
- threadLocalCacheSize:线程本地 buffer 池大小,个别不必批改
- leakDecetionPercent:内存透露查看百分比,目前没啥卵用
对于 bufferSize,最好和你零碎的 TCP Socket Buffer 配置一样。在咱们的容器中,咱们将微服务实例的容器内的 TCP Socket Buffer 的读写 buffer 大小成截然不同的配置(因为微服务之间调用,发送的申请也是另一个微服务承受,所以调整所有微服务容器的读写 buffer 大小统一,来优化性能,默认是依据零碎内存来主动计算出来的)。
查看 Linux 零碎 TCP Socket Buffer 的大小:
/proc/sys/net/ipv4/tcp_rmem
(对于读取)/proc/sys/net/ipv4/tcp_wmem
(对于写入)
在咱们的容器中,别离是:
bash-4.2# cat /proc/sys/net/ipv4/tcp_rmem
4096 16384 4194304
bash-4.2# cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4194304
从左到右三个值别离为:每个 TCP Socket 的读 Buffer 与写 Buffer 的大小的 最小值,默认值和最大值,单位是字节。
咱们设置咱们 Undertow 的 buffer size 为 TCP Socket Buffer 的默认值, 即 16 KB。Undertow 的 Builder 外面,如果内存大于 128 MB,buffer size 为 16 KB 减去 20 字节(为协定头预留)。所以, 咱们应用默认的即可 。
application.yml
配置:
server.undertow:
# 是否调配的间接内存 (NIO 间接调配的堆外内存),这里开启,所以 java 启动参数须要配置下间接内存大小,缩小不必要的 GC
# 在内存大于 128 MB 时,默认就是应用间接内存的
directBuffers: true
# 以下的配置会影响 buffer, 这些 buffer 会用于服务器连贯的 IO 操作
# 如果每次须要 ByteBuffer 的时候都去申请,对于堆内存的 ByteBuffer 须要走 JVM 内存调配流程(TLAB -> 堆),对于间接内存则须要走零碎调用,这样效率是很低下的。# 所以,个别都会引入内存池。在这里就是 `BufferPool`。# 目前,UnderTow 中只有一种 `DefaultByteBufferPool`,其余的实现目前没有用。# 这个 DefaultByteBufferPool 绝对于 netty 的 ByteBufArena 来说,非常简单,相似于 JVM TLAB 的机制
# 对于 bufferSize,最好和你零碎的 TCP Socket Buffer 配置一样
# `/proc/sys/net/ipv4/tcp_rmem` (对于读取)
# `/proc/sys/net/ipv4/tcp_wmem` (对于写入)
# 在内存大于 128 MB 时,bufferSize 为 16 KB 减去 20 字节,这 20 字节用于协定头
buffer-size: 16384 - 20
Worker 配置其实就是 XNIO 的外围配置,次要须要配置的即 io 线程池以及 worker 线程池大小。
默认状况下,io 线程大小为可用 CPU 数量 2,即读线程个数为可用 CPU 数量,写线程个数也为可用 CPU 数量。worker 线程池大小为 io 线程大小 8.
微服务利用因为波及的阻塞操作比拟多,所以能够将 worker 线程池大小调大一些。咱们的利用设置为 io 线程大小 * 32.
application.yml
配置:
server.undertow.threads:
# 设置 IO 线程数, 它次要执行非阻塞的工作, 它们会负责多个连贯, 默认设置每个 CPU 外围一个读线程和一个写线程
io: 16
# 阻塞工作线程池, 当执行相似 servlet 申请阻塞 IO 操作, undertow 会从这个线程池中获得线程
# 它的值设置取决于零碎线程执行工作的阻塞系数,默认值是 IO 线程数 *8
worker: 128
Spring Boot 中对于 Undertow 相干配置的形象是 ServerProperties
这个类。目前 Undertow 波及的所有配置以及阐明如下(不包含 accesslog 相干的,accesslog 会在下一节详细分析):
server:
undertow:
# 以下的配置会影响 buffer, 这些 buffer 会用于服务器连贯的 IO 操作
# 如果每次须要 ByteBuffer 的时候都去申请,对于堆内存的 ByteBuffer 须要走 JVM 内存调配流程(TLAB -> 堆),对于间接内存则须要走零碎调用,这样效率是很低下的。# 所以,个别都会引入内存池。在这里就是 `BufferPool`。# 目前,UnderTow 中只有一种 `DefaultByteBufferPool`,其余的实现目前没有用。# 这个 DefaultByteBufferPool 绝对于 netty 的 ByteBufArena 来说,非常简单,相似于 JVM TLAB 的机制
# 对于 bufferSize,最好和你零碎的 TCP Socket Buffer 配置一样
# `/proc/sys/net/ipv4/tcp_rmem` (对于读取)
# `/proc/sys/net/ipv4/tcp_wmem` (对于写入)
# 在内存大于 128 MB 时,bufferSize 为 16 KB 减去 20 字节,这 20 字节用于协定头
buffer-size: 16364
# 是否调配的间接内存 (NIO 间接调配的堆外内存),这里开启,所以 java 启动参数须要配置下间接内存大小,缩小不必要的 GC
# 在内存大于 128 MB 时,默认就是应用间接内存的
directBuffers: true
threads:
# 设置 IO 线程数, 它次要执行非阻塞的工作, 它们会负责多个连贯, 默认设置每个 CPU 外围一个读线程和一个写线程
io: 4
# 阻塞工作线程池, 当执行相似 servlet 申请阻塞 IO 操作, undertow 会从这个线程池中获得线程
# 它的值设置取决于零碎线程执行工作的阻塞系数,默认值是 IO 线程数 *8
worker: 128
# http post body 大小,默认为 -1B,即不限度
max-http-post-size: -1B
# 是否在启动时创立 filter,默认为 true,不必批改
eager-filter-init: true
# 限度门路参数数量,默认为 1000
max-parameters: 1000
# 限度 http header 数量,默认为 200
max-headers: 200
# 限度 http header 中 cookies 的键值对数量,默认为 200
max-cookies: 200
# 是否容许 / 与 %2F 本义。/ 是 URL 保留字, 除非你的利用明确须要,否则不要开启这个本义,默认为 false
allow-encoded-slash: false
# 是否容许 URL 解码,默认为 true,除了 %2F 其余的都会解决
decode-url: true
# url 字符编码集,默认是 utf-8
url-charset: utf-8
# 响应的 http header 是否会加上 'Connection: keep-alive',默认为 true
always-set-keep-alive: true
# 申请超时,默认是不超时,咱们的微服务因为可能有长时间的定时工作,所以不做服务端超时,都用客户端超时,所以咱们放弃这个默认配置
no-request-timeout: -1
# 是否在跳转的时候放弃 path,默认是敞开的,个别不必配置
preserve-path-on-forward: false
options:
# spring boot 没有形象的 xnio 相干配置在这里配置,对应 org.xnio.Options 类
socket:
SSL_ENABLED: false
# spring boot 没有形象的 undertow 相干配置在这里配置,对应 io.undertow.UndertowOptions 类
server:
ALLOW_UNKNOWN_PROTOCOLS: false
Spring Boot 并没有将所有的 Undertow 与 XNIO 配置进行形象,如果你想自定义一些相干配置,能够通过下面配置最初的 server.undertow.options
进行配置。server.undertow.options.socket
对应 XNIO 的相干配置,配置类是 org.xnio.Options
;server.undertow.options.server
对应 Undertow 的相干配置,配置类是 io.undertow.UndertowOptions
。
咱们这一节具体介绍了 Undertow 的外围配置,次要包含线程池以及 buffer 配置,以及对于 http 协定的一些配置。并且咱们还介绍了这些配置在 spring boot 下该如何配置。下一节,咱们将具体介绍如何配置 Undertow 的 accesslog。
微信搜寻“我的编程喵”关注公众号,每日一刷,轻松晋升技术,斩获各种 offer: