整体架构图

一. 启动阶段

BootStrap的main方法加载server.xml配置文件,封装成Server,Service,Connector,Engine等java对象

Server初始化==>Service初始化==>Connector初始化==>Engine初始化==>Host初始化==>Context初始化 WAR解压 创建Servlet

Connector初始化:绑定端口,创建BIO NIO NIO2线程池

Connector.setProtocol是在解析server.xml配置文件时绑定关系

启动Connector initInternal() ===>ProtocolHandler.init() ==> Endpoint.init()-->Endpoint.bind()

Connector作用(接收请求时):

ServerSocket(Channel)接收socket请求创建Socket, 并将Socket.InputStream中的内容封装成javax.servlet.http.HttpServletRequest的实现类, 经过多个valve filter之后传递到Container的Servlet(SpringMVC)中, servlet.doService完成之后由HttpServletResponse(持有请求时创建的socket?).outputStream回写内容到socket中

Protocol 配置在server.xml的<connector >标签的属性中, 作用:根据配置创建不同的Endpoint

tomcat8.5

Endpoint 具体协议的实现, 完成绑定端口及创建线程池

tomcat8.5

tomcat8.0 

tomcat 7.0

Endpoint.startInternal()

7.0默认使用JIOEndpoint, 8.0以上默认使用NIOEndpoint

//搞懂NIO NIO2===>

二、接收浏览器HTTP请求

整体流程:

NIOEndpoint ---> Http11Processor(创建Request, Response) ---> CoyoteAdapter --> Container -->

PipeLine(StandardEngineValve, StandardHostValve, StandardContextValve, StandardWrapperValve)--> Servlet.doService

2.1 Endpoint中request创建

JIOEndpoint在接收socket请求后,直接将Request交给了worker线程

NIOEndpoint.Acceptor在接收到请求后(while循环一直监听),将PollerEvent事件注册到NIOEndpoint.Poller(持有selector对象)的事件队列中,并调用selector.waitup() 只调用一次,

private void addEvent(PollerEvent event) {
events.offer(event);
if ( wakeupCounter.incrementAndGet() == 0 ) selector.wakeup();
}

Poller的while循环中查找到PollerEvent, 调用processKey()方法-->AbstractEndpoint#processSocket()在这里创建SocketProcessor(Runable)并提交给Executor线程池处理。

SocketProcessor --> Http11Processor.service() readsocket&buildRequest-->CoyoteAdatper.service()

2.2 CoyoteAdapter中处理Request

Servlet3.1 异步Request, 在Servlet里面设置.isAsync, coyoteAdapter invoke服务方法后直接返回,socket并没有释放

org.apache.catalina.connector.CoyoteAdapter#service

             if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
// Calling the container 调用filter servlet
connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);
}
if (request.isAsync()) {
async = true;
ReadListener readListener = req.getReadListener();
if (readListener != null && request.isFinished()) {
// Possible the all data may have been read during service()
// method so this needs to be checked here
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, null);
if (req.sendAllDataReadEvent()) {
req.getReadListener().onAllDataRead();
}
} finally {
request.getContext().unbind(false, oldCL);
}
} Throwable throwable =
(Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION); // If an async request was started, is not going to end once
// this container thread finishes and an error occurred, trigger
// the async error process
if (!request.isAsyncCompleting() && throwable != null) {
request.getAsyncContextInternal().setErrorState(throwable, true);
}
} else {
request.finishRequest(); // 非异步的请求处理之后, 会释放socket
response.finishResponse();
}

session创建时机, 在Request.getSession时根据请求中的JSESSIONID查找,如果id为null,首次创建,新的请求中就携带了JSESSIONID

Connector创建的是org.apache.catalina.connector.Request

org.apache.catalina.core.StandardWrapperValve --> 具体某个Servlet (DispatchServlet),  初始化FilterChain, 然后调用各个filter, 最后到Servlet.doService

filterChain.doFilter
(request.getRequest(), response.getResponse());

压缩版的两个默认Servlet: DefaultServlet处理静态资源,JSPServlet创建HttpServletRequest,对connector.Request又包一层

2.3 Response的socket WRITE,CLOSE事件在NIOEndpoint中的处理

和socket OPEN_READ事件基本一致

其他参考:

Http中socket长连接短连接使用场景 http://www.cnblogs.com/0201zcr/p/4694945.html

程序中设置为长连接 1. socket.setKeepAlive(true)   2.socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);

See:

http://tomcat.apache.org/tomcat-8.0-doc/architecture/requestProcess.html

http://tomcat.apache.org/tomcat-8.0-doc/config/http.html#NIO2_specific_configuration

