How Tomcat Works 3

2024-03-15 00:32
文章标签 tomcat works

本文主要是介绍How Tomcat Works 3,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Tomcat体系结构中有一个非常重要的概念——连接器,看下面这张图


一个connecotr对应一个container,connector用于接收请求,然后传递给container组件去处理,tomcat中默认的连接器是coyote,按照协议类型分,有http和ajp的连接器。

HTTP/1.1协议负责建立HTTP连接,web应用通过浏览器访问tomcat服务器用的就是这个连接器,默认监听的是8080端口;

AJP/1.3协议负责和其他HTTP服务器建立连接,监听的是8009端口,比如tomcat和apache或者iis集成时需要用到这个连接器。

下面是一个简单的connector实现:

package server2.connector;import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
/*** HttpConnector主要负责接入消息,分发给不同的处理器* * @author Administrator**/
public class HttpConnector implements Runnable{private boolean shutdown = false;// 服务器是否停止private String scheme = "http";public String getScheme() {return scheme;}public void setScheme(String scheme) {this.scheme = scheme;}@Overridepublic void run() {ServerSocket serverSocket = null;int port = 8080;try {serverSocket = new ServerSocket(port, 1,InetAddress.getByName("127.0.0.1"));} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}Socket socket = null;while (!shutdown) {// 不停的接受请求try {socket = serverSocket.accept();} catch (IOException e) {e.printStackTrace();}HttpProcessor processor = new HttpProcessor();processor.process(socket);}}/*** 启动connector监听线程*/public void start(){System.out.println("started!!!");Thread thread = new Thread(this);thread.start();}
}
这是一种非常原始的处理方法,一旦接收到请求便会构造出一个处理器,由处理器去处理socket,并且process是一个同步的方法,这里没有用到Processor的池化,也没有使用异步的方式处理socket。这种同步阻塞的方式,connector的处理能力有限,一旦处理过程被阻塞,那么connector便会拒绝下一个请求。

异步方式的connector它的run方法如下:

