<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
maven中添加 Web 的依赖,Spring Boot 就帮我们内置了 Servlet 容器,默认使用的是 Tomcat
因为内置了启动容器,应用程序可以直接通过 Maven 命令将项目编译成可执行的 jar 包,通过 java -jar 命令直接启动,不需要再像以前一样,打包成 War 包,然后部署在 Tomcat 中。
SpringBoot的启动主要是通过实例化SpringApplication来启动的,启动过程主要做了如下几件事情:
而启动 Tomcat 是在第7步 刷新上下文 这一步。
从整个流转过程中我们知道了 Tomcat 的启动主要是实例化两个组件:Connector、Container。
不同线程做不同的事情
在 Tomcat 中,NIO(New I/O)代表使用非阻塞 IO 的 Java NIO API。Tomcat 7 使用了一个基于 NIO 的连接器(Connector),它支持 HTTP/1.1 协议的长连接(keep-alive)和异步 IO。
相比传统的阻塞 IO 模型,NIO 提供了更高的并发处理能力和更低的资源消耗。NIO 基于事件驱动模型,通过 Selector 监听多个通道的状态变化,当通道就绪时,执行读写操作。这种模型避免了线程阻塞的问题,减少了线程切换的开销,提高了系统的吞吐量。
在 Tomcat 中,NIO 连接器使用了 Java NIO API 中的 ServerSocketChannel 和 SocketChannel,通过分配缓冲区来实现数据的读写操作。同时,Tomcat 还提供了一些针对 NIO 连接器的优化配置,例如调整最大请求头大小、设置线程池大小等,以充分发挥 NIO 的性能优势。
Netty 是一个基于 NIO 的网络通信框架,它通过事件驱动模型和异步非阻塞 IO 实现高性能的网络通信。下面是 Netty NIO 的工作原理:
总之,Netty 的 NIO 实现通过 Selector、Channel、Buffer 和 EventLoop 组成了一个基于事件驱动的高性能网络通信框架,可以支持大量并发连接和高吞吐量的数据传输。
以下是 Netty NIO 的工作原理图示:
Copy Code +---------------------+
| Selector |
| |
| wait for I/O |
| |
+----------+----------+
|
|
+-----------+------------+
| |
+------+--------+ +--------+------+
| Channel A | | Channel B |
| | | |
| +---------+ | | +---------+ |
| |Handler 1| | | | Handler1| |
| +---------+ | | +---------+ |
| +---------+ | | +---------+ |
| |Handler 2| | | | Handler2| |
| +---------+ | | +---------+ |
| +---------+ | | +---------+ |
| |Handler 3| | | | Handler3| |
| +---------+ | | +---------+ |
+---------------+ +--------------+
Figure 1. Netty NIO Architecture
如上图所示,Netty 基于 NIO 实现了事件驱动的网络通信框架。在这个框架中,Selector 负责监听多个 Channel 的状态变化并将其加入到就绪集合中;Channel 封装了 Java NIO 中的 SocketChannel 和 ServerSocketChannel,并通过 ChannelPipeline 来处理数据读写、协议解析等操作;Buffer 缓冲区用于存储数据,以减少数据复制和传输开销;EventLoop 是一个线程,在运行期间负责处理 Channel 上的事件。
在 Netty 中,每个 Channel 都被分配到一个 EventLoop 上,并在该线程中执行 Channel 的事件处理。由于每个 EventLoop 都是单线程的,因此不需要进行线程同步和并发控制,可以避免多线程竞争的问题,提升了性能。同时,通过使用 Selector、Channel 和 Buffer 这些 NIO 组件,Netty 可以支持大量并发连接和高吞吐量的数据传输。
Tomcat 能够处理高并发的原因主要有以下几个:
综上所述,Tomcat 通过多种技术手段来提高处理并发请求的能力,可以满足大规模应用程序的需求。
异步 Servlet 是指在处理 Servlet 请求时,Servlet 容器可以让请求线程在响应之前立即返回,然后通过回调机制等方式通知应用程序响应已经准备好了。这种方式相比传统的同步 Servlet 处理方式,可以更好地处理长时间运行的任务和高并发请求。
具体来说,异步 Servlet 的处理流程如下:
使用异步 Servlet 可以提高服务器的并发能力,从而更好地处理高并发请求。同时,它还可以用于处理需要长时间运行的任务,比如批量数据导入、大文件上传等。
需要注意的是,在使用异步 Servlet 时,应用程序需要负责控制线程的数量和生命周期,避免线程泄漏和资源浪费。
在多线程编程中,子线程和主线程是并行执行的,因此如果需要将子线程的处理结果返回给主线程,可以通过以下方法实现:
无论使用哪种方法,都需要注意线程安全问题,保证多个线程对共享资源的访问不会出现竞争和冲突。
在 Spring Boot 中,可以使用 CompletableFuture 来进行异步编程,实现子线程将处理结果返回给主线程的功能。具体实现方法如下:
以下是示例代码:
javaCopy CodeCompletableFuture future = CompletableFuture.supplyAsync(() -> {
// 执行异步操作,比如发送网络请求等操作
return doSomething();
}).thenApply(result -> {
// 对操作结果进行转换和处理
return processData(result);
});
// 获取最终的处理结果
String result = future.join();
在上述代码中,supplyAsync() 方法执行了一个异步操作,并返回一个 CompletableFuture 对象。接着在 thenApply() 方法中对操作结果进行转换和处理,并返回一个新的 CompletableFuture 对象。最后,通过 join() 方法获取最终的处理结果。
需要注意的是,如果在子线程中发生异常,可以使用 exceptionally() 方法来处理异常情况,比如返回一个默认值。
参考链接:
https://blog.csdn.net/qq_53318060/article/details/129782017
https://blog.csdn.net/niceyoo/article/details/109954382