SpringBoot 内置 Server 详解

2023年 8月 1日 38.3k 0

引言

基于Spring Boot的web应用中,在spring-boot包内包含了内置的 web server,具体包括 tomcatjettyundertownetty

本文旨在厘清 spring boot 中内置 server 的原理和使用。

Spring Boot Server 源码剖析

首先我们跟踪一下 org.springframework.boot:spring-boot 包中 org.springframework.boot.web package下的代码,代码可以看 Github spring-boot 源码

package下的目录结构如下:

  • embedded:主要是存放内置的web server,包含WebServer和WebServerFactory等实现,同时用到对应 server 的package
  • reactive:基于 reactive 的spring boot 应用,依赖spring-boot-starter-webflux
  • servlet:基于servlet的 spring boot 应用,依赖spring-boot-starter-web
  • server:servlet 和 reactive 中通用的 server 相关的类和接口

Untitled.png

Servlet 和 Reactive

Spring Framework 5.0 提供了两种web框架,分别是 servletreactive ,他们具体的不同如下

  • servlet 是Spring Web中引入,基于servlet API实现,即Spring MVC;

    reactive 是通过Spring Webflux引入,实现了Reactive Streams 规范的响应式

  • servlet 实现的是阻塞IO (blocking I/O)

    reactive 实现的是 Event-Loop,非阻塞IO(non-blocking I/O),即异步处理

  • 针对servlet 框架,SpringBoot提供了三种内置Server,分别是Jetty、Tomcat 和 Undertow

    针对reactive 框架,SpringBoot提供了四种内置Server,分别是Jetty、Tomcat、Undertow 和 Netty

Untitled 1.png

WebServer

这部分我们介绍一下 WebServer 接口与实现,WebServer提供的5个方法如下:

  • start:启动服务
  • stop:停止服务
  • getPort:提供端口号
  • shutDownGracefully: 优雅地关闭服务,在尝试结束服务的时候调用,处理一些被阻止的请求
  • destroy:销毁服务使其无法再次启动,默认调用stop方法

然后我们来看看 WebServer 的实现,实现主要是spring-boot中内置的几个Server,具体有:

  • JettyWebServer:基于Jetty的WebServer实现,依赖于 org.eclipse.jetty
  • NettyWebServer:基于Netty的WebServer实现,依赖于 io.projectreactorio.netty
  • TomcatWebServer:基于Tomcat的WebServer实现,依赖于 org.apache.tomcat
  • UndertowWebServer:基于Undertow的WebServer实现,依赖于 io.undertow

目前我们知道了SpringBoot中内置的WebServer提供了这些实现,那么在服务启动时,默认使用的是哪个 Server 呢?

  • 启用 servlet 框架的情况下,默认使用的是 TomcatWebServer,因为spring-boot-starter-web 中默认依赖了spring-boot-starter-tomcat
  • 启用 reactive 框架的情况下,默认使用的是 NettyWebServer,因为spring-boot-starter-webflux 中默认依赖了 spring-boot-starter-reactor-netty

Untitled 2.png

WebServerFactory

SpringBoot中提供了WebServerFactory的工厂接口类,用来封装WebServer的创建

WebServerFactory也分为了两种即 ServletWebServerFactory 和 ReactiveWebServerFactory,两者都提供了getWebServer 方法来创建WebServer,但具体有所不同

  • ServletWebServerFactory 提供的getWebServer 方法传入的参数是org.springframework.boot.web.servlet.ServletContextInitializer,用于配置Servlet 3.0+的接口。

    ServletContextInitializer中提供了onStartup(ServletContext servletContext) 方法

    其中jakarta.servlet.ServletContext用于连接对应的servlet容器

  • ReactiveWebServerFactory 提供的getWebServer 方法传入的参数是org.springframework.http.server.reactive.HttpHandler

    HttpHandler中提供了handle(ServerHttpRequest request, ServerHttpResponse response)方法

    其中 org.springframework.http.server.reactive.ServerHttpRequestorg.springframework.http.server.reactive.ServerHttpResponse 对应的则是基于reactive server的 request 和 response

Server Servlet stack Reactive stack
Tomcat TomcatServletWebServerFactory TomcatReactiveWebServerFactory
Jetty JettyServletWebServerFactory JettyReactiveWebServerFactory
Undertow UndertowServletWebServerFactory UndertowReactiveWebServerFactory
Reactor N/A NettyReactiveWebServerFactory

WebServerFactory具体的接口和实现类如下图:

Untitled 3.png

Server 的 Bean 管理

上面我们梳理了 WebServer 和 用于管理的工厂类 WebServerFactory,下面我们来剖析SpringBoot中是如何通过Factory管理Server Bean的。

