Spring Boot 内嵌容器Undertow参数设置

配置项:

# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
# 不要设置过大,如果过大,启动项目会报错:打开文件数过多
server.undertow.io-threads=16 # 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
server.undertow.worker-threads=256 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
server.undertow.buffer-size=1024 # 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region
server.undertow.buffers-per-region=1024 # 是否分配的直接内存(NIO直接分配的堆外内存)
server.undertow.direct-buffers=true

来看看源代码:

https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/Undertow.java

ioThreads = Math.max(Runtime.getRuntime().availableProcessors(), 2);

workerThreads = ioThreads * 8;

//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
}

很显然,Undertow认为它的运用场景是在IO密集型的系统应用中,并且认为多核机器是一个比较容易满足的点,Undertow初始化假想应用的阻塞系数在0.8~0.9之间,所以阻塞线程数直接乘了个8,当然,如果对应用较精确的估测阻塞系数,可以配置上去。

Spring Boot内嵌容器支持Tomcat、Jetty、Undertow。为什么选择Undertow?

这里有一篇文章,时间 2017年1月26日发布的:
Tomcat vs. Jetty vs. Undertow: Comparison of Spring Boot Embedded Servlet Containers

1. Setup Spring Boot Application

We will use Maven to setup a new project in Eclipse with the appropriate dependencies. We will use the starter parent for this example but the dependencies in a production application will likely be altered to streamline, optimize or customize.

1.1 Setup Spring Boot Dependencies

The default embedded servlet container is Tomcat. This version of Spring Web 1.4.3 brings in Tomcat version 8.5.6.

pom.xml

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent> <dependencies>
<!-- TOMCAT -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

1.2 Setup Spring Boot Main Application and Controllers

To setup the Spring Boot application you include the @SpringBootApplication annotation in your Main class. The @SpringBootApplication annotation brings in @SpringBootConfiguration@EnableAutoConfiguration and @ComponentScanannotations.

Application.java

@SpringBootApplication
@ConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

You may choose to eliminate this annotation and add the @SpringBootConfiguration alone or to another class that allows you to customize the configuration. The @ComponentScan will scan your application for items like the @Controller you will need to setup a RESTful service. The following controller will return a simple “Hello World” string from a HTTP GET request. We have also included in the bundled example another endpoint mapping that returns a complex object type.

SampleController.java

