tomcat源码分析学习笔记(三)

本文深入剖析Tomcat的默认连接器工作原理,包括HttpConnector、HttpProcessor的角色与职责,以及多线程处理机制。

——每天的寥寥几笔,坚持下去,将会是一份沉甸甸 的积累。


今天的笔记是针对《tomcat how works》第四章——tomcat的默认连接器来讲的。


1.在上一篇文章我罗列书第三章的源码目录,如下:

connector:      RequestStream,ResponseStream,ResponseWriter

connnectot.http:HttpConnector,HttpProcessor//前者用于创建serverSocket,监听客户端请求;后者是个关键类,后面单独讲

		HttpRequest,HttpResponse,HttpRequestFacade,HttpResponseFacade
			    //request和response实现了HttpRequestServlet和HttpResponseServlet接口,相关填充数据由下面两个对象提供

		HttpHeader,HttpRequestLine//HTTP消息的头部,请求行封装出的两个实体类

		SocketInputStream//用Socket.InputStream封装出的新的类,实现了读取HTTP消息的头部和请求行,封装到上面两个对象中

		Constants//存一些常量,降低耦合度,便于修改

core:           servletProcessor,staticResourceProcessor
			//这两个类为业务处理类,就servlet而言,会根据connector解析出的处理类类名,用反射机制实例化某servlet类来处理。


其实每章就是在之前简单的基础上进行扩张充实。在第四章里,覆盖了我们自己写的HttpConnector,HttpProcessor,采用了org.apache.catalina.connector.http.HttpConnector和org.apache.catalina.connector.http.HttpProcessor(实现了多处理器线程,可以用来处理不同的客户端请求);并新增了一个处理servlet的容器SimpleContainer。【源码及书籍下载链接:http://pan.baidu.com/s/1ntBhXX3


2.再强调一下,第四章的突破点在于:“多处理线程”,所以需要多线程的相关知识,不是很熟的,建议先给自己充下电。马上,下一篇我也会提供相关笔记的。


3.接下来把处理请求的执行流程给梳理下。

