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)的内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值