作者回复: 名字里带有Acceptor的线程负责接收浏览器的连接请求。
名字里带有Poller的线程,其实内部是个Selector,负责侦测IO事件。
名字里带有Catalina-exec的是工作线程,负责处理请求。
名字里带有 Catalina-utility的是Tomcat中的工具线程,主要是干杂活,比如在后台定期检查Session是否过期、定期检查Web应用是否更新(热部署热加载)、检查异步Servlet的连接是否过期等等。
作者回复: 如果业务处理时间过长,阻塞大量Tomcat线程导致线程饥饿,可以考虑异步Servlet,这样Tomcat线程立即返回,耗时处理由业务线程来处理。
但业务线程同样有线程阻塞的问题,比如阻塞在IO上。基本思路都是用“异步回调”来避免阻塞,采用异步非阻塞IO模型,用少量线程通过事件循环来提高吞吐量。Spring给出的方案是Spring Webflux。Nodejs也是这样,适合IO密集型的应用。
协程也是这个思路,并且它的网络通信也是通过epoll来实现非阻塞的,只不过它向开发者提供了“同步阻塞”式的API,另外协程的上下文切换开销也比线程小,因为它将“函数调用上下文”保存在应用层面,内核感觉不到,但是这需要额外的内存、调度和管理开销。
作者回复: Connector组件中持有ProtocolHandler和Processor实例,这算是静态的依赖关系;而Connector将请求解析出来后交给Container处理,这是动态的协作关系。说的有点咬文嚼字:)
作者回复: 对的尤其是接下来的文章会深入细节,我会贴出关键代码和分析,但课后最好也去读读相关源码。
作者回复: 默认情况下是一个Connector一个线程池,你还可以在server.xml中配置一个全局线程池,还可以指定线程名字的前缀:
<Service name="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
作者回复: 对的
作者回复: 建议还是不要折腾Ant编译了,直接用内嵌式方式启动和调试。
作者回复: file.encoding设成utf-8能解决输入数据乱码的问题,说明你的操作系统的默认字符集不是utf-8。
log4j乱码需要看看log4j的配置文件里的配置的字符集是不是utf-8,还需要看看日志文件本身的格式是不是utf-8。
作者回复:
一个请求到来,Tomcat会创建一个SocketProccessor,这是个runnable,会被扔到线程池执行。
在执行过程中,会创建一个Request对象,一个Response对象,和一个Http11Processor对象(AbstractProcessor的子类)。
一次请求处理完了,这些对象会被回收保存起来,重复使用(对象池技术)。
建议看第14篇,有详细过程。