Tomcat源码解析(六):HttpConnector和HttpProcessor的异步工作机制

本文详细介绍了Tomcat中HttpConnector和HttpProcessor如何实现异步工作机制。HttpConnector等待请求,分配HttpProcessor处理,然后继续等待下一个请求;HttpProcessor获取Socket后进行请求处理,完成后返回空闲队列,实现线程间的协同处理,达到异步效果。

HttpConnector请求处理分工如下:

1、ServerSocket等待接受Http请求连接;

2、请求到达,从HttpProcessor处理池获取处理对象;

3、委托给HttpProcessor具体处理请求;

4、当前HttpConnector继续等得下一个Http请求;


具体HttpConnector和HttpProcessor如何实现异步工作机制?

HttpConnector和HttpProcessor两者都实现Runnable接口,并且两者本身运行在自身线程中。

这里我们称HttpConnector实例中run方法所在线程为连接器线程;而HttpProcessor实例中run方法所在线程为处理器线程。


首先看下HttpConnector对应连接器线程的run方法,主要工作:

1、阻塞等待Http请求;
2、为每个请求分配一个HttpProcessor对象;
3、调用HttpProcessor的process()方法处理;

 	public void run() {
        // 循环,直到shutdown
        while (!stopped) {
        	// 监听socket
            Socket socket = serverSocket.accept();

            // 为socket分配处理器
            HttpProcessor processor = createProcessor();
            // 如果当前没有空闲处理器
			if(processor == null) {
				// 忽略请求,不做处理
			}
            // 执行处理
            processor.assign(socket);
        }
	}
HttpConnector中run方法所在连接器线程进入HttpProcessor对象的assign()方法,如下:

    synchronized void assign(Socket socket) {

        // 等待前一个socket被Processor获取,Processor获取后会调用totify唤醒当前线程,
        // 然后当前线程把socket赋给Processor全局socket
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        // 当前最新socket赋值给全局变量,并唤醒processor等待线程(等待socket)
        this.socket = socket;
        available = true;
        // 唤醒处理器线程
        notifyAll();
    }
此处变量available表示当前HttpProcessor对象中是否存在一个新的Socket套接字连接(也即是否有新的请求),初始available为false,表示初始没有socket连接。

assign程序流分两种情况:

1、当前available=false(表示当前HttpProcessor对象中不存在新的Socket可以获取),无需等待,直接将当前HttpConnector传递过来的最新socket传给HttpProcessor,

     同时设置available=true(表示当前HttpProcessor对象中存在新的Socket需要处理),唤醒处理器线程(之前处理器线程阻塞等待新的Socket到达);

2、当前available=true(表示当前HttpProcessor对象中存在未处理的新Socket),则wait方法会阻塞,直到HttpProcessor处理器线程获取前一个新的Socket,并通知我唤            醒,之后再进行第一步处理。

不管是情况1还是情况2,HttpConnector实例对应的连接器线程进去assign方法后,阻塞等待,之后负责把socket传给HttpProcessor,之后则直接返回,也就是并没有等待请求处理完毕再返回,HttpProcessor对应的处理器线程继续处理请求,而HttpConnector对应的连接器线程则继续等待下一个Http请求,此时便是异步实现的方式。


接下来看下HttpProcessor对应处理器线程的run方法,主要工作:、

1、await()会阻塞等待,直到HttpConnector对应连接器线程将新的socket传给HttpProcessor全局变量,并唤醒当前处理器线程;

2、获取新的socket之后,调用process()进行实际请求处理;

3、处理完毕后将当前自身处理器线程放入空闲队列中;

	public void run() {
		
        while (!stopped) {
            // 阻塞等待,直到下一个新的socket被赋值给全局变量
            Socket socket = await();
            if (socket == null)
                continue;

            // Process the request from this socket
            try {
                process(socket);
            } catch (Throwable t) {
                log("process.invoke", t);
            }

            // 放入空闲处理器池中
            connector.recycle(this);

        }
    }
看下await()方法,await()方法主要阻塞等待,直到HttpConnector对应线程将新的socket传给HttpProcessor全局变量,并唤醒通知我新的Socket已经到达。

此时await()将全局新的socket获取过来,并标志available为false,表示新的socket已经获取,没有新的socket了,notifalAll()告知HttpConnector又可以传新的socket进来。

    private synchronized Socket await() {

        // 等待被唤醒,唤醒者为connector线程
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        Socket socket = this.socket;
        available = false;
        // 通知已经获取最新socket,下一个socket可以赋值进来
        notifyAll();
        
        return (socket);
    }
虽然assign()方法和await()方法都属于HttpProcessor实例的方法,但是两者被不同线程所调用执行,assign()由HttpConnector中run方法所在线程调用,而await()由HttpProcessor中run方法所在线程调用。两者通过共享变量available实现协同工作,并通过全局socket变量来进行数据传输工作。


两者线程的程序流如下:







评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值