Tomcat 工作原理解析

Tomcat整体工作流程

1、启动阶段

  • 扫描webapp目录下的所有子目录和子文件,然后把这个目录下的 .class 文件挑选出来,拿到每个java类的类路径,拿到类路径之后通过class.forName()方法(反射)去获取 Class 类信息;
  • 在拿到所有的java类Class类信息之后会 for循环遍历每一个Class类信息,然后从Class类信息里去获取注解信息,拿到注解信息之后看哪些java的类信息里面有@WebServlet注解,把这些java文件挑选出来,挑选出来之后,通过newInstance() 生成类的实例
  • 生成servlet实例的时候,又进一步通过方法的实例拿到了它里面的 method实例,method实例里面挑选出 doGet 和 doPost实例,同时上面也拿到了注解里的路径值,然后把它们放到了 hashMap 中,其中 key值就是注解里的路径,value值就是对象实例信息。除了method实例,servlet实例也存在hashMap中,method实例和servlet实例对应的key值都是注解的路径。

2、请求转发阶段

  • tomcat负责接收来自网络的请求,tomcat 是通过socket监听端口(这里用的是netty框架中的socket);
  • tomcat 借助socket拿到http请求后并不是立即开启线程处理的,而是把它放入线程池
    • 在这为什么使用线程池呢?主要有以下几个原因:
      1、如果没有线程池,而是每个请求来了之后立刻开启线程对请求进行处理,如果一瞬间来上千个请求的话,会瞬间开启很多线程把内存完全消耗,导致服务器死机。线程池在过多请求来的时候会把请求打到队列中,而不是立刻开启线程执行。根据线程池原理,如果队列满了还可以执行饱和策略,过多的请求不在处理,不会导致服务器宕机。
      2、如果没有线程池,每个请求来了都要新建线程,线程执行完毕后销毁。随着请求的不断到来,会不断的有线程的新建和销毁,线程的新建和销毁都是有巨大的开销的,这种开销是毫秒级的。每个方法的执行实际上是一个个栈帧入栈的过程,方法的执行完毕是出栈的过程。线程的创建和申请伴随着栈空间的申请和回收,而它的回收并不是立刻回收的而是批量回收的,它的回收频率和回收次数是由java控制的。因为立刻回收会占用大量 CPU资源,会影响其他线程性能。如果不立即回收就得每隔一段时间回收,意味着回收前会堆积大量线程栈垃圾,尤其在高并发场景下垃圾会更多。这种垃圾会占用大量内存,进而影响到整体性能。所以我们应该尽可能避免线程的新建和销毁,所以我们就考虑如何在已申请的栈空间上进行资源重复利用,线程池能让线程不会被销毁,通过读源码发现线程池里的线程 run()方法里是有死循环的,它会循环从队列里获取任务,所以线程池可以重复利用线程,大幅提升了多线程性能。
  • 把通过端口传过来的 http字符信息封装成 httpRequest 对象和 httpResponce对象,同时提取出请求的 URL ,把URL中的 ip、端口、项目名字去掉剩下的就是要请求的servlet地址或前端地址。如果请求的是前端资源那么会根据请求路径去相应的目录下找前端文件,之后按照相应的编码读取里面的字符串返回给前端;如果请求的是servlet 那么会根据URL去之前启动阶段的 hashMap里匹配 servlet实例和 method对象,提取出来之后执行代理。Tomcat通过invoke()方法完成了 servlet的调用。(doGet() 和doPost() 方法都是void方法没有返回值)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值