创建了对应的ServletWebServerApplicationContextReactiveWebServerApplicationContext ,并在这两个类实现了 onRefresh() 方法,此方法用于在特定context子类中初始化特殊的bean,这里所指的特定context子类包含ServletWebServerApplicationContext、ReactiveWebServerApplicationContext 和 StaticWebApplicationContext,具体如下:

  • ServletWebServerApplicationContext 中,onRefresh() 方法中获取 ServletWebServerFactory Bean 创建 WebServer
  • ReactiveWebServerApplicationContext 中,onRefresh() 方法中获取ReactiveWebServerFactory Bean,并创建WebServerManager,在 WebServerManager 的构造方法中创建了 WebServer
  • StaticWebApplicationContext中,onRefresh() 方法用于创建 ThemeSource 的静态主题

Untitled 4.png

内置 Server 简述:Jetty/Netty/Tomcat/Undertow

这里不会展开介绍这4种Server的实现和区别,只是稍微简述一下实现和不同点。

Tomcat

Tomcat目前收录与 Apache 项目中,官方链接是 tomcat.apache.org/

Tomcat是主流的Java Web Server,所以是十分稳定和成熟的,同时社区活跃文档和资源丰富。

Tomcat可以支持Http, Http/2 , AJP, WebSocket 协议,支持Servlet 6.0

Jetty

Jetty是 Eclipse 提供的一款Server,官方链接是 eclipse.dev/jetty/docum…

相比Tomcat它更加轻量级,有自己的异步支持。

Jetty可以支持Http, Http/2 ,Http/3, AJP, WebSocket 协议,支持Servlet 6.0

Netty

Netty是一个基于时间驱动的异步网络框架,被广泛应用于高性能的网络应用程序,尤其是处理大量并发连接的服务端应用,官方链接是 netty.io/index.html。

Netty几乎支持了大部分的协议,有 SSL/TLS, HTTP, HTTP/2, HTTP/3, WebSockets, DNS, SPDY , SMTP

Undertow

Undertow是 JBoos 提供的一款Server,官方地址是undertow.io/

Undertow的特点在于轻量级、高性能和地资源消耗,同时支持嵌入式应用程序和微服务。

Undertow可以支持Http, Http/2 , WebSocket 协议,支持Servlet 4.0

Server对比

这里贴一下基于Tomcat/Jetty/Undertow的Server运行情况,主要监控了 内存使用、类加载、线程数、每秒请求书 和 每个请求的平均处理时长。

我们可以得知,内存占用和类加载方面,Jetty更加轻量;处理请求数和响应时间方面,Undertow速度更快。

Metric Tomcat Jetty Undertow
jvm.memory.used (MB) 168 155 164
jvm.classes.loaded 9869 9784 9787
jvm.threads.live 25 17 19
Requests per second 1542 1627 1650
Average time per request (ms) 6.483 6.148 6.059

如何在 Spring-Boot 中配置其他 Server

最后一部分我们介绍一下如何在 SpringBoot 中使用非默认的 Server

使用 Jetty Server

在 Servlet 框架下使用 Jetty


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


    org.springframework.boot
    spring-boot-starter-jetty

在 Reactive 框架下使用 Jetty:


    org.springframework.boot
    spring-boot-starter-webflux
    
        
            org.springframework.boot
            spring-boot-starter-reactor-netty
        
    


    org.springframework.boot
    spring-boot-starter-jetty

使用 Undertow Server

在 Servlet 框架下使用 Undertow:


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


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

在 Reactive 框架下使用 Undertow:


    org.springframework.boot
    spring-boot-starter-webflux
    
        
            org.springframework.boot
            spring-boot-starter-reactor-netty
        
    


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

在 Reactive 框架下使用 Tomcat


    org.springframework.boot
    spring-boot-starter-webflux
    
        
            org.springframework.boot
            spring-boot-starter-reactor-netty
        
    


    org.springframework.boot
    spring-boot-starter-tomcat

在 Reactive 框架下支持Netty, 且兼容 Servlet

如果原有是基于SpringMVC的项目,想使用Netty Server,需要依赖SpringWebflux

值得注意的是 SpringWebflux 也是支持@Controller、@RestController 等传统SpringMVC注解的,具体实现的类是AnnotationConfigReactiveWebServerApplicationContext ,它是ReactiveWebServerApplicationContext 的子类。


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


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

参考

“How-to” Guides

Spring 5的Servlet和反应式技术栈解析_Java_Rossen Stoyanchev_InfoQ精选文章

Comparing Embedded Servlet Containers in Spring Boot | Baeldung

Tomcat vs. Jetty vs. Undertow: Comparison of Spring Boot Embedded Servlet Containers - Examples Java Code Geeks - 2023

SpringBoot 2 performance — servlet stack vs WebFlux reactive stack

Spring MVC Async vs Spring WebFlux | Baeldung

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论