SpringCloud升级之路2020.0.x版-13.UnderTow 核心配置

本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford

Undertow 的配置可以参考 Undertow 的 Builder,并且其中也有一些默认的配置参数:
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 字节用于协议头。

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:

SpringCloud升级之路2020.0.x版-13.UnderTow 核心配置的更多相关文章
- SpringCloud升级之路2020.0.x版-14.UnderTow AccessLog 配置介绍
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford server: u ...
- SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面一节,我们利用 resilience4j 粘合了 OpenFeign 实现了断路器. ...
- SpringCloud升级之路2020.0.x版-12.UnderTow 简介与内部原理
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 在我们的项目中,我 ...
- SpringCloud升级之路2020.0.x版-15.UnderTow 订制
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...
- SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(2)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们继续上一节针对我们的重试进行测试 验证针对限流器异常的重试正确 通过系列前面的源码分析 ...
- SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(3)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们继续上一节针对我们的重试进行测试 验证针对可重试的方法响应超时异常重试正确 我们可以通 ...
- SpringCloud升级之路2020.0.x版-1.背景
本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ Spring ...
- SpringCloud升级之路2020.0.x版-41. SpringCloudGateway 基本流程讲解(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 接下来,将进入我们升级之路的又一大模块,即网关模块.网关模块我们废弃了已经进入维护状态的 ...
- SpringCloud升级之路2020.0.x版-6.微服务特性相关的依赖说明
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford spring-cl ...
随机推荐
- Integer Inquiry 大数加法
Integer Inquiry 1 import java.util.*; 2 import java.math.*; 3 import java.io.*; 4 import java.text.* ...
- 树莓派4B-SPI读写flash-FM25CL16B(同时支持FM25CL64等其它系列Flash)
1.树莓派SPI介绍 4B的引脚如下图所示: 其中Pin19.21.23是SPI0,接口定义如下所示: 时钟(SPI CLK, SCLK) 主机输出.从机输入(MOSI) 主机输入.从机输出(MISO ...
- Git常用命令超级详细(全网最详细)
1.新建代码库 1.1在当前目录新建一个 Git 代码库 $ git init 1.2新建一个目录,将其初始化为 Git 代码库 $ git init [project-name] 1.3下载一个项目 ...
- [心得体会]RabbitMQ
RabbitMQ是什么? 消息队列, 基于AMQP(高级消息队列), 使用Erlang语言编写, 收发消息使用 有什么用? 有什么应用场景? 1. 任务异步处理 2. 应用程序解耦 为什么使用Rabb ...
- Flask(9)- 蓝图的基本使用
前言 在前面的例子中,所有的页面处理逻辑都是放在同一个文件中,随着业务代码的增加,将所有代码都放在单个程序文件中是非常不合适的 不仅会让阅读代码变得困难,而且会给后期维护带来麻烦 Flask 中使用蓝 ...
- WPF教程十四:了解元素的渲染OnRender()如何使用
上一篇分析了WPF元素中布局系统的MeasureOverride()和ArrangeOverride()方法.本节将进一步深入分析和研究元素如何渲染它们自身. 大多数WPF元素通过组合方式创建可视化外 ...
- 「BZOJ2839」集合计数
「BZOJ2839」集合计数 题目大意: 一个包含 \(n\) 个数的集合有 \(2^n\) 个子集,从这些子集中取出若干个集合(至少一个),使他们的交集的元素个数恰好为 \(k\),求方案数,答案对 ...
- 将make的输出(标准输出/标准错误输出)重定向到文件
方式 描述符 含义 stdin 0 标准输入 stdout 1 标准输出 stderr 2 标准错误输出 1.想要把make输出的全部信息,输出到某个文件中 最常见的办法就是:make xxx > ...
- C语言:打印所有char字符
#include <stdio.h> int main() { int aa; char bla; for(aa=0;aa<=255;aa++) { if(aa%10==0 and ...
- C语言:Unicode字符集
Unicode 也称为统一码.万国码:看名字就知道,Unicode 希望统一所有国家的字符编码.Unicode 于 1994 年正式公布第一个版本,现在的规模可以容纳 100 多万个符号,是一个很大的 ...