Tomcat从socket到java Servlet的更多相关文章

  1. tomcat(一)--java基础

    什么是java java所涉及到的相关概念如下图.总体来说就是java语言.java API.jvm等构成. jvm:java虚拟机,java的代码都是运行在jvm上,这是java语言跨平台的保证,针 ...

  2. Java Servlet完全教程

    Servlet 是一些遵从Java Servlet API的Java类,这些Java类可以响应请求.尽管Servlet可以响应任意类型的请求,但是它们使用最广泛的是响应web方面的请求. Servle ...

  3. Java Servlet系列之Servlet生命周期

    Servlet生命周期定义了一个Servlet如何被加载.初始化,以及它怎样接收请求.响应请求,提供服务.在讨论Servlet生命周期之前,先让我们来看一下这几个方法: 1. init()方法 在Se ...

  4. Java Servlet(四):Servlet接口service工作(ServletRequest,ServletResponse对象)(jdk7+tomcat7+eclipse)

    本篇将会记录,Servlet接收客户端传递来的参数信息,并返回信息使用的对象,及这些对象的函数相关用法. 还是在java ee工程中进行操作,在WebContent目录下创建一个login.jsp文件 ...

  5. Java Servlet——改进的CGI

    一.关于Servlet 在上一篇随笔中,我们看到了CGI存在的不足,其每次请求都需加载和运行一个CGI程序.若使用Java编写CGI程序,需要为每个请求都启动一个系统进程以及JVM,其执行效率大大降低 ...

  6. Java Servlet 技术简介

    Java Servlet 技术简介 Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么 ...

  7. Java Servlet 工作原理问答

    导读 本文来自stackoverflow的问答,讨论了Java Servlet的工作机制,如何进行实例化.共享变量和多线程处理. 问题:Servlet是如何工作的?Servlet 如何实例化.共享变量 ...

  8. 【Java】Java Servlet 技术简介

    Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么,它们是如何工作的,如何使用它们来创 ...

  9. JavaWeb之Java Servlet完全教程(转)

    Servlet 是一些遵从Java Servlet API的Java类,这些Java类可以响应请求.尽管Servlet可以响应任意类型的请求,但是它们使用最广泛的是响应web方面的请求. Servle ...

随机推荐

  1. Android TextView跑马灯

    <TextView android:layout_width="fill_parent" android:layout_height="wrap_content&q ...

  2. 升级MySQL 5.7版本遇到的一些小问题(转)

    在5.6版本服务器做备份 /usr/local/mysql/bin/mysqldump -S /tmp/mysql3306.sock -A -p --set-gtid-purged=OFF > ...

  3. chromedriver下载

    https://www.cnblogs.com/vickey-wu/p/6629407.html

  4. 【转】Pro Android学习笔记(二五):用户界面和控制(13):LinearLayout和TableLayout

    目录(?)[-] 布局Layout 线性布局LinearLayout 表格布局TableLayout 布局Layout Layout是容器,用于对所包含的view进行布局.layout是view的子类 ...

  5. Webpack 基础使用

    使用webstorm编译: 1.新建一个工程(最基本的工程) 2.在webstorm的控制台,使用命令行     cnpm install webpack  -g  全局安装 3.安装完后,可以使用 ...

  6. 能否自己也写一个类叫做java.lang.String?

    这次的随笔很逗吧~没错,我们的确也可以自己在创建一个包java.lang,然后在 相应的包下面创建一个对应的类String,但是在每次jre运行的时候,我们都回去加载原来默认的java.lang.St ...

  7. Android Studio的Android Monitor窗口中把标签拉出来之后放不回去的解决方法

    不小心把下图方框中的logcat标签拖出来之后, 就变成了图2的浮动窗口,发现logcat标签怎么也弄不回原来窗口中的位置中. 其实解决方法很简单,只要拖住下图浮动窗口中红框位置的logcat标签,然 ...

  8. 安装zendstudio和破解方法及配置svn

    下载zendstudio12文件http://www.zendstudio.net/zend-studio-all-in-one-download/ 下载破解补丁http://pan.baidu.co ...

  9. Linux下压缩/解压

    Linux下各种压缩包的解压方法 作者:intq 时间:2009-9-25 文章来源:来自网络 ---------------------------------------------------- ...

  10. [Uva10641]Barisal Stadium(区间dp)

    题意:按照顺时针给出操场的周边点,然后给出周围可以建设照明灯的位置,以及在该位置建设照明灯的代价,照明灯照射的范围与操场的边界相切,现在要求一个最小的花费,要求操场的所有边都被照射到. 解题关键:预处 ...