Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to configure UnderTow for Spring Cloud and use it as a container

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is about how to configure the UnderTow of Spring Cloud and use it as a container. The editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

In our project, instead of using the default Tomcat container, we used UnderTow as our container. In fact, the difference in performance is not so obvious, but with UnderTow, we can use direct memory as the buffer for network transmission, reduce the GC of the business, and optimize the performance of the business.

* * official website of Undertow * *: https://undertow.io/

However, Undertow has some worrying things:

The NIO framework uses [XNIO] (http://xnio.jboss.org/), mentioned in the official website 3.0 roadmap statement that it will be migrated from XNIO to netty starting from version 3.0, see [Undertow 3.0 Announcement] (https://undertow.io/blog/2019/04/15/Undertow-3.html)). However, nearly two years later, * * 3.0 has not been released, and the 3.0 branch of github has not been updated for more than a year. Currently, the 2.x version of Undertow is still in use. I don't know if 3.0 is not necessary to develop at present, or is it stillborn? At present, the domestic environment is more widely used for netty and most people are more familiar with netty, but there are not many XNIO applications. However, the design of XNIO is more or less the same as netty. 2. * * the update of official documents is slow, which may be slow by 1 / 2 small versions * *, which causes the configuration to be less elegant when Spring Boot is glued to Undertow. * * while referring to the official documentation, it is best to take a look at the source code, or at least the configuration class, to figure out how to set it * *.

* * the update of official documents is slow, which may be slow by 1 / 2 small versions * *, which causes the configuration of Spring Boot to be less elegant when gluing Undertow. * * while referring to the official documentation, it is best to take a look at the source code, or at least the configuration class, to figure out how to set it * *.

If you take a closer look at the source code of Undertow, you will find that there are a lot of defensive programming or functional design Undertow authors thought of, but did not implement, * * there are a lot of semi-finished code that has not been implemented * *. This also makes people worry about whether the development of Underow is under-motivated and will suddenly die one day.

* * points to pay attention to when using Undertow * *:

1. Need to turn on the features of NIO DirectBuffer, understand and configure the relevant parameters.

2. Some necessary time, call chain and other information should be included in the access.log. By default, some of the parameters in the access.log are only configured or cannot display the information we want to see. The official website does not specify some details of the parameters in the access.log.

# using Undertow as our Web service container

For Servlet containers, the dependencies are as follows:

```org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat org.springframework.boot spring-boot-starter- undertow````

For Weflux containers, the dependencies are as follows:

```org.springframework.boot spring-boot-starter-webflux org.springframework.boot spring-boot-starter- undertow````

# basic structure of Undertow

Undertow is currently (2.x) based on Java XNIO,Java XNIO, which is an extension of the JDK NIO class, and the basic functions of netty are the same, but netty is more like an encapsulation of Java NIO and Java XNIO is more like an extension encapsulation. The basic transmission of bearer data in netty is not the `ByteBuffer` in Java NIO, but the encapsulated `ByteBuf`, while the design of each interface of Java XNIO is based on `ByteBuffer` as the transmission processing unit. The design is also very similar, it is the design of the Reactor model.

Java XNIO mainly includes the following concepts:

-Java NIO `ByteBuffer`: `Buffer` is an array with state, which is used to hold data and track what has been written or read. The main attributes include: capacity (the capacity of Buffer), position (the next location subscript to read or write), and limit (the current limit position that can be written or read). * * the program can only read or write data from Channel by putting data into Buffer * *. `ByteBuffer` is a more special Buffer, which can be allocated with direct memory, so that JVM can directly use this Bytebuffer for IO operations, saving one step of replication (see my article: [Java out-of-heap memory, zero-copy, direct memory and thinking about FileChannel in NIO] (https://zhuanlan.zhihu.com/p/161939673)). You can also allocate memory directly through file mapping, namely Java MMAP (see my article: [JDK Core JAVA Source Code parsing (5)-JAVA File MMAP principle parsing] (https://zhuanlan.zhihu.com/p/258934554)). Therefore, most IO operations are done through ByteBuffer.

-Java NIO `Channel`: Channel is an abstraction in Java for opening a connection with an external entity (such as hardware devices, files, network connection socket, or some components that can perform IO operations). Channel is primarily the source of IO events, and all data written or read must go through Channel. For the Channel of NIO, the event is notified by `Selector` (such as read and write), and then read or written through Buffer.

-XNIO `Worker`: Worker is the basic network processing unit in the Java XNIO framework. A Worker contains two different thread pool types, which are:

-* * IO thread pool * *. `Thread () `is mainly called to handle various callbacks of corresponding events. In principle, you cannot handle any blocked tasks, as this will cause other connections to fail to handle. The IO thread pool consists of two types of threads (in the XNIO framework, the size of the thread pool is set by setting WORKER_IO_THREADS, which defaults to one CPU and one IO thread):

-* * read thread * *: callback for handling read events

-* * write thread * *: callback for handling write events

-* * Worker thread pool * * to handle blocked tasks. In the design of Web servers, calling servlet tasks are generally placed in this thread pool (in the XNIO framework, the thread pool size is set by setting WORKER_TASK_CORE_THREADS)

-XNIO `ChannelListener`: ChannelListener is an abstraction used to listen for Channel events, including: `ChannelListener`, `channel readable`, `channel writable`, `channel opened`, `channel closed`, `channel bounds`, `channel unbound`

Undertow is a XNIO-based Web service container. On the basis of XNIO, add:

-Undertow `BufferPool`: if you apply for ByteBuffer every time you need it, you need to follow the JVM memory allocation process (TLAB-> heap) for ByteBuffer of heap memory and system call for direct memory, which is very inefficient. Therefore, memory pools are generally introduced. Here is `BufferPool`. Currently, there is only one `DefaultByteBufferPool` in UnderTow, and other implementations are currently useless. This DefaultByteBufferPool is very simple compared to netty's ByteBufArena, similar to JVM TLAB's mechanism (you can refer to my other series: [the hardest JVM TLAB Analysis of the whole Network] (https://juejin.cn/post/6925217498723778568)), but it is much simplified. * * We only need to configure buffer size and enable the use of direct memory * *.

-Undertow `Listener`: there are three kinds of Listener built into by default, namely the Listener corresponding to HTTP/1.1, AJP and HTTP/2 (HTTPS enables SSL implementation through the corresponding HTTP Listner), which is responsible for resolving all requests. After parsing, the request is packaged into `HttpServerExchange` and handed over to the subsequent `Handler` for processing.

-Undertow `Handler`: processes the response business through Handler to form a complete Web server.

# some default configurations of Undertow

Undertow's Builder sets some default parameters. Refer to the source code:

[`Undertow`] (https://github.com/undertow-io/undertow/blob/2.2.7.Final/core/src/main/java/io/undertow/Undertow.java)

````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 字节用于协议头。 # Undertow Buffer Pool 配置 [`DefaultByteBufferPool`](https://github.com/undertow-io/undertow/blob/2.2.7.Final/core/src/main/java/io/undertow/server/DefaultByteBufferPool.java) 构造器: ```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_rmem4096 16384 4194304 bash-4.2# cat /proc/sys/net/ipv4/tcp_wmem4096 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 ->

Heap), for direct memory, you need to take system calls, which is very inefficient. # therefore, memory pools are generally introduced. Here is `BufferPool`. # currently, there is only one `DefaultByteBufferPool` in UnderTow, and other implementations are currently useless. # this DefaultByteBufferPool is very simple compared to netty's ByteBufArena, similar to JVM TLAB mechanism # for bufferSize, it's better to be the same as your system's TCP Socket Buffer configuration # `/ proc/sys/net/ipv4/tcp_ rmem` (for reading) #` / proc/sys/net/ipv4/tcp_ wmem` (for writing) # bufferSize is 16 KB minus 20 bytes when memory is greater than 128MB These 20 bytes are used for the protocol header buffer-size: 16384-20```

# Undertow Worker configuration

Worker configuration is actually the core configuration of XNIO, and the main things that need to be configured are io thread pool and worker thread pool size.

By default, the io thread size is the number of available CPU * 2, that is, the number of read threads is the number of available CPU, and the number of write threads is the number of available CPU. Worker thread pool size is io thread size * 8.

Micro-service applications can increase the size of the worker thread pool because it involves a lot of blocking operations. Our application is set to the io thread size * 32.

`application.yml` configuration:

````server.undertow.threads: # sets the number of IO threads, which mainly performs non-blocking tasks, which are responsible for multiple connections. By default, each CPU core has one read thread and one write thread. Io: 16 # blocks the task thread pool. When performing a similar servlet request blocking IO operation, undertow will get threads from this thread pool. Its value setting depends on the blocking coefficient of the system thread executing the task. The default is the number of IO threads * 8 worker: 128```

# Undertow configuration in Spring Boot

The abstraction for Undertow-related configurations in Spring Boot is [`ServerProperties`] (class https://github.com/spring-projects/spring-boot/blob/2.4.x/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java)). All the configurations involved in Undertow are described as follows (excluding those related to accesslog, which will be analyzed in detail in the next section):

The following configurations of ```server: undertow: # will affect buffer, and these buffer will be used for IO operations of server connections # if you apply for ByteBuffer every time you need it, you need to go through the JVM memory allocation process (TLAB-> heap) for ByteBuffer of heap memory and system calls for direct memory, which is very inefficient. # therefore, memory pools are generally introduced. Here is `BufferPool`. # currently, there is only one `DefaultByteBufferPool` in UnderTow, and other implementations are currently useless. # this DefaultByteBufferPool is very simple compared to netty's ByteBufArena, similar to JVM TLAB mechanism # for bufferSize, it's better to be the same as your system's TCP Socket Buffer configuration # `/ proc/sys/net/ipv4/tcp_ rmem` (for reading) #` / proc/sys/net/ipv4/tcp_ wmem` (for writing) # bufferSize is 16 KB minus 20 bytes when memory is greater than 128MB These 20 bytes are used for the direct memory allocated by the protocol header buffer-size: 16364 # (out-of-heap memory allocated directly by NIO), which is enabled here, so the java startup parameters need to be configured with direct memory size to reduce unnecessary GC # when the memory is greater than 128MB. The default is to use the directBuffers: true threads: # of direct memory to set the number of IO threads, which mainly performs non-blocking tasks, which are responsible for multiple connections. By default, each CPU core has one read thread and one write thread io: 4 # blocking task thread pool, when performing similar servlet request blocking IO operations Undertow will get the thread from this thread pool # its value setting depends on the blocking factor of the system thread executing the task The default is the number of IO threads * 8 worker: 128 # http post body size, default is-1B, that is, there is no restriction on whether max-http-post-size:-1B # creates a filter at startup, defaults to true, does not need to modify eager-filter-init: true # to limit the number of path parameters, and defaults to 1000 max-parameters: 1000 # limit the number of http header The default is 200max-headers: 200# to limit the number of key-value pairs of cookies in http header, and whether 200max-cookies: 200# allows / escapes with% 2F by default. / is a reserved word for URL. Do not enable this escape unless your application explicitly needs it. The default is whether false allow-encoded-slash: false # allows URL decoding. The default is true. All but% 2F will handle the decode-url: true # url character encoding set. The default is whether the http header of utf-8 url-charset: utf-8 # response will add 'Connection: keep-alive' The default is true always-set-keep-alive: true # request timeout, and the default is no timeout. Because our micro services may have scheduled tasks for a long time, we do not do server timeout, but use client timeout. So we keep this default configuration: no-request-timeout:-1 # whether to keep path when redirecting, and whether it is turned off by default Generally, there is no need to configure preserve-path-on-forward: false options: # spring boot. No abstract xnio-related configuration is configured here for the corresponding org.xnio.Options class socket: SSL_ENABLED: false # spring boot. There is no abstract undertow-related configuration for the corresponding io.undertow.UndertowOptions class server: ALLOW_UNKNOWN_PROTOCOLS: false ``.

Spring Boot does not abstract all Undertow and XNIO configurations. If you want to customize some related configurations, you can configure them through `server.undertow.options` at the end of the above configuration. `server.undertow.options.socket` corresponds to the relevant configuration of XNIO, the configuration class is `org.xnio.Options`; `server.undertow.options.server` corresponds to the configuration of Undertow, and the configuration class is `io.undertow.UndertowOptions`. Http://www.2798888.com/

The above is how to configure the UnderTow of Spring Cloud and use it as a container. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report