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

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

SpringCloud升级之路2020.0.x版-13.UnderTow 核心配置的更多相关文章

  1. SpringCloud升级之路2020.0.x版-14.UnderTow AccessLog 配置介绍

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

  2. SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(1)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面一节,我们利用 resilience4j 粘合了 OpenFeign 实现了断路器. ...

  3. SpringCloud升级之路2020.0.x版-12.UnderTow 简介与内部原理

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 在我们的项目中,我 ...

  4. SpringCloud升级之路2020.0.x版-15.UnderTow 订制

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

  5. SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(2)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们继续上一节针对我们的重试进行测试 验证针对限流器异常的重试正确 通过系列前面的源码分析 ...

  6. SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(3)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们继续上一节针对我们的重试进行测试 验证针对可重试的方法响应超时异常重试正确 我们可以通 ...

  7. SpringCloud升级之路2020.0.x版-1.背景

    本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ Spring ...

  8. SpringCloud升级之路2020.0.x版-41. SpringCloudGateway 基本流程讲解(1)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 接下来,将进入我们升级之路的又一大模块,即网关模块.网关模块我们废弃了已经进入维护状态的 ...

  9. SpringCloud升级之路2020.0.x版-6.微服务特性相关的依赖说明

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

随机推荐

  1. Integer Inquiry 大数加法

    Integer Inquiry 1 import java.util.*; 2 import java.math.*; 3 import java.io.*; 4 import java.text.* ...

  2. 树莓派4B-SPI读写flash-FM25CL16B(同时支持FM25CL64等其它系列Flash)

    1.树莓派SPI介绍 4B的引脚如下图所示: 其中Pin19.21.23是SPI0,接口定义如下所示: 时钟(SPI CLK, SCLK) 主机输出.从机输入(MOSI) 主机输入.从机输出(MISO ...

  3. Git常用命令超级详细(全网最详细)

    1.新建代码库 1.1在当前目录新建一个 Git 代码库 $ git init 1.2新建一个目录,将其初始化为 Git 代码库 $ git init [project-name] 1.3下载一个项目 ...

  4. [心得体会]RabbitMQ

    RabbitMQ是什么? 消息队列, 基于AMQP(高级消息队列), 使用Erlang语言编写, 收发消息使用 有什么用? 有什么应用场景? 1. 任务异步处理 2. 应用程序解耦 为什么使用Rabb ...

  5. Flask(9)- 蓝图的基本使用

    前言 在前面的例子中,所有的页面处理逻辑都是放在同一个文件中,随着业务代码的增加,将所有代码都放在单个程序文件中是非常不合适的 不仅会让阅读代码变得困难,而且会给后期维护带来麻烦 Flask 中使用蓝 ...

  6. WPF教程十四:了解元素的渲染OnRender()如何使用

    上一篇分析了WPF元素中布局系统的MeasureOverride()和ArrangeOverride()方法.本节将进一步深入分析和研究元素如何渲染它们自身. 大多数WPF元素通过组合方式创建可视化外 ...

  7. 「BZOJ2839」集合计数

    「BZOJ2839」集合计数 题目大意: 一个包含 \(n\) 个数的集合有 \(2^n\) 个子集,从这些子集中取出若干个集合(至少一个),使他们的交集的元素个数恰好为 \(k\),求方案数,答案对 ...

  8. 将make的输出(标准输出/标准错误输出)重定向到文件

    方式 描述符 含义 stdin 0 标准输入 stdout 1 标准输出 stderr 2 标准错误输出 1.想要把make输出的全部信息,输出到某个文件中 最常见的办法就是:make xxx > ...

  9. C语言:打印所有char字符

    #include <stdio.h> int main() { int aa; char bla; for(aa=0;aa<=255;aa++) { if(aa%10==0 and ...

  10. C语言:Unicode字符集

    Unicode 也称为统一码.万国码:看名字就知道,Unicode 希望统一所有国家的字符编码.Unicode 于 1994 年正式公布第一个版本,现在的规模可以容纳 100 多万个符号,是一个很大的 ...