阅读TOMCAT 8源码(一)

阅读TOMCAT 8源码(一)

了解TOMCAT工作主体流程

  • 启动
  • 监听端口
  • 创建线程

tomcat 是通过socket服务及多线程来构建容器的,并通过java的nio来获取请求数据并写回返回数据

1、启动

启动是在网上阅读其它前辈的笔记的,目前学习源码感觉找源头比较痛苦,TOMCAT还好,有一个统计一的源码入口,其它的框架类感觉不太好找,有好的方法同学请不吝赐教
TOMCAT的启动类型是Bootstrap开始,这个类有一个main方法,使用Debug方式阅读每行代码的运行。
这个类许多都是做了初始化操作,具体关注StandradContext(很多基本服务都是存在该实例内或由这个实例窗口提供 ),NioeEndPoint类主要处理请求服务及分发。
启动时会做许多初始化的操作,比如实例化NioEndPoint、线程池等

2、网络

TOMCAT本身还是以SOCKET来监听网络端口的请求,他创建一个ServerSocket来绑定端口号,并通过while(true)来监听请求,所有的请求都是监听端口,并获取端口的通过数据。
TOMCAT默认通过ServerSocket来监听8080端口,用一个单独的NioEndPoint.Acceptor 线程来监听ServerSocket.accept(),当有请求时,NioEndPoint.Poller 线程会用一个标签死循环来监听请求通道是否有数据,如果有的话就会处理,创建一个SocketProcess线程来处理这个请求,该线程是使用线程池来处理,在NioEndPoint类内,使用了3个内部线程类(Acceptor,Poller,SocketProcessor)用于处理请求。NioEndPoint.Acceptor类专门用于监听服务端口请求。NioEndPoint.Poller用于获取请求数据,Poller其实用的是一个poller数组(2个元素)用于处理线程,tomcat默认的线程池处理数所有的请求,所以tomcat的并发极限默认也是200,Poller获取到请求通道后,执行SocketProcess线程,并通过线程池执行这个线程。

3、线程

在tomcat中用的最多 的就是多线程及nio,所有的请求及监听都是用多线程,所有的数据获取及返回都是用的nio。线程的集中处理都是NioEndPoint中,可以重点看这个类,处理逻辑中网络一节中有说明。获取数据都是用nio,获取到的请求都是用tomcat的Request类来构造,这个类实现了HttpServletRequest,并构造Response类,该类实现了HttpServletResponse,构造完请求后,及返回类后,调用servlet的service方法,并返回response的执行状态码,通过由代码根据结果的不同状态码生成对应的HTML界面。
Request的SessionID,不是一开始生成 的,而是在获取的时候生成,用的也JAVA本身SecureRandom来生成,并通过缓存判断是否与历史重复,重复再重新生成.

Poller监听Socket请求通道,处理Socket通道 是通过一个2个元素大小的数组

 public void run() {
            // Loop until destroy() is called
            while (true) {
                try {
                    // Loop if endpoint is paused
                    while (paused && (!close) ) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            // Ignore
                        }
                    }

                    boolean hasEvents = false;

                    // Time to terminate?
                    if (close) {
                        events();
                        timeout(0, false);
                        try {
                            selector.close();
                        } catch (IOException ioe) {
                            log.error(sm.getString(
                                    "endpoint.nio.selectorCloseFail"), ioe);
                        }
                        break;
                    } else {
                        hasEvents = events();
                    }
                    try {
                        if ( !close ) {
                            if (wakeupCounter.getAndSet(-1) > 0) {
                                //if we are here, means we have other stuff to do
                                //do a non blocking select
                                keyCount = selector.selectNow();
                            } else {
                                keyCount = selector.select(selectorTimeout);
                            }
                            wakeupCounter.set(0);
                        }
                        if (close) {
                            events();
                            timeout(0, false);
                            try {
                                selector.close();
                            } catch (IOException ioe) {
                                log.error(sm.getString(
                                        "endpoint.nio.selectorCloseFail"), ioe);
                            }
                            break;
                        }
                    } catch (Throwable x) {
                        ExceptionUtils.handleThrowable(x);
                        log.error("",x);
                        continue;
                    }
                    //either we timed out or we woke up, process events first
                    if ( keyCount == 0 ) hasEvents = (hasEvents | events());

                    Iterator<SelectionKey> iterator =
                        keyCount > 0 ? selector.selectedKeys().iterator() : null;
                    // Walk through the collection of ready keys and dispatch
                    // any active event.
                    while (iterator != null && iterator.hasNext()) {
                        SelectionKey sk = iterator.next();
                        KeyAttachment attachment = (KeyAttachment)sk.attachment();
                        // Attachment may be null if another thread has called
                        // cancelledKey()
                        if (attachment == null) {
                            iterator.remove();
                        } else {
                            attachment.access();
                            iterator.remove();
                            processKey(sk, attachment);
                        }
                    }//while

                    //process timeouts
                    timeout(keyCount,hasEvents);
                    if ( oomParachute > 0 && oomParachuteData == null ) checkParachute();
                } catch (OutOfMemoryError oom) {
                    try {
                        oomParachuteData = null;
                        releaseCaches();
                        log.error("", oom);
                    }catch ( Throwable oomt ) {
                        try {
                            System.err.println(oomParachuteMsg);
                            oomt.printStackTrace();
                        }catch (Throwable letsHopeWeDontGetHere){
                            ExceptionUtils.handleThrowable(letsHopeWeDontGetHere);
                        }
                    }
                }
            }//while

            stopLatch.countDown();
        }

SocketProcess线程处理请求,由线程池运行

protected boolean processSocket(KeyAttachment attachment, SocketStatus status, boolean dispatch) {
        try {
            if (attachment == null) {
                return false;
            }
            SocketProcessor sc = processorCache.pop();
            if ( sc == null ) sc = new SocketProcessor(attachment, status);
            else sc.reset(attachment, status);
            Executor executor = getExecutor();
            if (dispatch && executor != null) {
                executor.execute(sc);
            } else {
                sc.run();
            }
        } catch (RejectedExecutionException ree) {
            log.warn(sm.getString("endpoint.executor.fail", attachment.getSocket()), ree);
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            log.error(sm.getString("endpoint.process.fail"), t);
            return false;
        }
        return true;
    }

说明

第一阶段了解了TOMCAT内部的运行,对于配置文件 的加载及会话区别还未仔细看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值