《深入剖析Tomcat》读书笔记(一)
一、Tomcat
Tomcat,全名Apache Tomcat,最初是由Sun发起,后来捐赠给ASF,是Apache Jakarta下的一个子项目。
Tomcat是对Servlet API定义的容器的一个完整实现,同时它也不仅仅是一个容器,也完全可以当做一个纯Java实现的HTTP服务器来使用,Tomcat自带的Servlet容器的名称为Catalina。
Tomcat 的心脏是两个组件:Connector 和 Container,一个 Container 可以选择对应多个 Connector。多个 Connector(多个Connector的原因应该是多种网络协议吧) 和一个 Container 就形成了一个 Service,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,该环境由Server提供,所以整个 Tomcat 的生命周期由 Server 控制。
即:
Server:控制Tomcat的start/stop,通过server的start/stop,能够一路畅通地把下面所有的service/connector/container一起start/stop
Service:配置多个Connector的目的一般是为了适应不同的http协议,即不同的协议由不同的connector处理,但都关联到一个Container
Container:Container由四个级别,有高层到底层分别为Engine、Host、Context、Wrapper,具体介绍在下一篇博客解释

二、Tomcat连接器Connector的启动
Tomcat不推荐使用默认连接器,而是使用Coyote(郊狼),但默认的链接器依然是一个比较好的学习范本。本小结的分析就是基于默认连机器。
Connector 组件的主要任务是负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求,并把 Request 和 Response 对象传给处理这个请求的线程。
Connector连接器处理请求的时序图:

