《HowTomcatWorks》读书笔记_第四章(未完成)

4 篇文章 0 订阅
4 篇文章 0 订阅

简介

第四章相比与第三章最大的区别在于HttpConnector和HttpProcessor是一对多的关系,这使得这个版本的服务器可以同时处理多个http请求。

  • Bootstrap
  • HttpConnector:
    • 负责创建Request、Response和ServerSocket
    • 连接器和容器一对一关系,连接器和处理器一对多关系
    • 实现LifeCycle接口,在第六章详细介绍,新增部分
  • HttpProcessor
  • HttpRequestImpl
  • HttpResponseImpl
  • SimpleContainer

核心源码

后面的章节组件功能会逐渐复杂起来,因此只会挑出一部分源码来进行注释讲解

Bootstrap

public final class Bootstrap {
  public static void main(String[] args) {
    HttpConnector connector = new HttpConnector();
    SimpleContainer container = new SimpleContainer();
    connector.setContainer(container);
    try {
      // 初始化HttpConnector
      connector.initialize();
      // 启动HttpConnector
      connector.start();

      // make the application wait until we press any key.
      System.in.read();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

HttpConnector

public class HttpConnector implements Connector, Lifecycle, Runnable {
	// HttpConnector是否初始化
    private boolean initialized = false;
	// 简单的容器,为下一章做铺垫
    protected Container container = null;
	// HttpConnector是否启动
    private boolean started = false;
	// HttpConnector是否停止
    private boolean stopped = false;
	// 后台线程,用来执行HttpConnector的run方法
    private Thread thread = null;
	// 后台线程名称
    private String threadName = null;
	// 锁
    private Object threadSync = new Object();
	// 请求对象
    private HttpRequestImpl request = null;
	// 响应对象
    private HttpResponseImpl response = null;
	// 已被创建但没有被使用的HttpProcessor的集合
    private Stack processors = new Stack();
	// 已被创建的HttpProcessor
    private Vector created = new Vector();
	// 最小HttpProcessor数量
    protected int minProcessors = 5;
	// 最大HttpProcessor数量
    private int maxProcessors = 20;
    // 当前已创建的HttpProcessor的数量
    private int curProcessors = 0;
    // 初始化HttpConnector(ServerSocket在此创建)
    public void initialize() throws LifecycleException {
        if (initialized) {
			throw new LifecycleException (sm.getString("httpConnector.alreadyInitialized"));
		}

        this.initialized=true;
        Exception eRethrow = null;

        // open方法内部使用了工厂模式创建了ServerSocket
        try {
            serverSocket = open();
        } catch (Exception e) {
            // 此处省略
        	...
        } 

        if ( eRethrow != null )
            throw new LifecycleException(threadName + ".open", eRethrow);

    }

	// 开始处理Http请求
    public void start() throws LifecycleException {
        if (started)
            throw new LifecycleException
                (sm.getString("httpConnector.alreadyStarted"));
        threadName = "HttpConnector[" + port + "]";
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // 启动后台线程(执行run方法)
        threadStart();

        // 创建指定的最小数量的HttpProcessor
        while (curProcessors < minProcessors) {
            if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
                break;
            // new一个新的HttpProcessor
            HttpProcessor processor = newProcessor();
            // todo: 疑问, newProcessor会启动创建的Processor啊
            // 初始化的HttpProcessor先放入未使用的HttpProcessor集合中(回收)
            recycle(processor);
        }

    }

    private void threadStart() {
        log(sm.getString("httpConnector.starting"));
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.start();
    }

    void recycle(HttpProcessor processor) {
        processors.push(processor);
    }

	// new一个HttpProcessor, 没报错的情况下一定会new一个新的HttpProcessor
	//(区别于createProcessor()方法)
    private HttpProcessor newProcessor() {
        HttpProcessor processor = new HttpProcessor(this, curProcessors++);
        if (processor instanceof Lifecycle) {
            try {
                ((Lifecycle) processor).start();
            } catch (LifecycleException e) {
                log("newProcessor", e);
                return (null);
            }
        }
        // 放入已创建的HttpProcessor集合中
        created.addElement(processor);
        return (processor);
    }

	// 后台线程启动后执行该方法
    public void run() {
        // 循环,直到收到shutdown指令
        while (!stopped) {
            Socket socket = null;
            try {
            	// 
                socket = serverSocket.accept();
                if (connectionTimeout > 0)
                    socket.setSoTimeout(connectionTimeout);
                socket.setTcpNoDelay(tcpNoDelay);
            } catch (AccessControlException ace) {
                // 省略
                ...
                continue;
            }

            // 给一个请求创建一个HttpProcessor,
            HttpProcessor processor = createProcessor();
            if (processor == null) {
                try {
                    log(sm.getString("httpConnector.noProcessor"));
                    socket.close();
                } catch (IOException e) {
                    ;
                }
                continue;
            }
            // 将socket传入HttpProcessor线程
            processor.assign(socket);
        }

        synchronized (threadSync) {
            threadSync.notifyAll();
        }

    }

	// 返回一个可用的HttpProcessor,如果HttpProcessor数量达到最大值且都在使用中,返回null
	// 没有可用的HttpProcessor时会忽略客户端的请求
    private HttpProcessor createProcessor() {
        synchronized (processors) {
            if (processors.size() > 0) {
                return ((HttpProcessor) processors.pop());
            }
            if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {
                return (newProcessor());
            } else {
                if (maxProcessors < 0) {
                    return (newProcessor());
                } else {
                    return (null);
                }
            }
        }
    }

    /**
     * Create (or allocate) and return a Request object suitable for
     * specifying the contents of a Request to the responsible Container.
     */
    public Request createRequest() {
        HttpRequestImpl request = new HttpRequestImpl();
        request.setConnector(this);
        return (request);
    }

    /**
     * Create (or allocate) and return a Response object suitable for
     * receiving the contents of a Response from the responsible Container.
     */
    public Response createResponse() {
        HttpResponseImpl response = new HttpResponseImpl();
        response.setConnector(this);
        return (response);
    }

	// 其它省略
	...
}

HttpConnector主要工作流程:

  1. 创建服务器套接字;
  2. 池化思想:维护了HttpProcessor对象池,一个HttpProcessor负责一个http请求;
  3. 从对象池获取一个可用的HttpProcessor,将Socket传给HttpProcessor,让HttpProcessor处理具体的请求;

HttpProcessor

final class HttpProcessor implements Lifecycle, Runnable {

    public HttpProcessor(HttpConnector connector, int id) {

        super();
        this.connector = connector;
        this.debug = connector.getDebug();
        this.id = id;
        this.proxyName = connector.getProxyName();
        this.proxyPort = connector.getProxyPort();
        this.request = (HttpRequestImpl) connector.createRequest();
        this.response = (HttpResponseImpl) connector.createResponse();
        this.serverPort = connector.getPort();
        this.threadName =
          "HttpProcessor[" + connector.getPort() + "][" + id + "]";

    }
	// 是否有可用的Socket,默认为false
    private boolean available = false;
	// 和HttpProcessor关联的HttpConnector
    private HttpConnector connector = null;
    private HttpRequestImpl request = null;
    private HttpResponseImpl response = null;
    
	private Socket socket = null;
	// HttpProcessor是否启动
    private boolean started = false;
    // 后台线程
    private Thread thread = null;
    // 后台线程是否被停止
	private boolean stopped = false;
	// 后台线程名称
    private String threadName = null;
	// 锁对象
    private Object threadSync = new Object();

    private synchronized Socket await() {

        // 等待HttpConnector提供一个新的Socket
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
		// 将HttpConnector传入的Socket赋值给成员变量
        Socket socket = this.socket;
        available = false;
        // 通知HttpConnector我们已经接收到了这个Socket
        notifyAll();

        if ((debug >= 1) && (socket != null))
            log("  The incoming request has been awaited");
            
        return (socket);
    }	

    synchronized void assign(Socket socket) {

        // Wait for the Processor to get the previous Socket
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        // Store the newly available Socket and notify our thread
        this.socket = socket;
        available = true;
        notifyAll();

        if ((debug >= 1) && (socket != null))
            log(" An incoming request is being assigned");
    }

    public void run() {
        while (!stopped) {
			// 阻塞,等待HttpConnector传入Socket
			// 在HttpConnector中调用processor.assign(socket),传入待处理请求的Socket后
			// await方法才返回,后续调用process去处理请求
			// 这里可以看出,只有调用了assign方法的HttpProcessor才被视为已使用的
			// 而刚启动的HttpProcessor不能被视为已使用的
			// 所以启动HttpProcessor时调用recycle方法,就没有什么问题了
            Socket socket = await();
            if (socket == null)
                continue; 
            try {
            	// 处理请求
                process(socket);
            } catch (Throwable t) {
                log("process.invoke", t);
            }
            // 处理完请求后,回收当前的HttpProcessor
            connector.recycle(this);
        }
        // Tell threadStop() we have shut ourselves down successfully
        synchronized (threadSync) {
            threadSync.notifyAll();
        }
    }

	// 启动后台线程
    public void start() throws LifecycleException {
        if (started)
            throw new LifecycleException
                (sm.getString("httpProcessor.alreadyStarted"));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;
        
        threadStart();
    }
    
    private void threadStart() {
        log(sm.getString("httpConnector.starting"));
		// 传入HttpConnector,启动后调用run方法
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.start();
    }
    
	// 停止后台线程
    public void stop() throws LifecycleException {
        if (!started)
            throw new LifecycleException
                (sm.getString("httpProcessor.notStarted"));
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        threadStop();
    }

    private void threadStop() {
        log(sm.getString("httpProcessor.stopping"));
        stopped = true;
        assign(null);
        if (status != Constants.PROCESSOR_IDLE) {
            // Only wait if the processor is actually processing a command
            synchronized (threadSync) {
                try {
                    threadSync.wait(5000);
                } catch (InterruptedException e) {
                    ;
                }
            }
        }
        thread = null;
    }

	// 构造request和response请求
	private void process(Socket socket) {
		// 1.解析连接
		...
		// 2.解析请求
		...
		// 3.解析请求头
		...
        // 将构造好的request和response对象传给container,调用container的invoke方法
        try {
			// 省略
			...
            if (ok) {
                connector.getContainer().invoke(request, response);
            }
        } catch (Exception e) {
			// 省略
			...
 		}
	}
}

SimpleContainer

public class SimpleContainer implements Container {

  public static final String WEB_ROOT =
    System.getProperty("user.dir") + File.separator  + "webroot";

  public SimpleContainer() {
  }

  public void invoke(Request request, Response response)
    throws IOException, ServletException {

    String servletName = ( (HttpServletRequest) request).getRequestURI();
    servletName = servletName.substring(servletName.lastIndexOf("/") + 1);
    URLClassLoader loader = null;
    try {
      URL[] urls = new URL[1];
      URLStreamHandler streamHandler = null;
      File classPath = new File(WEB_ROOT);
      String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;
      urls[0] = new URL(null, repository, streamHandler);
      loader = new URLClassLoader(urls);
    }
    catch (IOException e) {
      System.out.println(e.toString() );
    }
    Class myClass = null;
    try {
      myClass = loader.loadClass(servletName);
    }
    catch (ClassNotFoundException e) {
      System.out.println(e.toString());
    }

    Servlet servlet = null;

    try {
      servlet = (Servlet) myClass.newInstance();
      servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
    }
    catch (Exception e) {
      System.out.println(e.toString());
    }
    catch (Throwable e) {
      System.out.println(e.toString());
    }
  }
	// 省略其他未实现的方法
	...
}

UML类图

图片从《How Tomcat Works》一书中截取

默认连接器

在这里插入图片描述

Request接口和相关实现类

在这里插入图片描述

Response接口和相关实现类

在这里插入图片描述

流程图

运行程序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值