tomcat建立连接

参考资料: Tomcat7.0源码分析——请求原理分析(上)


servlet应用放入tomcat中启动后就可以接受请求,那在tomcat中是怎么实现的呢?


1、ProtocolHandler接口是真正处理请求的地方,这个接口是在Connector中初始化的。在Connector中有两个方法用来初始化和启动ProtocolHandler

    @Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();
        // 构造Adapter对象,Adapter用来适配不同的网络协议
        adapter = new CoyoteAdapter(this);
        protocolHandler.setAdapter(adapter);
        if (null == parseBodyMethodsSet) {
            setParseBodyMethods(getParseBodyMethods());
        }
        try {
            // 初始化ProtocolHandler,ProtocolHandler用来处理请求
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
        }
        // 初始化MapperListener,MapperListener注册host
        mapperListener.init();
    }

    @Override
    protected void startInternal() throws LifecycleException {
        if (getPort() < 0) {
            throw new LifecycleException(sm.getString("coyoteConnector.invalidPort", Integer.valueOf(getPort())));
        }
        // 设置Connector已经启动
        setState(LifecycleState.STARTING);
        try {
            // 启动protocolHandler
            protocolHandler.start();
        } catch (Exception e) {
            String errPrefix = "";
            if (this.service != null) {
                errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
            }
            throw new LifecycleException(errPrefix + " " + sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
        }
        // 启动MapperListener
        mapperListener.start();
    }


2、我们来看看初始化ProtocolHandler的方法,ProtocolHandler默认使用Http11Protocol实例化,Http11Protocol直接继承了AbstractProtocol的init方法。

    @Override
    public void init() throws Exception {
        if (getLog().isInfoEnabled()) {
            getLog().info(sm.getString("abstractProtocolHandler.init", getName()));
        }
        if (oname == null) {
            oname = createObjectName();
            if (oname != null) {
                Registry.getRegistry(null, null).registerComponent(this, oname, null);
            }
        }
        if (this.domain != null) {
            try {
                tpOname = new ObjectName(domain + ":type=ThreadPool,name=" + getName());
                Registry.getRegistry(null, null).registerComponent(endpoint, tpOname, null);
            } catch (Exception e) {
                getLog().error(sm.getString("abstractProtocolHandler.mbeanRegistrationFailed", tpOname, getName()), e);
            }
            rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName());
            Registry.getRegistry(null, null).registerComponent(getHandler().getGlobal(), rgOname, null);
        }
        String endpointName = getName();
        endpoint.setName(endpointName.substring(1, endpointName.length() - 1));
        try {
            // 重点是这个方法,JIoEndpoint做为初始化的实现,创建服务器socket
            endpoint.init();
        } catch (Exception ex) {
            getLog().error(sm.getString("abstractProtocolHandler.initError",
                    getName()), ex);
            throw ex;
        }
    }



3、JioEndpoint创建socket的方法

    @Override
    public void bind() throws Exception {
        // 初始化接受请求线程数量
        if (acceptorThreadCount == 0) {
            acceptorThreadCount = 1;
        }
        // 初始化socket最大连接数
        if (getMaxConnections() == 0) {
            setMaxConnections(getMaxThreads());
        }
        if (serverSocketFactory == null) {
            if (isSSLEnabled()) {
                // 创建Socket工厂
                serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this);
            } else {
                serverSocketFactory = new DefaultServerSocketFactory(this);
            }
        }
        if (serverSocket == null) {
            try {
                if (getAddress() == null) {
                    // 创建服务器socket
                    serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog());
                } else {
                    serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress());
                }
            } catch (BindException orig) {
                String msg;
                if (getAddress() == null)
                    msg = orig.getMessage() + " <null>:" + getPort();
                else
                    msg = orig.getMessage() + getAddress().toString() + ":" + getPort();
                BindException be = new BindException(msg);
                be.initCause(orig);
                throw be;
            }
        }
    }



4、现在我们的服务端socket已经创建好了,接下来启动这个socket,启动和初始化相似, Http11Protocol直接继承了 AbstractProtocol的start方法。

    @Override
    public void start() throws Exception {
        if (getLog().isInfoEnabled())
            getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
        try {
            // 还是交给JIoEndpoint来启动
            endpoint.start();
        } catch (Exception ex) {
            getLog().error(sm.getString("abstractProtocolHandler.startError", getName()), ex);
            throw ex;
        }
    }


5、JioEndpoint启动socket的方法

    @Override
    public void startInternal() throws Exception {
        if (!running) {
            running = true;
            paused = false;
            if (getExecutor() == null) {
                // 初始化线程池
                createExecutor();
            }
            // 设置最大连接数,超过阻塞线程
            initializeConnectionLatch();
            // 启动接受请求的线程
            startAcceptorThreads();
            // 启动链接超时的线程
            Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout");
            timeoutThread.setPriority(threadPriority);
            timeoutThread.setDaemon(true);
            timeoutThread.start();
        }
    }


6、初始化线程池

    public void createExecutor() {
        internalExecutor = true;
        // 创建任务队列
        TaskQueue taskqueue = new TaskQueue();
        // 创建线程工厂
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
        // 初始化线程池
        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        // 任务队列使用线程池产生
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }


7、启动接受请求的线程

    protected final void startAcceptorThreads() {
        // 创建一个线程数组
        int count = getAcceptorThreadCount();
        acceptors = new Acceptor[count];
        for (int i = 0; i < count; i++) {
            // 实例化线程类
            acceptors[i] = createAcceptor();
            //  使用Thread 启动
            Thread t = new Thread(acceptors[i], getName() + "-Acceptor-" + i);
            t.setPriority(getAcceptorThreadPriority());
            t.setDaemon(getDaemon());
            t.start();
        }
    }


8、接受请求的线程类

    protected class Acceptor extends AbstractEndpoint.Acceptor {

        @Override
        public void run() {
            int errorDelay = 0;
            // 无限循环直接接受到shutdown后退出
            while (running) {
                // 收到线程暂停的命令后暂停50ms
                while (paused && running) {
                    state = AcceptorState.PAUSED;
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                    }
                }
                if (!running) {
                    break;
                }
                state = AcceptorState.RUNNING;
                try {
                    // 达到了最大连接数,线程阻塞
                    countUpOrAwaitConnection();
                    Socket socket = null;
                    try {
                        // 从服务端socket接受链接
                        socket = serverSocketFactory.acceptSocket(serverSocket);
                    } catch (IOException ioe) {
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        throw ioe;
                    }
                    errorDelay = 0;
                    if (running && !paused && setSocketOptions(socket)) {
                        if (!processSocket(socket)) {
                            closeSocket(socket);
                        }
                    } else {
                        closeSocket(socket);
                    }
                } catch (IOException x) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), x);
                    }
                } catch (NullPointerException npe) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), npe);
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }
    }


到此为止,请求和服务器之间的链接已经建立好了。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值