JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程

概述

JBossWeb 是JBoss 中的 Web 容器,他是对 Tomcat 的封装,本文以 Http 连接器为例,简单说明 JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程 。本文内容提要:

  • Connector 初始化开始过程
  • 如何理解 max-connections
  • JIoEndpoint 处理 Socket 请求

Connector 初始化开始过程

如下图所示:

  1. WebConnectorService 指的是 `org.jboss.as.web.WebConnectorService`
  2. Connector 指的是 `org.apache.catalina.connector.Connector`
  3. Http11Protocol 指的是 `org.apache.coyote.http11.Http11Protocol`
  4. JIoEndpoint 指的是 `org.apache.tomcat.util.net.JIoEndpoint`

Connector init()

Connector 可以是 HTTP Connector,也可以是 AJP Connector,Connector 中有 ProtocolHandler 和 Adapter 属性,Connector 初始化主要包括:初始化 Adapter,且将初始化的 Adapter 的 设定给 ProtocolHandler,然后调运 ProtocolHandler 的初始化方法,如下面代码段所示:

        // Initializa adapter
        adapter = new CoyoteAdapter(this);
        protocolHandler.setAdapter(adapter);

        IntrospectionUtils.setProperty(protocolHandler, "jkHome", System.getProperty("catalina.base"));

        try {
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException(MESSAGES.protocolHandlerInitFailed(e));
        }

Http11Protocol init()

Http11Protocol 它有一个 Http11ConnectionHandler Handler,该 Handler 实现 `org.apache.tomcat.util.net.JIoEndpoint.Handler` 接口,Http11Protocol 同样有一个 JIoEndpoint 属性,该属性用来处理 incoming TCP connections,如下代码段所示:

    protected Http11ConnectionHandler cHandler = new Http11ConnectionHandler(this);
    protected JIoEndpoint endpoint = new JIoEndpoint();

Http11Protocol 初始化主要包括:

  • 给 JIoEndpoint 设定名字,默认设定的名字为 http-/127.0.0.1:8080
  • 给 JIoEndpoint 设定 socket handler,设定的 handler 为 Http11ConnectionHandler,该 handler 的作用是 Handling of accepted sockets
  • 调运 JIoEndpoint 的初始化方法

JIoEndpoint init()

JIoEndpoint,关于此类的作用之前我们有说,对该类最直接的总结如下:

/**
 * Handle incoming TCP connections.
 *
 * This class implement a simple server model: one listener thread accepts on a socket and
 * creates a new worker thread for each incoming connection.
 *
 * More advanced Endpoints will reuse the threads, use queues, etc.
 *
 * @author James Duncan Davidson
 * @author Jason Hunter
 * @author James Todd
 * @author Costin Manolache
 * @author Gal Shachor
 * @author Yoav Shapira
 * @author Remy Maucherat
 */
public class JIoEndpoint {

JIoEndpoint 初始化包括:

  • 初始化 Acceptor thread count,默认初始设定的 Acceptor thread count 为 1
  • 初始化 ServerSocketFactory,并通过初始化的 ServerSocketFactory 创建 ServerSocket

Connector start()

Connector 开始方法验证更新当前的状态,并调运 Http11Protocol 的开始方法

Http11Protocol start()

Http11Protocol 的开始方法中直接调运 JIoEndpoint 的开始方法。

JIoEndpoint start()

JIoEndpoint 的开始方法主要包括:

如果外部基于 Executor 的线程池为空,则初始化内部的 workers 栈,该栈保存Worker,初始化的栈大小定义如下:

 protected int maxThreads = (org.apache.tomcat.util.Constants.LOW_MEMORY) ? 64 : ((Constants.MAX_THREADS == -1) ? 512 * Runtime.getRuntime().availableProcessors() : Constants.MAX_THREADS);

如上:

  • 如果通过系统参数 -Dorg.apache.tomcat.util.LOW_MEMORY=true,则初始化的栈大小为 64
  • 如果通过系统参数 -Dorg.apache.tomcat.util.net.MAX_THREADS=XXX 指定最大值,则初始化的栈大小为系统参数指定的最大值
  • 如果没有通过系统参数指定 MAX_THREADS,则初始化的栈大小为Runtime.getRuntime().availableProcessors()

启动 Poller 线程,默认线程的名字为 http-/127.0.0.1:8080-Poller。

启动 Acceptor 线程,默认线程的名字为 http-/127.0.0.1:8080-Acceptor-0

如下代码段显示如上逻辑

public void start()
        throws Exception {
        // Initialize socket if not done before
        if (!initialized) {
            init();
        }
        if (!running) {
            running = true;
            paused = false;

            // Create worker collection
            if (executor == null) {
                workers = new WorkerStack(maxThreads);
            }

            // Start event poller thread
            eventPoller = new Poller();
            eventPoller.init();
            Thread pollerThread = new Thread(eventPoller, getName() + "-Poller");
            pollerThread.setPriority(threadPriority);
            pollerThread.setDaemon(true);
            pollerThread.start();

            // Start acceptor threads
            for (int i = 0; i < acceptorThreadCount; i++) {
                Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
                acceptorThread.setPriority(threadPriority);
                acceptorThread.setDaemon(daemon);
                acceptorThread.start();
            }
        }
    }

如何理解 max-connections

JBoss Web 中关于max-connections 的定义如下

<subsystem xmlns="urn:jboss:domain:web:1.4" default-virtual-server="default-host" native="false">
            <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" max-connections="200" />

如上,如果我们定义了 max-connections,WebConnectorService 开始方法中会有如下逻辑:

