spring boot创建tomcat容器

https://www.cnblogs.com/junzisi/p/15616519.html
原文链接:https://blog.csdn.net/m0_63437643/article/details/123068012

###                                              spring boot创建tomcat容器
起点
-> SpringApplication.run()
-> SpringApplication.refreshContext()
-> AbstractApplicationContext.refresh()
-> AbstractApplicationContext.onRefresh()

第一步:spring boot启动时,容器初始化、启动                                                               重点:仅tomcat容器启动,连接未启动

-> AbstractApplicationContext.onRefresh()
-> ServletWebServerApplicationContext.onRefresh()


    createWebServer()         
-> ServletWebServerApplicationContext.createWebServer()                                                    createWebServer方法会将
                                                                                                           创建的webServer封装在WebServerStartStopLifecycle对象中,
                                                                                                           并注册到Spring容器中。
                                                                                                           
                                                                                                           
    ServletWebServerFactory factory = getWebServerFactory()                                                 getWebServerFactory会创建
                                                                                                            tomcatServletWebServerFactory、
                                                                                                            DispatcherServlet、
                                                                                                            DispatcherServletRegistrationBean 等bean放在ioc容器中                                                                                                          
    this.webServer = factory.getWebServer(getSelfInitializer())
    
    
-> ServletWebServerFactory.getWebServer()                                                                  ServletWebServerFactory的实现有tomcat、jetty、undertow

-> TomcatServletWebServerFactory.getWebServer()                                                            首先创建Tomcat,创建连接器Connector、创建协议、
                                                                                                           创建端点…创建容器Container,如StandardServer、…
    Tomcat tomcat = new Tomcat()
    Connector connector = new Connector(this.protocol)
    tomcat.getService().addConnector(connector)
    ...
-> TomcatServletWebServerFactory.getTomcatWebServer(tomcat)
-> new TomcatWebServer(tomcat, getPort() >= 0, getShutdown())
    initialize()
-> TomcatWebServer.initialize()                                                                            仅初始化:初始化Connector(Connector的内部类initInternal())时,
                                                                                                            会创建协议适配器CoyoteAdapter,它是连接Connector和Container的桥梁,
                                                                                                            具体就是:适配器持有Connector属性,协议持有适配器,
                                                                                                            连接器持有容器(Service)。
                                                                                                            初始化协议
                                                                                                            初始化端点
                                                                                                            初始化容器
                         
    tomcat.start()                                                                                          启动服务,触发初始化监听
                                                                                                            重要步骤:把DispatcherServlet注册到StandardWraper中                             
TomcatWebServer 的 initialize 方法中做了以下操作:重命名tomcat 弓|擎名称、对 Context 添加生 命周期监听事件、启动服务触发初始化监听、检查TomcatStarter 对象是否存在及 Container 状态是否正确、绑定命名到类加载器、启动守护等待线程等。

容器逐层start采用的是异步方式,但提交异步任务之后会同步等待子容器start完成,效果相当于同步完成。
                        
    


第二步:spring boot启动时,协议端点的初始化                                                                tomcat连接启动                                                        
->AbstractApplicationContext.finishRefresh()

    protected void finishRefresh() {
        // Initialize lifecycle processor for this context.
        // 初始化生命周期处理器。这个bena也是有固定名称的
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        // 启动生命周期处理器
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        // 发布 ContextRefreshedEvent 事件
        publishEvent(new ContextRefreshedEvent(this));
    }

    调用getLifecycleProcessor().onRefresh()       

    
-> org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start()                                                               
                                                                                        SpringBoo中就是通过实现SmartLifecycle来启动内嵌的web容器,
                                                                                        实现类为WebServerStartStopLifecycle。
                                                                                        
    public void start() {
        this.webServer.start();
        this.running = true;
        this.applicationContext
            .publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
    }                                                                                
                                                                                        
