第一章Tomcat

1.1 Tomcat源码及架构

1.2 Tomcat一些问题

1.3 Tomcat调优

1.1 Tomcat源码及架构

简易版Tomcat
Class Tomcat{
Connector connector;
List container;
}
整体上Tomcat由connector和container组成

第一步
从serlvet入口开始,servlet是一种规范
public class yunyunHttpServlet extends HttpServlet{
doGet(HttpServletRequest request, HttpServletResponse response)
}
其中HttpServletRequest和HttpServletResponse都是接口,这些接口需要实现类实现

当我们使用Tomcat时,则会使用Tomcat来实现这两个接口。
Tomcat会使用RequestFacade类和Request两个实现类实现这两个接口

Tomcat的两个Request类用了门面模式,开发者只能调用Request提供的方法,不能修改底层实现

第二步
那么yunyunHttpServlet 类下servlet这两个接口是如何知道调用Tomcat的Request类来实现呢

首先我们要知道war包和jar包的区别
本质上两者没有区别
规定Tomcat识别webapps下war包才能当成应用程序部署,否则必须在指定地方放入jar包才能识别

Tomcat部署有四种方式,其中可以通过war包达成Tomcat部署
然后Tomcat才知道从哪里读取文件

在war包下会有很多class文件和xml(class文件和名称映射)
比如有

	<servlet>
		<servlet-name>yunyunHttpServlet</servlet-name>
		<servlet-class>com.woaiyunyun.yunyunHttpServlet</~>
	</servlet>
	<servlet-mapping>
		<servlet-name>yunyunHttpServlet</~>
		<url-pattern>/yunyunHttp</~>
	</~>

因为配置过了映射关系,当我们调用yunyunHttpServlet下doGet方法,则会调用Tomcat具体实现类

第三步
那么Tomcat的request的实现类底层又是如何实现的呢

在这里插入图片描述

Connector:
当数据从操作系统传入进来时候,我们上文所说Tomcat两大快Connector下Endpoint
会根据名字如Http1.1,AJP/1.3等等来决定用哪个NIO/BIO等等来读取数据

其中在通过socket获取data用到了线程池,线程池大小也是我们后面可以调优的参数

在Connector下解析中就是对Tomcat request接口实现类的不断赋值,然后传递给你Container容器

Container:
在容器下以责任链模式,每层都是一个可以自定义实现的管道。每层管道都可以进行一层处理到下一个管道,比如每个管道记录日志

Engine – 主机管理引擎
Host – 主机
Context – 应用
Wrapper – 封装多个Servlet
Servlet – 应用下一个程序

其中Tomcat本身只会调用service方法,当Http请求是get则只需doGet方法,doPost
是Servlet规范写好的
简单例子责任链模式

class HTMLFilter implements Filter{
	@Override
	Public boolean service(Request request, Response response, FilterChain chain){
		1.	处理request(doGet)
		2.	递归chain.doFilter
		3.	处理response(doPost)
	}
}

责任链模式先稍微提及,在后面讲23种设计模式章节具体讲
就此tomcat执行完毕

1.2 Tomcat一些问题

1 Tomcat有安全管理器
A有权限,B无权限时候
AccessController.doPrivileged方法给B调用A中权限方法

\bin > startup.bat -security 安全管理机制运行tomcat

2 热加载和热部署的区别

热部署是Tomcat默认打开,热加载需要手动打开
热部署在服务器运行时重新部署项目。

热加载在运行时重新加载class。

热加载监控web-inf下class等变化
Web-inf下lib下jar包有无增加删除(比如通过class文件修改时间比较来判断)

3 Tomcat类加载器

为什么Tomcat下每个应用都会先走自己的类加载器?
因为不同应用可能有相同的名字的类,但是功能却不同    

Context下类加载器
	第一步:在缓存map中找想加载的class的路径path(key: xxx.className, value: class对线的路径)
	第二步: 如果map没有,看JVM是否加载过(JVM本地方法)
	第三步:查看是否开启委托父类中找设置,如果开启直接父类加载器中找
			如果未开启就自己路径下找并map缓存,如果仍没找到则走父类加载器

4 Tomcat如何实现异步servlet
走到Wrapper管道时,调用service后会封装一个AsyncContext对象,该对线封装了request和response方法,之后线程池就回收此线程了,用client自己线程池来真正处理这个这个context对象,完成业务逻辑后再通知tomcat已处理完成,然后tomcat对该对象再回收或关闭连接

1.3 Tomcat调优

1
配置项-----------------------------------默认-----------------建议
Connection Timeout-----------------20s------------------减少
(连接超时时间)

maxThreds-----------------------------200-----------------增加(不是越大越好)
(处理连接最大线程数,吞吐量)

acceptCount(backlog) --------------100 ----------------增加
(操作系统中接受请求的数量限制)

MaxConnections----------------------nio 1万------------不变
(Tomcat中接受请求数量限制,当Tomcat限制满了则会放入OS下acceptCount中)

2
线程线程数量
Windows下 maxThread = acceptCount + MaxConnections
Linux下 maxThread = TCPQueue(不可控一般不管) + acceptCount + MaxConnections

3
Linux下配置参数,不断调试启动项目,看运行情况 java -jar demo.jar -server tomcat.maxConnection=xxx …

Linux下ps看CPU利用率等

可用Jmeter程序调优,启动该程序,输入IP Port即可测试
Jmeter下看Http请求状态,吞吐量等

4
调maxConnections情况
当maxThread > maxConnections时, maxConnections应稍大于MaxThreads

调acceptCount情况
一般不改,在OS层面不可控因素大
Tomcat默认100, linux默认128

调maxThreads情况(调优核心)
理想线程数量= (1+code block time/code execute time)*cpu数量
实际是跑代码,压测下调试,不断调线程数将CPU利用率控制在百分之80-90之间,当CPU利用率超过百分之90则增加maxThreads

原创文章 5 获赞 5 访问量 289

猜你喜欢

转载自blog.csdn.net/weixin_40503364/article/details/106169027