  • 设定 JIoEndpoint 中 pollerSize,如下代码:
    protected int pollerSize = (org.apache.tomcat.util.Constants.LOW_MEMORY) ? 128 : (32 * 1024);
    public void setPollerSize(int pollerSize) { this.pollerSize = pollerSize; }
    public int getPollerSize() { return pollerSize; }

如上,默认的 pollerSize 如果没有 -Dorg.apache.tomcat.util.LOW_MEMORY=true 设定,它的值为 32 * 1024。

  • 设定 JIoEndpoint 中 maxThreads,如下代码段:
    protected int maxThreads = (org.apache.tomcat.util.Constants.LOW_MEMORY) ? 64 : ((Constants.MAX_THREADS == -1) ? 512 * Runtime.getRuntime().availableProcessors() : Constants.MAX_THREADS);
    public void setMaxThreads(int maxThreads) { this.maxThreads = maxThreads; }
    public int getMaxThreads() { return maxThreads; }

注意,该 maxThreads 用来初始化内部的 workers 栈的大小。

JIoEndpoint 处理 Socket 请求

JIoEndpoint 处理 Socket 请求如下图所示

如上,首先 Acceptor 线程(通常名字为 http-/127.0.0.1:8080-Acceptor-0)阻塞等待 Socket 连接,如下所示:

"http-/127.0.0.1:8080-Acceptor-0" daemon prio=10 tid=0x49ed5800 nid=0xbe9 runnable [0x49789000]
   java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAccept(Native Method)
        at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
        at java.net.ServerSocket.implAccept(ServerSocket.java:522)
        at java.net.ServerSocket.accept(ServerSocket.java:490)
        at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:61)
        at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:309)
        at java.lang.Thread.run(Thread.java:722)

   Locked ownable synchronizers:
        - None

//coming soon

JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程

时间: 2024-10-29 14:24:53

JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程的相关文章

Tomcat剖析(四):Tomcat默认连接器(2)

Tomcat剖析(四):Tomcat默认连接器(2) 目录: Tomcat剖析(一):一个简单的Web服务器 Tomcat剖析(二):一个简单的Servlet服务器 Tomcat剖析(三):连接器(1) Tomcat剖析(三):连接器(2) Tomcat剖析(四):Tomcat默认连接器(1) Tomcat剖析(四):Tomcat默认连接器(2) 同样的,你需要先下载代码. https://github.com/zebinlin/Tomcat4-src 经过上一节的讲解,你已经理解了请求和响应对

tomcat connector连接器

Connector是Tomcat最核心的组件之一,负责处理一个WebServer最核心的连接管理.Net IO.线程(可选).协议解析和处理的工作.一.连接器介绍在开始Connector探索之路之前,先看看Connector几个关键字 NIO:Tomcat可以利用Java比较新的NIO技术,提升高并发下的Socket性能 AJP:Apache JServ Protocol,AJP的提出当然还是为了解决java亘古不变的问题——性能,AJP协议是基于包的长连接协议,以减少前端Proxy与Tomca

tomcat 解析(四)-处理http请求过程

声明:源码版本为Tomcat 6.0.35 前面的文章中介绍了Tomcat初始化的过程,本文将会介绍Tomcat对HTTP请求的处理的整体流程,更细节的. 在上一篇文章中,介绍到JIoEndpoint 中的内部类Acceptor用来接受Socket请求,并调用processSocket方法来进行请求的处理,所以会从本文这个方法开始进行讲解. ? 1 2 3 4 5 6 7 8 9 10 11 12 protected boolean processSocket(Socket socket) {

TOMCAT原理详解及请求过程

Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat目录: tomcat |---bin:存放启动和关闭tomcat脚本 |---conf:存放不同的配置文件(server.xml和web.xml): |---doc:存放Tomcat文档: |---lib/japser/common:存放Tomcat运行需要的库文件(JARS): |---logs:

TOMCAT原理详解及请求过程(转)

https://www.cnblogs.com/hggen/p/6264475.html TOMCAT原理详解及请求过程 Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat目录: tomcat |---bin:存放启动和关闭tomcat脚本 |---conf:存放不同的配置文件(server.xml和web.xml): |---doc:存放Tomc

Tomcat系列之Apache负载均衡请求至Tomcat及DeltaManager的使用

Tomcat系列之Apache负载均衡请求至Tomcat及DeltaManager的使用

servlet图解。1。。tomcat处理请求过程、servlet的生命周期

Tomcat的组成部分 Tomcat容器的处理请求过程 servlet的生命周期 HttpServletRequest HttpServletResponse

struts2请求过程源代码分析

struts2请求过程源代码分析 Struts2是Struts社区和WebWork社区的共同成果.我们甚至能够说,Struts2是WebWork的升级版.他採用的正是WebWork的核心,所以.Struts2并非一个不成熟的产品,相反.构建在WebWork基础之上的Struts2是一个执行稳定.性能优异.设计成熟的WEB框架. 我这里的struts2源代码是从官网下载的一个最新的struts-2.3.15.1-src.zip.将其解压就可以. 里面的文件夹页文件很的多,我们仅仅须要定位到stru

mvc请求过程总结-前篇

前言 最近在思考一个问题,我的学习方法一般主要是看博客来学习新东西,但是光看,基本也没总结过,所以经常会出现这样的问题,某个知识点我知道,但是就是不能很好的表达出来,很简单的东西往往都不知道如何简短精炼的阐述清楚.所以我想到应该每天抑或是经常性的总结近期学到的知识,这样既可以巩固知识又可以提高语言的组织能力. MVC的请求过程 有些比较细节的地方直接忽略了,我主要摸索它的大概轨迹 首先从客户端发出请求开始,iis接受请求,找到web应用程序运行的工作者进程,如果进程不存在,则创建的新的工作进程,