@Controller
public class SampleController { @Autowired
private ResourceLoader resourceLoader; @RequestMapping("/")
@ResponseBody
public String home() {
return "Hello World!";
}

1.3 Key Configuration Parameters

The default properties for all the embedded servlet containers are the same. Some of the most important properties to consider are the properties for configuring startup information like ports and application name, TSL, access logs, compression and many more.

For example, to configure SSL add the following to key value pairs to the application.properties.

application.properties

server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret

1.4 How to Find Additional Parameters

To explore the parameters for Spring boot applications you can add the Spring actuator dependency and the @ConfigurationProperties annotation to your Main class. You then visit the /configprops endpoint on your application to get a list of the available properties.

Application.java

@SpringBootApplication
@ConfigurationProperties
public class Application {

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

http://localhost:8080/jcg/service/configprops

1.5 Change version of Embedded Servlet Containers

The embedded servlet container versions are defined in the following parent dependency from the pom. You can change the version of the embedded servlet container by explicitly including the dependency and identifying a new version in the pom. We will show you how in the examples below.

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.7.RELEASE</version>
</dependency>

2. Tomcat

As Tomcat is the default embedded servlet container there is nothing you need to do to the default implementation to use Tomcat. You can change the version of Tomcat you are using or change properties in the pom.xml or application.properties files.

2.2 Change Version of Tomcat

pom.xml

<properties>
<tomcat.version>8.5.6</tomcat.version></properties>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>

3. Jetty

To change the embedded servlet container to Jetty you need to edit the pom file to remove the Tomcat dependency and add Jetty.

3.1 Change to Jetty (version 9.3.14)

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

4. Undertow

To change the embedded servlet container to Undertow you need to edit the pom file to remove the Tomcat dependency and add Undertow.

4.1 Change to Undertow (version 1.3.24 final)

Notice the undertow version included in the spring boot starter is incorrect, referring to 1.3.25. You’ll need to change it to 1.3.24.Final for this to work at the time of this article.

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>1.3.24.Final</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>1.3.24.Final</version>
</dependency>

5. Performance and Load

In this example, we will analyze both the peformance of HTTP requests and the memory footprint at startup of all three embedded servlet containers. We used JMeter to measure performance by simulating load and JVisualVM to look at the memory footprint.

5.1 Measure Performance

In this example, we will analyze both the peformance of simple RESTFul GET requests that return a string and more complex GET requests that return complex JSON objects. JMeter is the tool used to measure the performance of the the three different types of containers. The key to setting up this test was establishing thread groups with the appropriate load, a counter to dynamically update the input to the API and report viewers to display or aggregate the results. For the simple string examples, we used a thread group with 1000 threads that would loop 3 times through the sequence. It also used a ramp up time of 10 seconds. For the complex object examples, we used the same parameters but did not loop.

JMeter Tomcat Thread Group

JMeter Tomcat Summary Report

5.1.1 Tomcat

5.1.1.1 Simple String
Label # Samples Average Min Max Std. Dev. Error % Throughput Received KB/sec Sent KB/sec Avg. Bytes
Startup 3000 7 1 549 35.78374361 0 293.8583603 55.95935572 55.67238466 195
Others 3000 1 0 45 1.359661682 0 287.8802418 54.82094449 54.53981144 195
Others 3000 1 0 24 1.155032275 0 292.1129503 55.62697785 55.3417113 195
5.1.1.2 Complex Object with Dynamic Data
Label # Samples Average Min Max Std. Dev. Error % Throughput Received KB/sec Sent KB/sec Avg. Bytes
Startup 1000 114 3 1601 322.8671905 0 97.68486861 202.3335999 19.93763432 2121
Others 1000 3 2 17 1.328216473 0 97.88566954 202.7495167 19.9786181 2121
Others 1000 2 1 16 1.110529603 0 98.52216749 204.0678879 20.10852833 2121
Others 1000 2 1 21 1.344498419 0 98.53187506 204.0879951 20.11050966 2121

5.1.2 Jetty

5.1.2.1 Simple Object
Label # Samples Average Min Max Std. Dev. Error % Throughput Received KB/sec Sent KB/sec Avg. Bytes
Startup 3000 7 0 561 40.13705065 0 291.5168594 56.0828333 55.22878 197
Others 3000 1 0 21 1.058925031 0 293.5995302 56.48350338 55.6233485 197
Others 3000 1 0 21 0.926034317 0 294.3485086 56.62759395 55.7652448 197
5.1.2.2 Complex Object with Dynamic Data
Label # Samples Average Min Max Std. Dev. Error % Throughput Received KB/sec Sent KB/sec Avg. Bytes
Startup 1000 110 3 1397 278.7961107 0 98.13542689 203.3626717 19.93375859 2122
Others 1000 3 2 20 1.500210319 0 98.48335631 204.0836739 20.00443175 2122
Others 1000 3 2 45 2.729377218 0 98.29942003 203.7025091 19.96706969 2122

5.1.3 Undertow

5.1.3.1 Simple Object
Label # Samples Average Min Max Std. Dev. Error % Throughput Received KB/sec Sent KB/sec Avg. Bytes
Startup 3000 6 0 451 31.6188702 0 295.6830278 63.81440346 56.01807363 221
Others 3000 1 0 22 1.255447862 0 292.7400468 63.17924839 55.46051669 221
Others 3000 1 0 18 1.559477975 0 294.3773918 63.53262069 55.77071681 221
5.1.3.2 Complex Object with Dynamic Data
Label # Samples Average Min Max Std. Dev. Error % Throughput Received KB/sec Sent KB/sec Avg. Bytes
Startup 1000 70 3 1114 197.1333241 0 97.059109 203.3969361 19.62044201 2145.893
Startup 1000 42 3 852 132.6443576 0 98.02960494 205.6324135 20.00799554 2148
Others 1000 3 2 19 1.293570253 0 98.55129595 206.6305004 20.01823199 2147
Others 1000 2 2 27 1.659250132 0 98.74592673 207.0385788 20.05776637 2147
Others 1000 2 1 17 1.260904041 0 98.28975821 206.0821395 19.96510714 2147

5.2 Measure Memory

To measure the memory of each embedded servlet container we looked at the memory usage on startup. JVisualVM is a tool provided with the Java Development Kit for visualizing the memory and footprint of java applications. We used this tool to show the initial startup impact of each of the three embedded servlet containers. The heap size and thread counts are key in analyzing this initial footprint. The ten threads that are common to all three containers include: JMX server connection timeout, RMI Scheduler, RMI TCP Connection (2), RMI TCP Accept, Attach Listener, DestroyJavaVM, Signal Dispatcher, Finalizer and Reference Handler.

JVisualVM Report

5.2.2 Tomcat

Heap Size: 697,827,328 B
Used: 124,260,976 B
Max: 2,147,483,648 B

Threads: 17 Live, 22 Started

5.2.3 Jetty

Heap Size: 628,621,312 B
Used: 311,476,776 B
Max: 2,147,483,648 B

Threads: 19 Live, 22 Started

5.2.4 Undertow

Heap Size: 630,718,464 B
Used: 114,599,536 B
Max: 2,147,483,648 B

Threads: 17 Live, 20 Started

6. 对比

6.1 性能

压测结果:从上面的6张压力测试报告中,可以看到3个容器在相同的用例及并发请求下,Undertow稍微比Tomcat和Jetty好一点。

资源消耗:JETY启动时内存占用最大,使用311 MB。Tomcat和Undertow的初始脚印相似,在120 MB左右,Undertow出现在114 MB的最低水平。响应头中的关键差异在于默认情况下默认情况下包括HTTP持久连接。该头将在支持持久连接的客户端中使用,以通过重用连接细节来优化性能。

6.1.1 Tomcat Response Headers

Content-Type →application/json;charset=UTF-8
Date →Mon, 09 Jan 2017 02:23:26 GMT
Transfer-Encoding →chunked
X-Application-Context →JcgSpringBootContainers:# Application index.

6.1.2 Jetty Response Headers

Content-Type →application/json;charset=UTF-8
Date →Mon, 09 Jan 2017 02:29:21 GMT
Transfer-Encoding →chunked
X-Application-Context →JcgSpringBootContainers:# Application index.

6.1.3 Undertow Response Headers

Connection →keep-alive
Content-Type →application/json;charset=UTF-8
Date →Mon, 09 Jan 2017 02:20:25 GMT
Transfer-Encoding →chunked
X-Application-Context →JcgSpringBootContainers:# Application index.

7. 结论

这些数字表明Undertow在性能和内存使用方面是最好的。令人鼓舞的是,Undertow 正在接受最新的能力,并默认为持久的连接。这些数字并不表示在这个例子中使用的负载有显著的性能差异,但我想它们会缩放,如果性能是最重要的因素,则Undertow 是应用程序的正确匹配。认为一个组织可能因为熟悉它的能力而喜欢嵌入的servlet容器也是合理的。很多时候默认设置将不得不改变,因为应用程序要求包括性能、内存使用和功能。

=========================分割线=================================================================================

在Spring Boot中使用 Undertow 而不是 Tomcat

1、Maven示例:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

2、配置Undertow,application.yml示例:

server.undertow.accesslog.dir= # Undertow access log directory.
server.undertow.accesslog.enabled=false # Enable access log.
server.undertow.accesslog.pattern=common # Format pattern for access logs.
server.undertow.accesslog.prefix=access_log. # Log file name prefix.
server.undertow.accesslog.rotate=true # Enable access log rotation.
server.undertow.accesslog.suffix=log # Log file name suffix.
server.undertow.buffer-size= # Size of each buffer in bytes.
server.undertow.buffers-per-region= # Number of buffer per region.
server.undertow.direct-buffers= # Allocate buffers outside the Java heap.
server.undertow.io-threads= # Number of I/O threads to create for the worker.
server.undertow.max-http-post-size=0 # Maximum size in bytes of the HTTP post content.
server.undertow.worker-threads= # Number of worker threads.

3、使用 Undertow 监听多个端口示例:

@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() { @Override
public void customize(Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
} });
return factory;
}

