博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Springboot源码分析之内嵌tomcat源码分析
阅读量:1981 次
发布时间:2019-04-27

本文共 6773 字,大约阅读时间需要 22 分钟。

Springboot源码是内嵌tomcat的,这个和完整的tomcat还是不同。

内嵌tomcat的源码在tomcat-embed-core等3个jar包里

 展开tomcat-embed-core的catalina目录

再对照下载的apache-tomcat-9.0.31源码

打开bin目录,看到很多库文件比如catalina.jar

再展开看看类文件

和之前Spring内嵌的tomcat-embed-core的catalina目录文件一致。

所以内嵌的tomcat只用了一部分代码。

 

内嵌tomcat的配置文件是ServerProperties.java

在org.springframework.boot.autoconfigure.web里,port等配置信息默认取这里的。

调试一下

可以看到最大线程数:maxThreads=200

最大连接数:maxConnections=8192

 

修改最大线程数和最大连接数

##端口号server.port=8080server.tomcat.max-threads=300server.tomcat.max-connections=10000

已经改了

 

再看看NIO和APR源码

在TomcatServletWebServerFactory.java

public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory		implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {	private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;	private static final Set
> NO_CLASSES = Collections.emptySet(); /** * The class name of default protocol used. */ public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
private String protocol = DEFAULT_PROTOCOL;
protocol读取默认的DEFAULT_PROTOCOL

启动完成输出日志看到确实是NIO:

2020-02-27 12:38:43.264 [main] [INFO ] o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)2020-02-27 12:38:43.277 [main] [INFO ] org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]

NIO相对于BIO已经是提升很多, 还可以改为更高效的APR

tomtcat7.0内置BIO,8.0,9.0都是NIO。

这三种模式的不同之处如下:

BIO

【一个线程处理一个请求】。

缺点:【并发量高时,线程数较多,浪费资源】。

Tomcat7或以下,在Linux系统中默认使用这种方式。

NIO

【多路复用】,可以通过【一个线程处理大量的请求】。

Tomcat8在Linux系统中默认使用这种方式。

APR

即Apache Portable Runtime,从操作系统层面解决io阻塞问题。

Tomcat7或Tomcat8在Win7或以上的系统中启动默认使用这种方式。

------------------------------------------------------------------------

Tomcat源码中与connector相关的类位于org.apache.coyote包中,Connector分为以下几类:

Http Connector, 基于HTTP协议,负责建立HTTP连接。它又分为BIO Http Connector与NIO Http Connector两种,后者提供非阻塞IO与长连接Comet支持。默认情况下,Tomcat使用的就是这个Connector。

AJP Connector, 基于AJP协议,AJP是专门设计用来为tomcat与http服务器之间通信专门定制的协议,能提供较高的通信速度和效率。如与Apache服务器集成时,采用这个协议。

APR HTTP Connector, 用C实现,通过JNI调用的。主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能。现在这个库已独立出来可用在任何项目中。Tomcat在配置APR之后性能非常强劲。

具体地,Tomcat7中实现了以下几种Connector:

org.apache.coyote.http11.Http11Protocol : 支持HTTP/1.1 协议的连接器。

org.apache.coyote.http11.Http11NioProtocol : 支持HTTP/1.1 协议+New IO的连接器。

org.apache.coyote.http11.Http11AprProtocol : 使用APR(Apache portable runtime)技术的连接器,利用Native代码与本地服务器(如linux)来提高性能。

(以上三种Connector实现都是直接处理来自客户端Http请求,加上NIO或者APR)

org.apache.coyote.ajp.AjpProtocol:使用AJP协议的连接器,实现与web server(如Apache httpd)之间的通信

org.apache.coyote.ajp.AjpNioProtocol:SJP协议+ New IO

org.apache.coyote.ajp.AjpAprProtocol:AJP + APR

------------------------------------

关于  APR介绍

 

介绍

Tomcat可以使用提供出色的可伸缩性,性能以及与本机服务器技术的更好集成。Apache可移植运行时是一个高度可移植的库,它是Apache HTTP Server 2.x的核心。APR有许多用途,包括访问高级IO功能(例如sendfile,epoll和OpenSSL),操作系统级别的功能(生成随机数,系统状态等)和本机进程处理(共享内存,NT管道和Unix套接字)。

这些功能使Tomcat成为通用的Web服务器,可以更好地与其他本机Web技术集成,并且总体上使Java作为完善的Web服务器平台而不是仅以后端为中心的技术更加可行。

安装

APR支持需要安装三个主要的本机组件:

  • APR库
  • Tomcat使用的APR的JNI包装器(libtcnative)
  • OpenSSL库