-> TomcatWebServer.start()
-> TomcatWebServer.addPreviouslyRemovedConnectors()
-> StandardService.addConnector()

    public void addConnector(Connector connector) {

        synchronized (connectorsLock) {
            connector.setService(this);
            Connector results[] = new Connector[connectors.length + 1];
            System.arraycopy(connectors, 0, results, 0, connectors.length);
            results[connectors.length] = connector;
            connectors = results;
        }

        try {
            if (getState().isAvailable()) {
                connector.start();                                                      启动连接    
            }
        } catch (LifecycleException e) {
            throw new IllegalArgumentException( );
        }
 
    }


-> LifecycleBase.startInternal()
-> Connector.startInternal()
   protocolHandler.start()                                                             启动协议
-> AbstractProtocol.startInternal()
   endpoint.start()
-> AbstractEndpoint.start()
-> NioEndpoint.startInternal()                                                         启动端点

   createExecutor()                                                                    线程池
   initializeConnectionLatch()
   poller = new Poller();                                                              Poller线程
   startAcceptorThread()                                                               Acceptor线程监听客户端请求
   

第三步:监听客户端请求

Acceptor处理客户端连接
主要用于接收网络请求,建立连接,连接建立之后,将一个SocketChannel对象包装成一个NioChannel,并注册到Poller中。由Poller来负责执行数据的读取和业务执行。           
Acceptor的作用是控制与tomcat建立连接的数量,但Acceptor仅仅负责建立连接。AbstractEndpoint有个maxConnections属性,用来规定server所能接受的最大连接数。
默认是8192。在NioEndpoint初始化的时候,会使用maxConnections来初始化一个LimitLatch,使用这个LimitLatc来进行并发请求连接的管理。 

###        Acceptor与三次握手

backlog=syn+accept=accpetCount
对于client端的一个请求进来,流程是这样的:tcp的三次握手建立连接,建立连接的过程中,OS维护了半连接队列(syn队列)以及完全连接队列(accept队列),
在第三次握手之后,server收到了client的ack,则进入establish的状态,然后该连接由syn队列移动到accept队列。
tomcat的Acceptor线程则负责从accept队列中取出该connection,然后交给工作线程去处理(读取请求参数、处理逻辑、返回响应等等;
如果该连接不是keep alived的话,则关闭该连接,然后该工作线程释放回线程池,如果是keep alived的话,则等待下一个数据包的到来直到keepAliveTimeout,
然后关闭该连接释放回线程池),然后自己接着去accept队列取connection(当当前socket连接超过maxConnections的时候,Acceptor线程自己会阻塞等待,等连接降下去之后,
才去处理accept队列的下一个连接)。


###         Acceptor与限流器

执行时,使用while(true)来进行循环。主要是进行serverSocket.accept的监听。当没有连接请求来时,线程会堵塞在accept方法上。
当有新的请求到达时,使用countUpOrAwaitConnection来管理连接数。假设连接数还没有达到最大值。就将LimitLatch的值加1,LimitLatch的值就表示了当前与服务端建立连接的个数,
socket成功执行就调用desctorySocket方法,进而调用countDownConnection方法减一,socket异常时直接调用countDownConnection减一。假设已经达到了最大值,则让线程等待。

###         Poller工作线程进行业务处理
在端点的startInternal方法中启动,由pollerThreadCount属性控制,默认是2。
socket内容的读写是通过Poller来实现的。Poller使用java nio来实现连接的管理。封装后SocketChannel放入Poller线程内部维护的一个PollerEvent队列中,
然后在Poller线程运行时处理队列,将SocketChannel注册到这个Poller的Selector上。
当数据到来的时候,Selector通过selector.select系列方法来获取数据,然后经由processKey到processSocket方法,封装成一个SocketProcessor对象后,放在EndPoint的线程池中执行。
SocketProcessor
SocketProcessor中调用协议的ConnectionHandler,它内部调用Processor,Processor内部在调用CoyoteAdaptor完成请求转换并调用到Container中。 

###         Processor

###         CoyoteAdaptor


管道任务
一个servlet容器可以有一条管道。当调用了容器的invoke()方法后,容器将处理工作交由管道完成,而管道会调用其中的第一个阀开始处理。当第一个阀处理完后,它会调用后续的阀继续执行任务,直到管道中所有的阀都处理完成,基础阀总是最后一个执行的。


 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值