Spring Boot 容器选择 Undertow 而不是 Tomcat的更多相关文章

  1. Spring Boot 容器选择 Undertow 而不是 Tomcat Spring Boot 内嵌容器Unde

    Spring Boot 内嵌容器Undertow参数设置 配置项: # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动 ...

  2. 在spring boot里使用undertow而非tomcat

    参考https://examples.javacodegeeks.com/enterprise-java/spring/tomcat-vs-jetty-vs-undertow-comparison-o ...

  3. spring boot容器启动详解

    目录 一.前言 二.容器启动 三.总结 =======正文分割线====== 一.前言 spring cloud大行其道的当下,如果不了解基本原理那么是很纠结的(看见的都是约定大于配置,但是原理呢?为 ...

  4. Jdk和Spring Boot版本选择

    ==========================版本选择的原则:==========================1. 优先选择官方指定的long-term support(LTS)版本, 非L ...

  5. Jrebel热部署配置完整教程(IntelliJ IDEA、Jrebel、spring boot、springboot、eclipse、Tomcat)

    标签:IntelliJ IDEA.Jrebel.spring boot.springboot.eclipse.Tomcat1.安装插件并激活插件安装参考:http://blog.csdn.net/u0 ...

  6. spring boot容器加载完后执行特定操作

    有时候我们需要在spring boot容器启动并加载完后,开一些线程或者一些程序来干某些事情.这时候我们需要配置ContextRefreshedEvent事件来实现我们要做的事情 1.Applicat ...

  7. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  8. 精尽Spring Boot源码分析 - 支持外部 Tomcat 容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  9. spring boot 在什么时候启动的tomcat

    我一直很好奇 spring boot 以哪种方式 启动的 tomcat  今天 特地跟踪了一下 大家都知道 spring 容器很核心的 方式 是org.springframework.context. ...

随机推荐

  1. 关于”铁大吃什么“的nabcd的分析

    Need: 为那些饥肠辘辘而又囊中羞涩的铁大同学提供最新最全的美食信息. Approach: 跑遍铁大所有角落,收集所有关于美食的信息,主要是价格口味方面,口味方面会通过学生的打分来数量化,建立一个库 ...

  2. JSM的topic和queue的区别

    在JMS(Java消息服务)中,Topic实现publish和subscribe语义.一条消息被publish时,它将发到所有感兴趣的订阅者,所以零到多个 subscriber(电脑词汇中解释为“用户 ...

  3. 20165313 预备作业3 Linux安装及学习

    虚拟机安装 刚开始我觉得既然有了教程,安装虚拟机应该是很简单的事情,然而由于电脑本身系统地地问题,导致我数次安装失败,后来咨询了老师并查阅了资料,最终才安装好. 其中最主要的问题就是电脑虚拟化的修改. ...

  4. Hibernate(二)

    性能分析 抓取策略 研究对象 研究怎么样提取集合的,该策略应该作用与set元素上 研究从一的一方加载多的一方 案例 查询cid为1的班级的所有的学生 明:通过一条sql语句:左外链接,把classes ...

  5. 分享一篇 Git Web 开发流程

    分享一篇 Git Web 开发流程 web 项目如何进行 git 多人协作开发 https://segmentfault.com/a/1190000018165757

  6. 做 Excel 的 XML schema.xsd

    做 Excel 的 XML schema.xsd 因为需要将 BOM Cost 归档并使用 Git 管理,原来 XLSX 是二进制的,使用 Git 管理并不方便. 于是有了想用 XML 来管理想法,在 ...

  7. [转]logback常用配置简介

    logback是一套日志框架,由log4j的优化版,由同一个作者开发,在速度和性能上都超过其他日志框架,再结合slf4j,已成为当前最流行的日志框架. Logback最常用就是在classpath定义 ...

  8. maven默认本地仓库

    本地仓库是远程仓库的一个缓冲和子集,当你构建Maven项目的时候,首先会从本地仓库查找资源,如果没有,那么Maven会从远程仓库下载到你本地仓库.这样在你下次使用的时候就不需要从远程下载了.如果你所需 ...

  9. jmeter ---断言持续时间(Duration to Assert )和断言文件大小

    jmeter ---断言持续时间(Duration to Assert )和断言文件大小 1.断言持续时间(Duration to Assert ) Duration to Assert -- 允许的 ...

  10. Jmeter之函数助手

    本文转载自:心的开始  Emily0120 JMeter函数是一些能够转化在测试树中取样器或者其他配置元件的域的特殊值.一个函数的调用就像这样:${_functionName(var1,var2,va ...