/*** The background thread that listens for incoming TCP/IP connections and* hands them off to an appropriate processor.*/public void run() {// Loop until we receive a shutdown commandwhile (!stopped) {// Accept the next incoming connection from the server socketSocket socket = null;try {//                if (debug >= 3)//                    log("run: Waiting on serverSocket.accept()");//接收客户端的socket连接socket = serverSocket.accept();//                if (debug >= 3)//                    log("run: Returned from serverSocket.accept()");if (connectionTimeout > 0)socket.setSoTimeout(connectionTimeout);socket.setTcpNoDelay(tcpNoDelay);} catch (AccessControlException ace) {log("socket accept security exception", ace);continue;} catch (IOException e) {//                if (debug >= 3)//                    log("run: Accept returned IOException", e);try {// If reopening fails, exitsynchronized (threadSync) {if (started && !stopped)log("accept error: ", e);if (!stopped) {//                    if (debug >= 3)//                        log("run: Closing server socket");serverSocket.close();//                        if (debug >= 3)//                            log("run: Reopening server socket");serverSocket = open();}}//                    if (debug >= 3)//                        log("run: IOException processing completed");} catch (IOException ioe) {log("socket reopen, io problem: ", ioe);break;} catch (KeyStoreException kse) {log("socket reopen, keystore problem: ", kse);break;} catch (NoSuchAlgorithmException nsae) {log("socket reopen, keystore algorithm problem: ", nsae);break;} catch (CertificateException ce) {log("socket reopen, certificate problem: ", ce);break;} catch (UnrecoverableKeyException uke) {log("socket reopen, unrecoverable key: ", uke);break;} catch (KeyManagementException kme) {log("socket reopen, key management problem: ", kme);break;}continue;}// Hand this socket off to an appropriate processor//创建processor,如果连接池没有可用的处理器,则拒绝消息,其中的createProcessor方法基于栈来实现的处理池HttpProcessor processor = createProcessor();if (processor == null) {try {log(sm.getString("httpConnector.noProcessor"));socket.close();} catch (IOException e) {;}continue;}//            if (debug >= 3)//                log("run: Assigning socket to processor " + processor);//否则的话将socket传递给processorprocessor.assign(socket);// The processor will recycle itself when it finishes}// Notify the threadStop() method that we have shut ourselves down//        if (debug >= 3)//            log("run: Notifying threadStop() that we have shut down");synchronized (threadSync) {threadSync.notifyAll();}}
接收到socket调用processor的assign方法传递给HttpProcessor。处理器的实现也和上面有很大的差别,这里单独实现为一个线程类,先不急看assign方法,看看processor的run方法:

 /*** The background thread that listens for incoming TCP/IP connections and* hands them off to an appropriate processor.*/public void run() {// Process requests until we receive a shutdown signal//不停的循环处理消息while (!stopped) {// Wait for the next socket to be assigned//调用自身的await()Socket socket = await();//未获取到socket继续循环if (socket == null)continue;// Process the request from this sockettry {//获取到则进行处理process(socket);} catch (Throwable t) {log("process.invoke", t);}// Finish up this request//将该处理线程放回池中复用connector.recycle(this);}// Tell threadStop() we have shut ourselves down successfullysynchronized (threadSync) {threadSync.notifyAll();}}
await方法:

/*** Await a newly assigned Socket from our Connector, or <code>null</code>* if we are supposed to shut down.该方法是个同步方法,并且内部可能发生阻塞*/private synchronized Socket await() {// Wait for the Connector to provide a new Socket
//如果没有可处理的socket则同步阻塞,这里connector调用processor的assign方法会传递
//过来可用的socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this Socket
//否则可以处理,成员变量赋值给私有变量Socket socket = this.socket;
//设置为没有可处理的socketavailable = false;
//唤醒被阻塞的线程notifyAll();if ((debug >= 1) && (socket != null))log("  The incoming request has been awaited");return (socket);}


再来看下assign方法:

synchronized void assign(Socket socket) {// Wait for the Processor to get the previous Socket//available表示是否有可处理的socket,第一次值为false跳过while循环while (available) {//try {wait();} catch (InterruptedException e) {}}// Store the newly available Socket and notify our thread//将socket赋值给成员变量socketthis.socket = socket;//修改值为trueavailable = true;//唤醒阻塞在该对象上的线程notifyAll();if ((debug >= 1) && (socket != null))log(" An incoming request is being assigned");}
如果当前线程有可处理的socket则阻塞住connector,否则唤醒阻塞在await上的线程,处理可用的socket,这里的assign方法是异步返回的,只是负责传递socket,处理过程由processor线程完成。connector和processor线程的通讯由available变量和wait,notifyAll方发共同完成。



这篇关于How Tomcat Works 3的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810230

相关文章

详解Tomcat 7的七大新特性和新增功能(1)

http://developer.51cto.com/art/201009/228537.htm http://tomcat.apache.org/tomcat-7.0-doc/index.html  Apache发布首个Tomcat 7版本已经发布了有一段时间了,Tomcat 7引入了许多新功能,并对现有功能进行了增强。很多文章列出了Tomcat 7的新功能,但大多数并没有详细解释它们

Tomcat性能参数设置

转自:http://blog.csdn.net/chinadeng/article/details/6591542 Tomcat性能参数设置 2010 - 12 - 27 Tomcat性能参数设置 博客分类: Java Linux Tomcat 网络应用 多线程 Socket 默认参数不适合生产环境使用,因此需要修改一些参数   1、修改启动时内存参数、并指定J

TL-Tomcat中长连接的底层源码原理实现

长连接:浏览器告诉tomcat不要将请求关掉。  如果不是长连接,tomcat响应后会告诉浏览器把这个连接关掉。    tomcat中有一个缓冲区  如果发送大批量数据后 又不处理  那么会堆积缓冲区 后面的请求会越来越慢。

Tomcat下载压缩包解压后应有如下文件结构

1、bin:存放启动和关闭Tomcat的命令的路径。 2、conf:存放Tomcat的配置,所有的Tomcat的配置都在该路径下设置。 3、lib:存放Tomcat服务器的核心类库(JAR文件),如果需要扩展Tomcat功能,也可将第三方类库复制到该路径下。 4、logs:这是一个空路径,该路径用于保存Tomcat每次运行后产生的日志。 5、temp:保存Web应用运行过程中生成的临时文件

docker学习系列(四)制作基础的base项目镜像--jdk+tomcat

前面已经完成了docker的安装以及使用,现在我们要将自己的javaweb项目与docker结合 1.1准备jdk+tomcat软件 ​​我下载了apache-tomcat-7.0.68.tar.gz和jdk-7u79-linux-x64.tar.gz,存储于Linux机器的本地目录/usr/ect/wt/下(利用xshell上传)。利用linux命令 tar -zxvf apache-tom

Tomcat服务详解

一、部署Tomcat服务器 JDK安装官方网址:https://www.oracle.com/cn/java Tomcat安装官方网址:Apache Tomcat® - Welcome! 安装JDK 1.获取安装包wget https://download.oracle.com/otn/java/jdk/8u411-b09/43d62d619be4e416215729597d70b8ac

龙芯小本8089b安装debian7+java+tomcat+mysql

之前团购了一个龙芯小本8089b,cpu很差劲,内存也只有1G,根本不能用来娱乐,于是想把它换个纯字符系统,然后搭建java服务器平台,用作局域网固定的mini服务器开发用。 以下是我搭建过程,当然实际比这做的多,这是多次尝试之后的成功过程,分享给大家,自己也做个笔记 debian7纯字符系统安装龙芯专有java安装tomcat安装mysql安装 一、debian7安装参考 圣域☆

eclipse中,更新JDK之后,启动Tomcat报错:

更新到这个版本之后,启动Tomcat报错: 四月 25, 2016 10:13:20 上午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent INFO: The APR based Apache Tomcat Native library which allows optimal performance in prod

在Eclipse环境下修改Tomcat编码的问题

问题: 由于BMS需要设置UTF-8编码,要不就会出现中文乱码问题; 一、项目保持UTF-8格式; 二、由于可能会多次移除项目、加载项目,不想每次都要修改tmp0\conf 原因: 如果在eclipse中配置了tomcat后,其实,tomcat所用的所有tomcat配置文件,都不是catalina_home/config下面的xml文件,而是在eclipse所创建的Serve

Eclipse发布Maven项目到tomcat,无法加载到lib文件夹下的jar包

BMS 解决方法: 当我们发布web项目到tomcat时,访问地址时会报一个classnotfound的错误,但是eclipse中的项目中都已经添加了相应的类,有一种比较容易犯的错误是,你没有把额外所需的jar包加到tomcat中的lib文件夹中,在这里介绍一种在项目中直接添加jar包到lib目录下:  右键已创建的web项目——properties属性——点击Deployment Assem