ToB企服应用市场:ToB评测及商务社交产业平台

标题: Spring(21) 在 Spring Boot 中利用 Undertow 作为嵌入式服务器 [打印本页]

作者: 魏晓东    时间: 2024-7-13 06:49
标题: Spring(21) 在 Spring Boot 中利用 Undertow 作为嵌入式服务器
一、四种 Web 服务器


通过 org.springframework.boot.autoconfigure.web.ServerProperties 查看,可以看到这里包罗了 Tomcat、Jetty、Netty、Undertow 四种服务器的设置,默认启用 Tomcat。
1.1 Tomcat 服务器

Tomcat: 是 Spring Boot 默认采取的 Web 服务器,通过 spring-boot-starter-web 依赖自动引入。
优点:

缺点:

1.2 Jetty 服务器

Jetty: 一个快速、高性能且轻量级的 Servlet 容器和 HTTP 服务器。若要利用 Jetty 替换 Tomcat,只需在项目中清除 Tomcat 并引入 Jetty 的起步依赖 spring-boot-starter-jetty。
优点:

缺点:

1.3 Undertow 服务器

Undertow: 由 Red Hat 提供的一个机动、高性能的 Web 服务器,可通过添加 spring-boot-starter-undertow 依赖来启用 Undertow 作为应用的内嵌服务器。
优点:

缺点:

1.4 Netty(相应式场景)

Netty: 虽然 Netty 不是传统的基于 Servlet 的 Web 容器,但在 Spring Boot 中可以用于构建相应式的 Web 应用,尤其是通过 Reactive Stack(如 WebFlux)时,会利用 Netty 作为底层网络通讯层。要利用 Netty,通常引入的是 spring-boot-starter-webflux 依赖。
优点:

缺点:

总的来说,各人可以根据以上优缺点来举行权衡,选择最得当项目的服务器。这里我们主要对 Undertow 服务器举行详细说明。

二、Undertow 介绍

Undertow 是一个轻量级的、高性能的 Java Web 服务器,由 JBoss 公司(Red Hat 旗下)开发并开源的。它是基于非壅闭(non-blocking)的 I/O 模型,具有低资源斲丧和高并发处置惩罚本领。
Undertow 的上风如下:
在许多场景的测试下,Undertow 的性能测试都高于 Tomcat。天生得看成为 Spring Boot 应用的嵌入式服务器。

三、SpringBoot 中利用 Undertow

如上所述,Spring Boot 默认利用 Tomcat 作为嵌入式服务。所以 spring-boot-starter-web 默认依赖了 spring-boot-starter-tomcat。
要利用 Undertow 替换 Tomcat,首先要从 spring-boot-starter-web 中清除 Tomcat,再添加 spring-boot-starter-undertow 依赖:
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-web</artifactId>
  4.     <exclusions>
  5.         <exclusion>
  6.             <groupId>org.springframework.boot</groupId>
  7.             <artifactId>spring-boot-starter-tomcat</artifactId>
  8.         </exclusion>
  9.     </exclusions>
  10. </dependency>
  11. <dependency>
  12.         <groupId>org.springframework.boot</groupId>
  13.         <artifactId>spring-boot-starter-undertow</artifactId>
  14. </dependency>
复制代码
仅此即可。启动应用,查看日志如下:
  1. 2024-01-24 22:14:03.204  INFO 41412 --- [           main] io.undertow                              : starting server: Undertow - 2.0.33.Final
  2. 2024-01-24 22:14:03.211  INFO 41412 --- [           main] org.xnio                                 : XNIO version 3.3.8.Final
  3. 2024-01-24 22:14:03.221  INFO 41412 --- [           main] org.xnio.nio                             : XNIO NIO Implementation Version 3.3.8.Final
  4. 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 ''
  5. 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 作为嵌入式服务器。

四、设置属性

4.1 设置文件

