赞
踩
通过 org.springframework.boot.autoconfigure.web.ServerProperties
查看,可以看到这里包括了 Tomcat
、Jetty
、Netty
、Undertow
四种服务器的设置,默认启用 Tomcat。
Tomcat
: 是 Spring Boot 默认采用的 Web 服务器,通过 spring-boot-starter-web
依赖自动引入。
优点:
缺点:
Jetty
和 Undertow
,Tomcat 的性能可能稍逊一筹,尤其是在内存占用和线程模型方面。Undertow
,Tomcat的架构设计可能不够灵活,例如在处理大量短链接时,资源回收效率可能会收到影响。Jetty
: 一个快速、高性能且轻量级的 Servlet 容器和 HTTP 服务器。若要使用 Jetty 替换 Tomcat,只需在项目中排除 Tomcat 并引入 Jetty 的起步依赖 spring-boot-starter-jetty
。
优点:
Tomcat
。缺点:
Tomcat
较小,社区活跃度和第三方插件支持略少一些。Undertow
: 由 Red Hat 提供的一个灵活、高性能的 Web 服务器,可通过添加 spring-boot-starter-undertow
依赖来启用 Undertow 作为应用的内嵌服务器。
优点:
缺点:
Tomcat
和 Jetty
的知名度和使用率可能较低,这意味着相关的教程和实践经验可能不如前者丰富。Netty
: 虽然 Netty 不是传统的基于 Servlet 的 Web 容器,但在 Spring Boot 中可以用于构建响应式的 Web 应用,尤其是通过 Reactive Stack(如 WebFlux)时,会使用 Netty 作为底层网络通信层。要使用 Netty,通常引入的是 spring-boot-starter-webflux
依赖。
优点:
缺点:
总的来说,大家可以根据以上优缺点来进行衡量,选择最适合项目的服务器。这里我们主要对 Undertow 服务器进行详细说明。
Undertow
是一个轻量级的、高性能的 Java Web 服务器,由 JBoss 公司(Red Hat 旗下)开发并开源的。它是基于非阻塞(non-blocking)的 I/O 模型,具有低资源消耗和高并发处理能力。
Undertow 的优势如下:
在很多场景的测试下,Undertow 的性能测试都高于 Tomcat。天生适合作为 Spring Boot 应用的嵌入式服务器。
如上所述,Spring Boot 默认使用 Tomcat 作为嵌入式服务。所以 spring-boot-starter-web
默认依赖了 spring-boot-starter-tomcat
。
要使用 Undertow 替换 Tomcat,首先要从 spring-boot-starter-web 中排除 Tomcat,再添加 spring-boot-starter-undertow
依赖:
<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>
仅此即可。启动应用,查看日志如下:
2024-01-24 22:14:03.204 INFO 41412 --- [ main] io.undertow : starting server: Undertow - 2.0.33.Final
2024-01-24 22:14:03.211 INFO 41412 --- [ main] org.xnio : XNIO version 3.3.8.Final
2024-01-24 22:14:03.221 INFO 41412 --- [ main] org.xnio.nio : XNIO NIO Implementation Version 3.3.8.Final
2024-01-24 22:14:04.029 INFO 41412 --- [ main] o.s.b.w.e.u.UndertowServletWebServer : Undertow started on port(s) 8080 (http) with context path ''
2024-01-24 22:14:04.035 INFO 41412 --- [ main] com.demo.SpringbootDemoApplication : Started SpringbootDemoApplication in 3.337 seconds (JVM running for 5.652)
如你所见,Spring Boot 已经使用 Undertow 作为嵌入式服务器。
Spring Boot 预制了很多属性,可用于在 application.properties | yaml
中对 Undertow 服务器进行个性化配置。
它们都以 server.undertow.*
开头,总结如下:
配置项 | 说明 | 示例 |
---|---|---|
server.undertow.accesslog.dir | Undertow 访问日志没目录。 | |
server.undertow.accesslog.enabled | 是否启用访问日志。 | false |
server.undertow.accesslog.pattern | 访问日志的格式。 | common |
server.undertow.accesslog.prefix | 日志文件前缀。 | access_log |
server.undertow.accesslog.rotate | 是否开启日志滚动。 | true |
server.undertow.accesslog.suffix | 日志文件后缀 | log |
server.undertow.always-set-keep-alive | 是否应在所有响应中添加 Connection:keep-alive Header,即使 HTTP 规范没有要求。 | true |
server.undertow.buffer-size | 每个 buffer 的大小。默认大小是根据 JVM 可用的最大内存确定的。 | |
server.undertow.decode-slash | 是否应解码已编码的斜线字符(%2F )。如果前端代理不执行相同的解码,解码可能会导致安全问题。只有在传统应用程序需要时才启用。设置后,server.undertow.allow-encoded-slash 无效。 | |
server.undertow.decode-url | 是否对 URL 进行编码。禁用时,URL 中的百分比编码字符将保持原样。 | true |
server.undertow.direct-buffers | 是否在 Java 堆外分配 buffer。默认大小是根据 JVM 可用的最大内存确定的。 | |
server.undertow.eager-filter-init | 是否应在启动时初始化 servlet Filter | true |
server.undertow.max-cookies | 允许的最大 cookie 数量。这一限制是为了防止基于哈希碰撞的 DOS 攻击。 | 200 |
server.undertow.max-headers | 允许的最大 header 数量。这一限制是为了防止基于哈希碰撞的 DOS 攻击。 | |
server.undertow.max-http-post-size | HTTP post content 的最大大小。当值为 -1(默认值)时,大小为无限。 | -1B |
server.undertow.max-parameters | 允许查询或路径参数的最大数量。这一限制是为了防止基于哈希碰撞的 DOS 攻击。 | |
server.undertow.no-request-timeout | 在服务器关闭连接之前,连接在不处理请求的情况下闲置的时间。 | |
server.undertow.options.server.* | 在 io.undertow.UndertowOptions 中定义的服务器选项。 | |
server.undertow.options.socket.* | 在 org.xnio.Options 中定义的 socket 选项。 | |
server.undertow.preserve-path-on-forward | 转发请求时是否保留请求路径。 | false |
server.undertow.threads.io | I/O 线程数。默认值为可用的处理器数量。 | |
server.undertow.threads.worker | Worker 线程数。默认为 I/O 线程数的 8 倍。 | |
server.undertow.url-charset | 用于解码 URL 的字符集。 | UTF-8 |
如果配置属性无法满足你的需求,你可以通过配置类,以编程式的方式进行定制。
实现 WebServerFactoryCustomizer<UndertowServletWebServerFactory
接口,重写 customize()
方法:
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>{
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.setBufferSize(8192);
// 其他自定义配置 ...
}
}
对于 UndertowServletWebServerFactory
配置类的细节,请参阅:
当我们使用 Undertow 作为 Spring Boot 的嵌入式服务器时,启动应用后会看到有一条 WARN
日志,如下所示:
WARN 9608 --- [ main] io.undertow.websockets.jsr : UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used
大致意思是:“没有给 WebSocketDeploymentInfo 设置 Buffer pool,将会使用默认值”。
有两种方式可以解决这个问题:
方式一:排除 undertow-websockets-jsr 依赖
如果未使用到 WebSocket 技术,那么可以直接从 spring-boot-starter-undertow
中排除 undertow-websockets-jsr
依赖即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<exclusions>
<!-- 排除 undertow-websockets-jsr 依赖 -->
<exclusion>
<groupId>io.undertow</groupId>
<artifactId>undertow-websockets-jsr</artifactId>
</exclusion>
</exclusions>
</dependency>
方式二:为 WebSocketDeploymentInfo 设置合理的参数
也可以通过上述的 “编程式” 配置方式,为 WebSocketDeploymentInfo
设置一个合理的参数,如下所示:
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Configuration; import io.undertow.server.DefaultByteBufferPool; import io.undertow.websockets.jsr.WebSocketDeploymentInfo; @Configuration public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>{ @Override public void customize(UndertowServletWebServerFactory factory) { factory.addDeploymentInfoCustomizers(deploymentInfo -> { WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo(); // 设置合理的参数 webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 8192)); deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo); }); } }
经测试,以上 2 种方式都可以解决 Undertow 启动时有警告日志的问题。
整理完毕,完结撒花~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。