作者回复: 1,说的对,能用组合就不用继承,这里我感觉Tomcat设计者考虑的是通过多层继承来尽量重用一些通用的逻辑。另外I/O模型和应用层协议的个数也是可控的,用户可以在server.xml中直接指定想要的连接器类型:比如Http11NioProtocol和Http11Nio2Protocol。
2,这里的考虑是,如果连接器直接创建ServletRequest和ServletResponse对象的话,就和Servlet协议耦合了,设计者认为连接器尽量保持独立性,它不一定要跟Servlet容器工作的。另外对象转化的性能消耗还是比较少的,Tomcat对HTTP请求体采取了延迟解析的策略,也就是说,TomcatRequest对象转化成ServletRequest的时候,请求体的内容都还没读取呢,直到容器处理这个请求的时候才读取的。
作者回复: 1)软件系统本质是对信息的处理,要跟踪信息在流动过程中的经过的关键环节,并在这些地方下断点,看看变量的值是什么。比如你可以在业务代码中下个断点,看看调用栈,看Tomcat和Spring是怎么调到你的代码的,然后在这个调用栈中的关键函数里上下都看看,先熟悉个大概,然后带着问题去深入调试。
2)你可以把Netty理解成Tomcat中的连接器,它们都负责网络通信,都利用了Java NIO非阻塞特性。但Netty素以高性能高并发著称,为什么Tomcat不把连接器替换成Netty呢?第一个原因是Tomcat的连接器性能已经足够好了,同样是Java NIO编程,套路都差不多。第二个原因是Tomcat做为Web容器,需要考虑到Servlet规范,Servlet规范规定了对HTTP Body的读写是阻塞的,因此即使用到了Netty,也不能充分发挥它的优势。所以Netty一般用在非HTTP协议和Servlet的场景下。
作者回复: 理解正确👍
作者回复: 阻塞和非阻塞说的是线程发起IO操作时,如果数据没有就绪,线程是否挂起。
同步异步说的是,应用程序与内核交互时,数据从内核空间到用户空间的拷贝,是内核主动发起还是由应用程序来触发,14篇会详细介绍。
这里的accept调用,当连接请求未到时,应用线程会挂起,因此是阻塞的,但为什么又说NIO是非阻塞呢?这是因为读取数据的线程没有挂起,因为之前已经通过Selector侦测到数据已经准备好了,到了内核空间,数据读取线程不需要等待,不需要挂起去等待数据。
作者回复: Nginx/Apche一般做反向代理和处理静态HTML资源,做的事情相对来说简单,KPI就是要快,因此用C语言实现,直接调用操作系统API,充分利用操作系统的高级特性。
而Tomcat用来处理动态请求,还需要跑Java应用,因此用Java实现,因此”快“不是它主要的KPI。Java调用操作系统API要通过JNI,无形中有性能损耗。另外Tomcat通过使用Apache APR本地库来做I/O通信,性能已经跟Apache、Nginx接近了。
作者回复: 抓主线,抓主干,每个系统中都有一个关键的核心类,紧紧抓住这些类,先不要分散,在逐步看旁枝,等你学习弄明白一个经典的系统,很多套路你就明白了。
作者回复: 谢谢😄
作者回复: 对的
作者回复: 一个Service中可以部署多个项目呢,一个连接器对应一个监听端口,不是一个请求,一个端口上可以接收多个请求。
作者回复: Tomcat在I/O模型和线程模型方面跟Netty很相似,后面会详细分析。
作者回复: 是的
作者回复: I/O是外部设备和主存之间拷贝数据的过程,I/O模型是实现这个过程的方式,后面会详细介绍各种I/O模型的区别:同步阻塞,同步非阻塞、异步等等。
作者回复: 发送方是先http数据生成后tcp发送,接收方先tcp接收,再http解析
作者回复: 可以的,在server.xml配置多个service,或者同一个service里配置多个connector
作者回复: 1.对的,默认是一个service
2.容器就是装载Servlet的箱子,Tomcat的容器分层次,大箱子里有小箱子,最大的箱子是Engine,下一篇会讲到。
作者回复: 不是的,一个连接器对应一个监听端口,比如一扇门,一个web应用是一个业务部门,进了这个门后你可以到各个业务部门去办事。
作者回复: unix环境高级编程里相关章节有详细介绍,这个专栏也会图文并貌分析,你有没有发现这个专栏的内容其实蛮容易懂的😊
作者回复: 😑后面还会有整体架构图。