SpringBoot WebServer启动与监听器原理深度解析
·
SpringBoot WebServer启动与监听器原理深度解析
目录
- 引言
- WebServerFactory接口体系
- WebServer初始化完整时序
- Tomcat核心组件架构
- Undertow与Jetty架构对比
- WebServerManager生命周期管理
- WebServerInitializedEvent事件机制
- 端口配置与多服务器
- SSL/TLS与HTTP2配置
- Tomcat线程模型与优化
- 健康检查与优雅关闭
- 自定义WebServerFactoryCustomizer
- 实战:动态调整服务器配置
- 总结
引言
Spring Boot的嵌入式Web服务器是其最核心的特性之一。从Tomcat到Undertow、Jetty,Spring Boot通过抽象的工厂接口体系,让开发者可以无缝切换不同的Web服务器实现。
本文将从源码层面深入剖析WebServer的启动流程、组件架构、事件机制,以及如何在生产环境中进行深度定制和优化。
1. WebServerFactory接口体系
1.1 接口层次结构
1.2 WebServer接口定义
1.3 自动配置机制
1.4 WebServerFactoryCustomizer接口
public interface WebServerFactoryCustomizer<T extends WebServerFactory> {
/**
* 自定义WebServerFactory配置
*/
void customize(T factory);
}
TomcatWebServerFactoryCustomizer源码:
class TomcatWebServerFactoryCustomizer implements
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
private final Environment environment;
@Override
public void customize(TomcatServletWebServerFactory factory) {
// 1. 配置端口
ServerProperties.Tomcat properties = getServerProperties();
if (!getPort().isPresent()) {
factory.setPort(getPortValue(properties.getPort()));
}
// 2. 配置SSL
if (properties.getSsl() != null && properties.getSsl().isEnabled()) {
factory.setSsl(properties.getSsl());
}
// 3. 配置压缩
if (properties.getCompression() != null) {
factory.setCompression(properties.getCompression());
}
// 4. 配置连接器
factory.addConnectorCustomizers(
new TomcatConnectorCustomizer(properties)
);
// 5. 配置访问日志
if (properties.getAccesslog().isEnabled()) {
factory.addContextValves(createAccessLogValve(properties));
}
}
}
2. WebServer初始化完整时序
2.1 Spring Boot启动链路
2.2 WebServerManager核心逻辑
2.3 ServletWebServerApplicationContext刷新流程
// ServletWebServerApplicationContext.java
@Override
protected void onRefresh() {
super.onRefresh();
// 1. 创建WebServer
createWebServer();
// 2. 初始化Servlet上下文
initServletContext();
}
private void createWebServer() {
// 1. 如果WebServer已存在,先停止
if (this.webServer != null) {
this.webServer.stop();
}
// 2. 获取WebServerFactory
WebServerFactory factory = getWebServerFactory();
// 3. 获取ServletContextInitializer
ServletContextInitializer initializers = getServletContextInitializers();
// 4. 创建WebServer
this.webServer = factory.getWebServer(initializers);
// 5. 注册到ServletContext
this.webServer.getServletContext();
}
2.4 getWebServerFactory获取逻辑
private WebServerFactory getWebServerFactory() {
// 1. 获取所有WebServerFactory类型的Bean
List<WebServerFactory> factories =
getBeanFactory().getBeansOfType(WebServerFactory.class).values()
.stream()
.sorted(annotationAwareComparator)
.collect(Collectors.toList());
// 2. 断言至少存在一个
Assert.state(!factories.isEmpty(),
"No WebServerFactory customizer has been defined. " +
"Requires a class of type WebServerFactory.");
// 3. 返回第一个(非延迟)
return factories.get(0);
}
3. Tomcat核心组件架构
3.1 Tomcat组件层次结构
3.2 Tomcat启动初始化流程
3.3 连接器初始化详解
3.4 NioEndpoint线程模型
3.5 三种服务器对比
| 特性 | Tomcat | Undertow | Jetty |
|---|---|---|---|
| 默认端口 | 8080 | 8080 | 8080 |
| 线程模型 | BIO/NIO | XNIO(NIO) | NIO |
| 内存占用 | 较高 | 较低 | 较低 |
| 并发性能 | 一般 | 优秀 | 优秀 |
| WebSocket | 支持 | 支持 | 支持 |
| 懒加载 | 不支持 | 支持 | 支持 |
| 启动速度 | 较慢 | 快 | 快 |
| HTTP/2 | 需配置 | 原生支持 | 原生支持 |
| 最小依赖 | ~1.5MB | ~1MB | ~1MB |
4. Undertow与Jetty架构对比
4.1 Undertow架构
4.2 Jetty架构
4.3 启动流程对比
5. WebServerManager生命周期管理
5.1 WebServerManager状态机
5.2 WebServerManager源码
class WebServerManager {
private final WebServerFactory webServerFactory;
private volatile WebServer webServer;
private final List<ServletContextInitializer> initializers;
// 容器刷新时调用
void onRefresh() {
// 1. 收集所有ServletContextInitializer
this.initializers = getServletContextInitializers();
// 2. 创建WebServer(不启动)
this.webServer = this.webServerFactory.getWebServer(this.initializers);
}
// 容器刷新完成时调用
void start() throws WebServerException {
if (this.webServer != null) {
synchronized (this.monitor) {
if (this.webServer != null) {
this.webServer.start();
}
}
}
}
// 容器关闭时调用
void stop() throws WebServerException {
if (this.webServer != null) {
synchronized (this.monitor) {
if (this.webServer != null) {
this.webServer.stop();
}
}
}
}
}
5.3 WebServerFactoryCustomizerBeanPostProcessor
6. WebServerInitializedEvent事件机制
6.1 事件发布时机
6.2 事件体系结构
6.3 事件监听器使用模式
// 模式1:通用监听器
@Component
public class GenericServerListener
implements ApplicationListener<WebServerInitializedEvent> {
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
WebServer webServer = event.getWebServer();
// 通用的服务器信息获取
System.out.println("Server started on port: " + webServer.getPort());
}
}
// 模式2:类型特定监听器
@Component
public class TomcatSpecificListener
implements ApplicationListener<TomcatWebServerInitializedEvent> {
@Override
public void onApplicationEvent(TomcatWebServerInitializedEvent event) {
Tomcat tomcat = event.getTomcat();
// 获取Tomcat特定信息
MBeanRegistry.getMBeanServer();
}
}
// 模式3:使用@EventListener
@Component
public class EventListenerExample {
@EventListener
public void onServerStart(WebServerInitializedEvent event) {
// Spring 5.x+ 推荐方式
}
}
6.4 与Spring Boot 1.x的差异
7. 端口配置与多服务器
7.1 端口配置决策流程
7.2 多端口配置
@Configuration
public class MultiPortConfiguration
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
// 主连接器已在factory中配置
// 添加额外的连接器(管理端口)
Connector adminConnector = new Connector();
adminConnector.setPort(8443);
adminConnector.setProtocol("HTTP/1.1");
adminConnector.setSecure(true);
adminConnector.setScheme("https");
factory.addAdditionalTomcatConnectors(adminConnector);
}
}
7.3 Unix Socket配置
# application.properties
server.tomcat.basedir=/tmp/tomcat
server.tomcat.unix-socket=/tmp/tomcat/app.sock
7.4 禁用服务器
8. SSL/TLS与HTTP2配置
8.1 SSL配置体系
8.2 SSL/TLS完整配置流程
8.3 双向SSL配置
@Configuration
public class MutualSslConfig {
@Bean
public ConfigurableServletWebServerFactory servletWebServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Ssl ssl = new Ssl();
ssl.setEnabled(true);
ssl.setKeyStore("keystore.p12");
ssl.setKeyStorePassword("changeit");
ssl.setKeyStoreType("PKCS12");
ssl.setTrustStore("truststore.p12");
ssl.setTrustStorePassword("changeit");
ssl.setClientAuth(ClientAuth.WANT); // WANT/NEED/NONE
factory.setSsl(ssl);
return factory;
}
}
8.4 HTTP/2配置
# application.properties
server.ssl.enabled=true
server.ssl.enabled-protocols=TLSv1.2,TLSv1.3
server.http2.enabled=true
9. Tomcat线程模型与优化
9.1 Tomcat线程池架构
9.2 请求处理流程
9.3 优化参数配置
# 连接器优化
server.tomcat.max-connections=10000
server.tomcat.accept-count=200
server.tomcat.connection-timeout=20000
server.tomcat.max-http-header-size=65536
# 线程池优化
server.tomcat.threads.max=300
server.tomcat.threads.min-spare=20
# 性能优化
server.tomcat.max-keep-alive-requests=100
server.tomcat.keep-alive-timeout=60000
server.compression.enabled=true
server.compression.mime-types=text/html,text/xml,text/plain,text/css,application/javascript
10. 健康检查与优雅关闭
10.1 健康检查体系
10.2 自定义健康检查
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
try {
// 执行健康检查
boolean healthy = checkSomething();
if (healthy) {
return Health.up()
.withDetail("timestamp", System.currentTimeMillis())
.build();
} else {
return Health.down()
.withDetail("error", "检查失败原因")
.build();
}
} catch (Exception e) {
return Health.down()
.withException(e)
.build();
}
}
private boolean checkSomething() {
// 实际检查逻辑
return true;
}
}
10.3 优雅关闭流程
10.4 优雅关闭配置
# 优雅关闭配置
server.shutdown=graceful
# 等待时间
server.tomcat.shutdown.timeout=30s
# 等待存量请求完成
server.tomcat.connection-timeout=10s
11. 自定义WebServerFactoryCustomizer
11.1 Customizer执行时机
11.2 完整Customizer示例
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class PerformanceCustomizer
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Value("${app.thread-pool.max:200}")
private int maxThreads;
@Value("${app.thread-pool.min:10}")
private int minThreads;
@Override
public void customize(TomcatServletWebServerFactory factory) {
// 1. 添加访问日志Valve
factory.addContextValves(createAccessLogValve());
// 2. 自定义线程池
factory.addConnectorCustomizers(connector -> {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof Http11NioProtocol) {
NioEndpoint endpoint = ((Http11NioProtocol) handler).getEndpoint();
endpoint.setMaxThreads(maxThreads);
endpoint.setMinSpareThreads(minThreads);
}
});
// 3. 添加额外连接器
factory.addAdditionalTomcatConnectors(createManagementConnector());
}
private AccessLogValve createAccessLogValve() {
AccessLogValve valve = new AccessLogValve();
valve.setDirectory("/var/logs");
valve.setPrefix("access");
valve.setSuffix(".log");
valve.setPattern("%h %l %u %t %r %s %b %D");
return valve;
}
private Connector createManagementConnector() {
Connector connector = new Connector();
connector.setPort(8443);
connector.setSecure(true);
connector.setScheme("https");
return connector;
}
}
12. 实战:动态调整服务器配置
12.1 通过Actuator动态获取端口
# 添加Actuator依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# 暴露端点
management.endpoints.web.exposure.include=serverports,health,info
# 获取当前端口
curl http://localhost:8080/actuator/serverports
12.2 动态端口监听器
@Component
public class DynamicPortListener {
private final AtomicInteger actualPort = new AtomicInteger();
@EventListener
public void onWebServerInitialized(WebServerInitializedEvent event) {
actualPort.set(event.getWebServer().getPort());
System.out.println("服务器启动在端口: " + actualPort.get());
}
public int getActualPort() {
return actualPort.get();
}
}
12.3 动态获取服务器信息
@Service
public class ServerInfoService {
@Autowired
private ApplicationContext context;
public void printServerDetails() {
WebServerManager manager = context.getBean(WebServerManager.class);
WebServer webServer = manager.getWebServer();
if (webServer instanceof TomcatWebServer) {
Tomcat tomcat = ((TomcatWebServer) webServer).getTomcat();
for (Connector connector : tomcat.getService().findConnectors()) {
System.out.println("协议: " + connector.getProtocolHandlerClassName());
System.out.println("端口: " + connector.getPort());
System.out.println("状态: " + connector.getState());
}
}
}
}
总结
核心要点
接口体系设计:
启动流程:
SpringApplication.run()→refresh(context)onRefresh()→createWebServer()WebServerFactoryCustomizer自定义配置getWebServer()创建服务器实例finishRefresh()→webServer.start()publishEvent(WebServerInitializedEvent)
定制方式:
WebServerFactoryCustomizer- 启动前自定义ApplicationListener<WebServerInitializedEvent>- 启动后获取信息ServletContextInitializer- Servlet上下文初始化
优化方向:
- 线程池参数调优
- 连接器配置优化
- SSL/HTTP2配置
- 优雅关闭配置
- 健康检查指标
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)