下面是Connector启动的入口:
public final class Bootstrap {
public static void main(String[] args) {
HttpConnector connector = new HttpConnector();
SimpleContainer container = new SimpleContainer();
connector.setContainer(container);
connector.initialize();//对应上图第一步,创建全局的ServerSocket
connector.start();
}
}
HttpConnector的start方法如下:
public void start() throws LifecycleException {
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our background thread
threadStart();
// Create the specified minimum number of processors
while (curProcessors < minProcessors) {
if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
break;
//创建多个processor,并且每个processor都调用了本线程的start方法进行启动
//将process压入堆栈,该堆栈用来保存多个processor
HttpProcessor processor = newProcessor();
recycle(processor);
}
}
threadStart()会启动后台线程,于是进入该connector的run()方法,上图中的第3步
private void threadStart() {
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
}
public void run() {
while (!stopped) {
// Accept the next incoming connection from the server socket
Socket socket = null;
try {
socket = serverSocket.accept();//connector会阻塞在accept方法,等待http连接
socket.setTcpNoDelay(tcpNoDelay);
}
// Hand this socket off to an appropriate processor
// 连接带来后获取processor,获取方式很简单,就是从stack中弹出一个
HttpProcessor processor = createProcessor();
// 调用processor的assign方法,assing会通知processor线程去处理具体的动作
// 本处调用直接返回,提高了效率
processor.assign(socket);
// The processor will recycle itself when it finishes
}//结束while
synchronized (threadSync) {
threadSync.notifyAll();
}
}//结束run
上述为Connector线程的启动过程,下面就要讲Processor线程的处理过程了,注意二者是不同的处理线程。
上面讲到processor线程进行了启动,即每个线程都运行了run方法,该run方法如下:
public void run() {
// Process requests until we receive a shutdown signal
while (!stopped) {
// Wait for the next socket to be assigned
// 线程阻塞在这里,等待通知
Socket socket = await();
if (socket == null)
continue;
// Process the request from this socket
process(socket);
// Finish up this request
connector.recycle(this);
}
// Tell threadStop() we have shut ourselves down successfully
synchronized (threadSync) {
threadSync.notifyAll();
}
}
await方法会阻塞住,直到被通知,这是上图中的第5步骤,这个通知的发出是由connector调用processor的assign方法发出的。await()和assing的实现如下:
private synchronized Socket await() {
// Wait for the Connector to provide a new Socket
while (!available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Notify the Connector that we have received this Socket
Socket socket = this.socket;
available = false;
notifyAll();
if ((debug >= 1) && (socket != null))
log(" The incoming request has been awaited");
return (socket);
}
Procesor的assign方法如下:
synchronized void assign(Socket socket) {
// Wait for the Processor to get the previous Socket
while (available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Store the newly available Socket and notify our thread
this.socket = socket;
available = true;
notifyAll();
}
整个过程描述总结如下:
1、processor线程启动的时候,avaliable=false,线程会在await方法中等待,直到其他线程调用notify()或者notifyAll()方法。
2、客户端发起请求,新的socket通过assing()方法传入processor,此时avaliable依然为false,assign方法会跳过while,设置available=true,并发出通知,告诉processor线程可以向下继续运行
3、processor线程收到通知,此时avaliable=true,await方法会跳过while,执行process方法,进行处理。
4、process方法中,将处理好request和response, connector.getContainer().invoke(request, response);交给container去处理。问题是,到底交个container中的哪个servlet去处理呢?后续文章介绍吧
参考资料
《Tomcat深度剖析》
https://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/
《深入剖析Tomcat》读书笔记(一)的更多相关文章
- 《html5 从入门到精通》读书笔记(一)
今天看了<html5 从入门到精通>这本书,感觉阅读下来很舒心,不像阅读其他书籍很揪心.html增加的知识点,我觉得非常有价值,看完几章记录了一些内容,不但能巩固,也为下次遗忘知识点做好准 ...
- HTML5从入门到精通(明日科技) 中文pdf扫描版
HTML5从入门到精通(明日科技) 中文pdf扫描版
- HTML5从入门到精通(千锋教育)免费电子版+PDF下载
本书是HTML5初学者极好的入门教材之一,内容通俗易懂.由浅入深.循序渐进.本书内容覆盖全面.讲解详细,其中包括标签语义化.标签使用规范.选择器类型.盒模型.标签分类.样式重置.CSS优化.Photo ...
- Unity Shader入门精要读书笔记(一)序章
本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数 ...
- Oracle从入门到精通----学习笔记
书名:<Oracle从入门到精通:视频实战版>秦靖.刘存勇等编著 第4章 SQL基础 1.SQL语言分类 数据定义语言 --- DDL,Data Definition Language 数 ...
- MySQL数据库应用 从入门到精通 学习笔记
以下内容是学习<MySQL数据库应用 从入门到精通>过程中总结的一些内容提要,供以后自己复现使用. 一:数据库查看所有数据库: SHOW DATABASES创建数据库: CREATE DA ...
- Unity Shader入门精要读书笔记(二)UnityShader概述
第三章<UnityShader概述>的读书笔记: 1.Unity Shader模板提供了几种选择: 标准光照模型(新添加的基于物理的渲染方法) 不含光照的基本的顶点.片元着色器 屏幕后处理 ...
- 《html5 从入门到精通》读书笔记(二)
接着上面继续记录笔记,这次要记的知识点比较多...记录下我认为比较重要的东西. 一.表单属性 1.autocomplete属性 该属性规定form或input域应该拥有自动完成功能. <form ...
- 《html5 从入门到精通》读书笔记(三)
二.标签详解 标签 描述 4 5 <form> 定义表单. 4 5 <h1> to <h6> 定义标题1到标题6. 4 5 <head> 定义关于文档的 ...
- 《HTML5 CANVAS基础教程》读书笔记
一.HTML5简介 1.HTML5新特性 1)结构元素:section,header,hgroup,footer,nav,article,aside, 2)内容元素:figure,figcaption ...
随机推荐
- 想直接用Windows API开发程序,你真的应该知道这些!
1,Windows数据类型. 2,Windows数据类型命名规律. 3,匈牙利表示法.
- 要件审判九步法及其基本价值 z
要件审判九步法及其基本价值 发布时间:2014-12-24 14:29:05 作者介绍 邹碧华,男,1967年出生于江西奉新,毕业于北京大学法学院,获法学博士学位.上海市高级人民法院副院长.2006年 ...
- vacabulary1
The hard hat is rigid,so nothing will hurt my head. glue 胶水vegetarian 素食者: 素食主义者:素食的 North Korea 朝鲜S ...
- 离线使用echarts及一些细节
最近要做图表,用js起来太麻烦,所以就找些开源的库来用,发现echarts挺不错, echarts的文档把所有东西都说的很明白了,直接下载zip包,要是想离线使用的话只需要引用下载包里面的dist文件 ...
- tomcat7 内存溢出 java.lang.OutOfMemoryError: Java heap space
在{tomcat7_home}bin/catalina.sh最上面添加: JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=128M -XX ...
- redis在windows上的安装
1.下载地址:https://github.com/MSOpenTech/redis 主要支持win64的,有个msi文件可以直接安装,安装后redis会变成一个服务,对于windows来说这种最方便 ...
- [ZOJ 1011] NTA (dfs搜索)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1011 题目大意:在一棵树上,给你起始状态,问你能否到达终止状态. ...
- 一道 JavaScript 面试题
有一道 JavaScript 面试题. f = function () { return true; }; g = function () { return false; }; (function() ...
- win8 C 盘 突然少了 十几G 空间 原因,解决方法
原因: win8 默认最大虚拟内存为 16G多,但现在电脑本身内存就大,所以应该不用了.我现在电脑本身内存是16G. 如果C盘空间大,这个无所谓了,如果C盘空间小可以按以下操作,拿回16G空间: 解决 ...
- some tips
1.在使用selenium的时候,需要等待页面加载完成,特别是一些ajax请求,最好使用以下方法(python),通过document.readyState来判断 from selenium.webd ...