APR主页

 

由于本地开发是基于Windows,Windows下需要二进制文件提供给tcnative-1,它是一个静态编译的.dll,其中包括OpenSSL和APR。在下载对应tomcat包,将bin目录下的tcnative-1.dll拷贝到jdk安装目录的bin目录下.

新增配置文件:

import org.apache.catalina.core.AprLifecycleListener;import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class AprProtocolConfig {    @Bean    public TomcatServletWebServerFactory servletContainer() {        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();        tomcat.setProtocol("org.apache.coyote.http11.Http11AprProtocol");        tomcat.addContextLifecycleListeners(new AprLifecycleListener());        return tomcat;    }}

 

先初始化TomcatServletWebServerFactory,默认的protocol是NIO

 再set为APR

再到TomcatServletWebServerFactory.getWebServer初始化Connector

 反射出org.apache.coyote.http11.Http11AprProtocol

完成初始化

 

ServletWebServerApplicationContext.createWebServer()创建webserver

启动完成输出APR模型: 

[main] [INFO ] org.apache.coyote.http11.Http11AprProtocol - Initializing ProtocolHandler ["http-apr-8080"] [main] [INFO ] org.apache.catalina.core.StandardService - Starting service [Tomcat] [main] [INFO ] org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.30]

 

下面这两篇讲怎么自定义配置实现自动配置

下面这篇讲linux下apr库安装

 

================

tomcat8.5以后都是NIO,可以在NIO和APR之间选

public Connector(String protocol) {        boolean aprConnector = AprLifecycleListener.isAprAvailable() &&                AprLifecycleListener.getUseAprConnector();        if ("HTTP/1.1".equals(protocol) || protocol == null) {            if (aprConnector) {                protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";            } else {                protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";            }        } else if ("AJP/1.3".equals(protocol)) {            if (aprConnector) {                protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";            } else {                protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";            }        } else {            protocolHandlerClassName = protocol;        }

再用反射出对象

// Instantiate protocol handler        ProtocolHandler p = null;        try {            Class
clazz = Class.forName(protocolHandlerClassName); p = (ProtocolHandler) clazz.getConstructor().newInstance(); } catch (Exception e) { log.error(sm.getString( "coyoteConnector.protocolHandlerInstantiationFailed"), e); } finally { this.protocolHandler = p; }

===========================

Spring Boot 集成undertow作为web容器

默认是tomcat,也可以启用undertow。

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

 启动信息里面的tomcat已经被替换为undertow:

2020-03-22 23:25:44.535 [main] [INFO ] io.undertow - starting server: Undertow - 2.0.29.Final2020-03-22 23:25:44.542 [main] [INFO ] org.xnio - XNIO version 3.3.8.Final2020-03-22 23:25:44.550 [main] [INFO ] org.xnio.nio - XNIO NIO Implementation Version 3.3.8.Final2020-03-22 23:25:44.633 [main] [INFO ] o.s.b.w.embedded.undertow.UndertowServletWebServer - Undertow started on port(s) 8080 (http) with context path ''2020-03-22 23:25:44.635 [main] [INFO ] c.p.springboot.SpringBootLearningApplication - Started SpringBootLearningApplication in 3.209 seconds (JVM running for 3.682)

 

转载地址:http://elrpf.baihongyu.com/

你可能感兴趣的文章
13行MATLAB代码实现网络爬虫 爬取NASA画廊星图
查看>>
MATLAB指定路径保存图片方法
查看>>
Python一键获取微信推送封面图
查看>>
油猴脚本:微信推送浏览功能拓展
查看>>
JavaScript DOM对象操作详解
查看>>
JavaScript 表单操作与MD5加密
查看>>
JAVA学习笔记4 - 循环与分支结构
查看>>
JAVA学习笔记5 - Number类,Math类,Character类,String类,StringBuffer类
查看>>
JAVA学习笔记6 - 数组
查看>>
JAVA学习笔记8 - Stream 和 File I/O
查看>>
JAVA学习笔记9 - 异常
查看>>
JAVA学习笔记10 - 继承
查看>>
JAVA学习笔记11 - 接口interface
查看>>
JAVA学习笔记12 - 包package
查看>>
Android 开发学习笔记 00 - Getting Started
查看>>
【学习笔记】Android Activity
查看>>
【学习笔记】Android Fragments
查看>>
Android使用Retrofit_00_Getting Started
查看>>
Android使用Retrofit_01_OAuth2 + GitHub
查看>>
Django oauth toolkit + Android + Retrofit 实现 OAuth2 的 access token 获取
查看>>