`
zddava
  • 浏览: 240465 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Tomcat请求处理(二) -- 请求处理框架

阅读更多
书接上文。

当Tomcat的Acceptor监听到有请求到来时,就会结束阻塞,继续进行程序下面的动作。如下面的代码所示:

		public void run() {
			while (running) {

				while (paused) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}

				try {
					// 开始监听端口
					Socket socket = serverSocketFactory.acceptSocket(serverSocket);
					// 初始化Socket
					serverSocketFactory.initSocket(socket);
					// 处理Socket
					if (!processSocket(socket)) {
						try {
							socket.close();
						} catch (IOException e) {
						}
					}
				} catch (IOException x) {
					if (running)
						log.error(sm.getString("endpoint.accept.fail"), x);
				} catch (Throwable t) {
					log.error(sm.getString("endpoint.accept.fail"), t);
				}
			}

		}


结束阻塞后,首先是Socket的初始化,由于ServerSocketFactory的实现类DefaultServerSocketFactory并没有扩展initSocket()方法,所以这一步其实是什么都没做的。

接下来程序执行到了processSocket(socket);这一步了,这个方法的源代码如下所示:

	protected boolean processSocket(Socket socket) {
		try {
			if (executor == null) {
				// 得到一个Work并为它分配这个Socket
				getWorkerThread().assign(socket);
			} else {
				executor.execute(new SocketProcessor(socket));
			}
		} catch (Throwable t) {
			log.error(sm.getString("endpoint.process.fail"), t);
			return false;
		}
		return true;
	}


executor是一个外部的基于线程池的执行器,先不去考虑它,重点看一下getWorkerThread()和Worker#assign()

getWorkerThread()的源代码如下:


	protected Worker getWorkerThread() {
		// 获取一个Worker
		Worker workerThread = createWorkerThread();
		while (workerThread == null) {// 如果获取的Worker为Null
			try {
				synchronized (workers) {
					// 等待workers里边Worker的回收,recycleWorkerThread()中会调用notify通知这个线程结束等待的
					workers.wait();
				}
			} catch (InterruptedException e) {
			}
			// 等待结束,再次获取一个Worker
			workerThread = createWorkerThread();
		}
		return workerThread;
	}


这里这个createWorkerThread()也就是获取Worker的方法值得研究一下。

	protected Worker createWorkerThread() {
		synchronized (workers) {
			if (workers.size() > 0) {// 如果堆栈中有剩余的Worker
				// 当前在使用的Worker线程计数
				curThreadsBusy++;
				// 将一个Worker推出堆栈
				return workers.pop();
			}
			// 如果堆栈中没有多余的Worker了,那么创建一个。
			if ((maxThreads > 0) && (curThreads < maxThreads)) {
				// 如果maxThreads有定义,并且当前的Worker数量小于这个值。
				// 在recycleWorkerThread()中会将新创建的Worker放入堆栈的
				curThreadsBusy++;
				return (newWorkerThread());
			} else {
				if (maxThreads < 0) {
					// maxThreads没有定义,可以有无限个Worker的情况。
					curThreadsBusy++;
					return (newWorkerThread());
				} else {
					return (null);
				}
			}
		}

	}


而newWorkerThread()方法还是很好理解的:

	protected Worker newWorkerThread() {
		Worker workerThread = new Worker();
		workerThread.start();
		return (workerThread);

	}


创建一个Worker线程,并且开启线程。

经过上述的过程,就获得了一个Worker(并且已经开始运行了),那么程序的下一步是调用Worker的assign()方法:

	synchronized void assign(Socket socket) {
		// 等待获取完上一个Socket
		while (available) {
			try {
				wait();
			} catch (InterruptedException e) {
			}
		}
		
		// 保存新的Socket
		this.socket = socket;
		available = true;
		notifyAll();
	}


这样新的Worker已经有一个Socket对象去处理了,下面来看一下Worker的线程中做了哪些工作。

	public void run() {

		// 知道收到停止信号,否则一直循环
		while (running) {
			// 等待为这个线程设置一个Socket对象
			Socket socket = await();
			if (socket == null)
				continue;

			// 处理请求
			if (!setSocketOptions(socket) || !handler.process(socket)) {
				// 关闭Socket
				try {
					socket.close();
				} catch (IOException e) {
				}
			}

			// 回收Worker
			socket = null;
			recycleWorkerThread(this);

		}

	}


其中await()用于等待有Socket对象赋给当前的Worker已进行请求处理,代码如下:

		private synchronized Socket await() {

			// 等待获取Socket
			while (!available) {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}

			// Socket已经收到
			Socket socket = this.socket;
			available = false;

			// 这个notifyAll()是通知assign()中的等待Socket的处理已经开始了,
			// 可以为这个Worker赋新的值了。
			notifyAll();

			return (socket);

		}


而setSocketOptions()用于设定一些Socket的参数,如下所示:

	protected boolean setSocketOptions(Socket socket) {
		int step = 1;
		try {

			if (soLinger >= 0) {
				socket.setSoLinger(true, soLinger);
			}
			if (tcpNoDelay) {
				socket.setTcpNoDelay(tcpNoDelay);
			}
			if (soTimeout > 0) {
				socket.setSoTimeout(soTimeout);
			}

			step = 2;
			serverSocketFactory.handshake(socket);

		} catch (Throwable t) {
			if (log.isDebugEnabled()) {
				if (step == 2) {
					log.debug(sm.getString("endpoint.err.handshake"), t);
				} else {
					log.debug(sm.getString("endpoint.err.unexpected"), t);
				}
			}
			return false;
		}
		return true;
	}


handler.process(socket)封装了处理请求的全过程,下次再详细了解

而最后的recycleWorkerThread()用于回收Worker到堆栈中以备下次使用:

	protected void recycleWorkerThread(Worker workerThread) {
		synchronized (workers) {
			workers.push(workerThread);
			curThreadsBusy--;
			workers.notify();
		}
	}


好了,请求处理的整个流程大致就是这样的,下次再详细了解请求的真实处理部分,就是handler.process(socket)的内容。
分享到:
评论

相关推荐

    urlrewritefilter-4.0.3.jar

    这是urlrewritefilter-4.0.3.jar下载,通过java的Filter过滤器对URL进行重写,用户得到的全部都是经过处理后的URL静态地址,本质上通过伪地址进行页面跳转。 软件介绍 urlrewritefilter-4.0.3.jar是有时候项目中的...

    apache-tomcat-7.0.82.rar

    Apache Tomcat是一款基于Java的Web应用程序服务器,用于处理Java Servlet和JavaServer Pages(JSP)等动态Web内容的请求和响应。在Java Web开发中,Tomcat是广泛应用的Web容器之一。 Apache Tomcat 7.0.82是Tomcat ...

    1个Nginx+2个tomcat+2个redis服务器(主从复制)实现反向代理,实现动静分离。 - 张相逢的博客 - CSDN博客收藏20200109-134106.html

    1个Nginx+2个tomcat+2个redis服务器(主从复制)实现反向代理,实现动静分离。 - 张相逢的博客 - CSDN博客 Nginx的个人理解 - fly1056601582的博客 - CSDN博客 Redis 集合(Set)_redis教程 mysql、zookeeper、redis和...

    实习新项目-基于SSM+vue实现的智慧校园服务平台后端源码+数据库+项目说明.zip

    后负责返回请求处理及返回 【使用技术】 - 脚手架:Vue-cli (Vue2) - UI组件:Element-UI+View UI - 后端框架:SSM(spring、springMVC、mybatis) - 后端服务器:Tomcat - 数据库:Mysql - 接口测试:Postman - ...

    JSP_MVC架构

    适合初学者,整个系统采用MVC架构,并对Servlet进行了轻量级的封装,构建了一套基于请求驱动的MVC框架,项目所有功能基于该MVC框架开发, 项目部署为apache 分发多个Tomcat的方式,数据库设置采用MySql 提供有4中...

    基于SpringBoot框架搭建的物联网数据采集系统服务器端(源码+项目说明).zip

    * 默认请求路径 http://localhost:8080/ 8080为SpringBoot内置Tomcat端口,可在application.yml文件中修改。 * 以下所有API除测试、用户相关的/login、/info、/exit之外,都会被登录拦截器所拦截,调用其他API需要...

    仿网易新闻客户端源码+服务器

    3,如何利用框架去请求网络,如何缓存数据,如何加载图片 4,如何解决事件的传递引发的问题 5,如何自定义PullToRefreshListView控件 6,补间动画,属性的动画的使用 7,首页轮播图的实现,导航页的实现 8,如何实现...

    基于YMP框架实现的简单HTTP请求透传代理模块.rar

    为了让YMP框架能够在Android环境中使用,本次更新已支持编码方式初始化框架各模块;并针对Serv服务端提供会话管理器,用于管理已连接的TCP或UDP客户端会话以及对会话空闲检测、流量监听等; 新版本已提交至Maven...

    用javascript硬编码方式和jquery框架方式完成ajax异步请求

    用javascript硬编码方式和jquery框架方式完成ajax异步请求的示例,不包括源码。直接访问方式是,可以直接在tomcat启动后访问helloAjaxDemo.jsp或是helloJQueryAjaxDemo.jsp。比如:...

    2020年SpringMVC面试题,看这篇就足够了

    SpringMVC是一种基于 Java 的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring框架的一个模块。 它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程...

    入门案例-SpringMVC技术架构图

    Spring MVC是Spring提供的构建Web应用程序的框架,该框架遵循了Servlet规范,负责接收并处理Servelt容器传递的请求,并将响应写回Response。Spring MVC以DispatcherServlet为核心,众多组件如HandlerMapping为辅助,...

    SSM框架+redis+druid事务控制+定时任务介绍+sql脚本+测试说明及请求路径

    SSM框架+redis+druid事务控制+定时任务介绍+sql脚本+测试说明及请求路径,内涵redis免安装文件,txt文档说明,我用的是myeclipse2014+tomcat8配置启动的

    javaweb--ssm框架基础

    个人收集网络上的javaweb开发基础知识,整理成的新手PPT,欢迎各位指正。并附有知识点原文链接 ...Tomcat JSP JSP编译 JSP隐式对象 SSM spring springMVC Mybatis 目录结构(Maven项目) Annotation

    ajax异步请求演示

    用javascript硬编码方式和jquery框架方式完成ajax异步请求的示例源码。直接访问方式是,可以直接在tomcat启动后访问helloAjaxDemo.jsp或是helloJQueryAjaxDemo.jsp。

    javaWeb实现的超市管理系统

    未使用ssm框架,使用javaweb,tomcat,vue,element-ui实现的超市管理系统。 超市管理系统是一套为超市工作人员提供的用于对超市工作人员的信息管理,商品信息管理,商品采购管理和商品销售管理的信息系统。 采用...

    基于ssm的网咖服务系统

    使用 idea 编辑器开发,使用 Java-maven 管理项目,使用 SSM 框架,在异步处理上使用了 Dwr框架,并采用 Quartz 框架来定时完成指定任务,tomcat 服务器,数据库使用Mysql。灵活使用 dwr做到前端与后台的信息交互,...

    基于Java智慧校园云端管理系统的设计和实现源码(毕设源码).zip

    | Axios | Ajax请求工具 | 后端 | 技术 | 说明 | | ------------ | ------------------- | | Java | 面向对象高级语言 | | SpringBoot | 微服务开发框架 | | Mybatis Plus | 持久层框架 | | Swagger2 | API接口...

    tomcat 环境下使用quercus运行php程序简单demo -登陆验证

    代码可以放在 tomcat 环境下运行(放到 tomcat 安装目录下启动 tomcat 即可),也可以用eclipse 打开,项目用 easyui 做前段框架,使用 php 做后台开发,请求用 的ajax,数据库使用 MySQL 5.6 。项目压缩包里包含 sql...

    基于SSM框架的高并发电子商务平台设计与实现_吴倩.pdf

    后端使用高性能服务器Tomcat处理用户请求,形成分布式系统;数据存储采用MySQL数据库,持久存储用户数据;同时利用Lucence和Solr完成网站搜索功能。此外,还利用基于用户的协同过滤算法实现该电商平台的推荐功能。本文...

    初识SpringMVC以及springmvc基本应用入门案例彩色PPT版本.pptx

    定义处理请求的功能类(UserServlet) 设置请求映射(配置映射关系) 使用SpringMVC技术开发web程序流程 创建web工程(Maven结构) 设置tomcat服务器,加载web工程(tomcat插件) 导入坐标(SpringMVC+Servlet) ...

Global site tag (gtag.js) - Google Analytics