Spring Boot 预制了许多属性,可用于在 application.properties | yaml 中对 Undertow 服务器举行个性化设置。
它们都以 server.undertow.* 开头,总结如下:
设置项说明示例server.undertow.accesslog.dirUndertow 访问日志没目录。server.undertow.accesslog.enabled是否启用访问日志。falseserver.undertow.accesslog.pattern访问日志的格式。commonserver.undertow.accesslog.prefix日志文件前缀。access_logserver.undertow.accesslog.rotate是否开启日志滚动。trueserver.undertow.accesslog.suffix日志文件后缀logserver.undertow.always-set-keep-alive是否应在全部相应中添加 Connection:keep-alive Header,即使 HTTP 规范没有要求。trueserver.undertow.buffer-size每个 buffer 的大小。默认大小是根据 JVM 可用的最大内存确定的。server.undertow.decode-slash是否应解码已编码的斜线字符(%2F)。如果前端署理不执行相同的解码,解码大概会导致安全题目。只有在传统应用程序须要时才启用。设置后,server.undertow.allow-encoded-slash 无效。server.undertow.decode-url是否对 URL 举行编码。禁用时,URL 中的百分比编码字符将保持原样。trueserver.undertow.direct-buffers是否在 Java 堆外分配 buffer。默认大小是根据 JVM 可用的最大内存确定的。server.undertow.eager-filter-init是否应在启动时初始化 servlet Filtertrueserver.undertow.max-cookies允许的最大 cookie 数目。这一限制是为了防止基于哈希碰撞的 DOS 攻击。200server.undertow.max-headers允许的最大 header 数目。这一限制是为了防止基于哈希碰撞的 DOS 攻击。server.undertow.max-http-post-sizeHTTP post content 的最大大小。当值为 -1(默认值)时,大小为无穷。-1Bserver.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转发请求时是否保留请求路径。falseserver.undertow.threads.ioI/O 线程数。默认值为可用的处置惩罚器数目。server.undertow.threads.workerWorker 线程数。默认为 I/O 线程数的 8 倍。server.undertow.url-charset用于解码 URL 的字符集。UTF-8 4.2 编程式设置

如果设置属性无法满足你的需求,你可以通过设置类,以编程式的方式举行定制。
实现 WebServerFactoryCustomizer<UndertowServletWebServerFactory 接口,重写 customize() 方法:
  1. import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
  2. import org.springframework.boot.web.server.WebServerFactoryCustomizer;
  3. import org.springframework.context.annotation.Configuration;
  4. @Configuration
  5. public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>{
  6.     @Override
  7.     public void customize(UndertowServletWebServerFactory factory) {
  8.         factory.setBufferSize(8192);
  9.         // 其他自定义配置 ...
  10.     }
  11. }
复制代码
对于 UndertowServletWebServerFactory 设置类的细节,请参阅:


五、增补

5.1 启动时的警告日志

当我们利用 Undertow 作为 Spring Boot 的嵌入式服务器时,启动应用后会看到有一条 WARN 日志,如下所示:
  1. 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 依赖即可。
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-undertow</artifactId>
  4.     <exclusions>
  5.         <!-- 排除 undertow-websockets-jsr 依赖 -->
  6.         <exclusion>
  7.             <groupId>io.undertow</groupId>
  8.             <artifactId>undertow-websockets-jsr</artifactId>
  9.         </exclusion>
  10.     </exclusions>
  11. </dependency>
复制代码
方式二:为 WebSocketDeploymentInfo 设置合理的参数
也可以通过上述的 “编程式” 设置方式,为 WebSocketDeploymentInfo 设置一个合理的参数,如下所示:
  1. import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
  2. import org.springframework.boot.web.server.WebServerFactoryCustomizer;
  3. import org.springframework.context.annotation.Configuration;
  4. import io.undertow.server.DefaultByteBufferPool;
  5. import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
  6. @Configuration
  7. public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>{
  8.     @Override
  9.     public void customize(UndertowServletWebServerFactory factory) {
  10.         factory.addDeploymentInfoCustomizers(deploymentInfo -> {
  11.             
  12.             WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
  13.             
  14.             // 设置合理的参数
  15.             webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 8192));
  16.             
  17.             deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
  18.         });
  19.     }
  20. }
复制代码
经测试,以上 2 种方式都可以办理 Undertow 启动时有警告日志的题目。
整理完毕,完结撒花~




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4