(1)bootstrap类启动

    HttpConnector connector = new HttpConnector();
    SimpleContainer container = new SimpleContainer();
    connector.setContainer(container);
    try {
      connector.initialize();
      connector.start();
解释:
- 创建一个Httpconnector连接器,set一个container容器(这个后面解释);
- 初始化操作:会调用open()函数,而open()函数会调用DefaultServerFactory来生产serverSocket对象(前三章都是直接new出来的,这里用到了工厂)
- start操作:会new出来5个(默认,等于minProcessors)httpProcessor对象(通过调用newProcessor()函数,这个函数会启动httpProcessor自身的线程,即run函数已经跑起来),然后添加到栈中(源码如下)。
    start():
        while (curProcessors < minProcessors) {
            if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
                break;
            HttpProcessor processor = newProcessor();
            recycle(processor);//加入栈中
        }
    newProcessor():
	private HttpProcessor newProcessor() {
        //        if (debug >= 2)
        //            log("newProcessor: Creating new processor");
        HttpProcessor processor = new HttpProcessor(this, curProcessors++);
        if (processor instanceof Lifecycle) {
            try {
                ((Lifecycle) processor).start();//httpProcessor实现了runnable接口,调用start函数直接启动线程,具体源码后面提到
            } catch (LifecycleException e) {
                log("newProcessor", e);
                return (null);
            }
        }
        created.addElement(processor);
        return (processor);
}

(2)其实(1)中的connector.start()还会进行一个操作,就是启动httpConnector线程(这个类也实现了runnable接口)。于是自然而然,start函数一执行,便进入run函数

//极简模式   
 public void run() {
        while (!stopped) {
		//监听客户端请求
		//获取socket对象
            processor.assign(socket);//将Socket对象传到httpProcessor里面处理
        }
    }


(3)httpProcessor类。主要功能依旧是封装request,response对象的相关数据,用于触发相关servlet的service方法。封装数据的过程,也就涉及http消息解析,前一篇文章讲到了parseRequest,parseHeaders等,在本文中该类将继续拓展,新增了如parseAcceptLanguage等。

除了上面提到的几个咱们熟悉的方法之外,又新增了assign()和await()方法,下面详细介绍(设计的非常巧妙),主要看看代码里我的文字介绍

public void run() {
        while (!stopped) {
            Socket socket = await();
//流程从这开始:
//new出这个processor对象的时候已经触发run方法(上面讲过),然后调用await()方法,由于默认available=false,
//因此await方法调用wait()方法,是的线程进入等待状态(等待notify方法唤醒)
//知道httpConnector调用assign方法,是的available=true,然后又notify,使得线程被唤醒,正好available=true,跳出while循环,
//available又被赋成false。此时run中的socket不为null,调用process方法进行处理,最后将封装好的request和response对象作为参数触发serlvet容器的处理程序
            if (socket == null)continue;
            try {
                process(socket);
            } catch (Throwable t) {}
            connector.recycle(this);
        }
    }

private void process(Socket socket) {//极简,删掉了细节部分
        connector.getContainer().invoke(request, response);
    }

synchronized void assign(Socket socket) {
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        this.socket = socket;
        available = true;
        notifyAll();
    }
private synchronized Socket await() {
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        Socket socket = this.socket;
        available = false;
        notifyAll();
        return (socket);
    }


(4)还有一个SimpleContainer类,这个就是servlet容器,用来接收request,response对象,解析request得到相应的servlet,根据反射机制,触发改serlvet的service方法

 

public void invoke(Request request, Response response)throws IOException, ServletException {
      servlet.service((HttpServletRequest) request, (HttpServletResponse) response);//主要就是这个invoke方法,和上的process方法挂钩
    }


由于涉及到多线程相关知识,理解起来可能有些难度。下一篇我会整理一份多线程相关的笔记以供大家参考。

又周一了,可能接下来几天更新频率不会那么高(学生党要上课),不过依旧会尽量保持进度(各种学长阿里,腾讯的offer纷纷到手,学弟甚是欣羡,必须加倍努力)。。。。




【SCI复现】含可再生能源与储能的区域微电网最优运行:应对不确定性的解鲁棒性与非预见性研究(Matlab代码实现)内容概要:本文围绕含可再生能源与储能的区域微电网最优运行展开研究,重点探讨应对不确定性的解鲁棒性与非预见性策略,通过Matlab代码实现SCI论文复现。研究涵盖多阶段鲁棒调度模型、机会约束规划、需求响应机制及储能系统优化配置,结合风电、光伏等可再生能源出力的不确定性建模,提出兼顾系统经济性与鲁棒性的优化运行方案。文中详细展示了模型构建、算法设计(如C&CG算法、大M法)及仿真验证全过程,适用于微电网能量管理、电力系统优化调度等领域的科研与工程实践。; 适合人群:具备一定电力系统、优化理论和Matlab编程基础的研究生、科研人员及从事微电网、能源管理相关工作的工程技术人员。; 使用场景及目标:①复现SCI级微电网鲁棒优化研究成果,掌握应对风光负荷不确定性的建模与求解方法;②深入理解两阶段鲁棒优化、分布鲁棒优化、机会约束规划等先进优化方法在能源系统中的实际应用;③为撰写高水平学术论文或开展相关课题研究提供代码参考和技术支持。; 阅读建议:建议读者结合文档提供的Matlab代码逐模块学习,重点关注不确定性建模、鲁棒优化模型构建与求解流程,并尝试在不同场景下调试与扩展代码,以深化对微电网优化运行机制的理解。
个人防护装备实例分割数据集 一、基础信息 数据集名称:个人防护装备实例分割数据集 图片数量: 训练集:4,524张图片 分类类别: - Gloves(手套):工作人员佩戴的手部防护装备。 - Helmet(安全帽):头部防护装备。 - No-Gloves(未戴手套):未佩戴手部防护的状态。 - No-Helmet(未戴安全帽):未佩戴头部防护的状态。 - No-Shoes(未穿安全鞋):未佩戴足部防护的状态。 - No-Vest(未穿安全背心):未佩戴身体防护的状态。 - Shoes(安全鞋):足部防护装备。 - Vest(安全背心):身体防护装备。 标注格式:YOLO格式,包含实例分割的多边形坐标和类别标签,适用于实例分割任务。 数据格式:来源于实际场景图像,适用于计算机视觉模型训练。 二、适用场景 工作场所安全监控系统开发:数据集支持实例分割任务,帮助构建能够自动识别工作人员个人防护装备穿戴状态的AI模型,提升工作环境安全性。 建筑与工业安全检查:集成至监控系统,实时检测PPE穿戴情况,预防安全事故,确保合规性。 学术研究与创新:支持计算机视觉在职业安全领域的应用研究,促进AI与安全工程的结合。 培训与教育:可用于安全培训课程,演示PPE识别技术,增强员工安全意识。 、数据集优势 精准标注与多样性:每个实例均用多边形精确标注,确保分割边界准确;覆盖多种PPE物品及未穿戴状态,增加模型鲁棒性。 场景丰富:数据来源于多样环境,提升模型在不同场景下的泛化能力。 任务适配性强:标注兼容主流深度学习框架(如YOLO),可直接用于实例分割模型开发,支持目标检测和分割任务。 实用价值高:专注于工作场所安全,为自动化的PPE检测提供可靠数据支撑,有助于减少工伤事故。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值