tomcat 整体的架构
tomcat是实现了Servlet规范的一个容器.最顶层的容器是server,一个Tomcat只能有一个server
tomcat通过service对外提供服务,service比作一个家庭这个家庭的核心就是connector container,多个connector对应一个container.
connector container两个组件就是tomcat整个架构的心脏.
Connector 作用
用于接收客户端的请求,底层通过socket技术监听特定的端口,来接收请求并将请求按照一定的编码(默认UTF-8) 通信协议 http协议
tcp/ip 协议等,来封装 request response.最后将请求传递给Container.
Container作用
封装管理servlet处理request的请求.Container内部也是风层级的最外层是依次 Engine Host Context Warpper
connnector 和container的关系图
通过conf/server.xml文件也可以看出组件之间的关系
Connector架构
connector 通过ProtocolHandler来处理请求的,不同类型的ProtocolHandler来处理不同类型的请求
ProtocolHandler由三个主要的部件构成 Endpoint Processor Adapter 请求的处理也是依靠三个完成的,可以从AbstractProtocol的部分源码看出来
//ProtocolHandler 主要构件
public abstract class AbstractProtocol<S> implements ProtocolHandler,
MBeanRegistration {
private final AbstractEndpoint<S> endpoint;
protected Adapter adapter;
@Override
public void setAdapter(Adapter adapter) { this.adapter = adapter; }
@Override
public Adapter getAdapter() { return adapter; }
public void addWaitingProcessor(Processor processor) {
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractProtocol.waitingProcessor.add", processor));
}
waitingProcessors.add(processor);
}
public void removeWaitingProcessor(Processor processor) {
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractProtocol.waitingProcessor.remove", processor));
}
waitingProcessors.remove(processor);
}
下面再看一下这个三个组件分别有什么作用
Endpoint 底层用的socket技术,监听到请求并将请求传递给Processor.
Endpoint 通过其内部类Acceptor来实现这个功能,Acceptor 是实现了Runable 重写了run()
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
// 内部类 Acceptor是一个线程 用来接收连接的
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
....
try {
//if we have reached max connections, wait
countUpOrAwaitConnection();
SocketChannel socket = null;
try {
//监听请求的链接
socket = serverSock.accept();
} catch (IOException ioe) {
// We didn't get a socket
countDownConnection();
if (running) {
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
} else {
break;
}
}
....
}
Processor接受Endpoint 并把封装request response
//Processor 接收请求 创建Request Response
public abstract class AbstractProcessor extends AbstractProcessorLight implements ActionHook {
public AbstractProcessor(AbstractEndpoint<?> endpoint) {
this(endpoint, new Request(), new Response());
}
}
Adapter 执行service方法 将请求传递到Container容器中.
CoyoteAdapter 是Adapter 唯一的实现类,所有的功能都是在这个类中实现的.
public class CoyoteAdapter implements Adapter {
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
throws Exception {
...
try {
// Parse and set Catalina and configuration specific
// request parameters
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//设置异步的支持
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
//调用容器处理请求 以管道的形式执行
connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);
}
...
}
}
Container的架构
首先看一下container的总体架构
Engine 引擎,一个service只能有一个engine,用来管理多个站点
Host:站点 也可以叫做虚拟主机
Context 一个应用
wrapper 每个Wrapper 封装一个Servlet
这四个容器都是自己的标准实现StandardXXXX
public final class StandardServer extends LifecycleMBeanBase implements Server
public class StandardService extends LifecycleMBeanBase implements Service
public class StandardEngine extends ContainerBase implements Engine
public class StandardHost extends ContainerBase implements Host
public class StandardContext extends ContainerBase implements Context, NotificationEmitter
public class StandardWrapper extends ContainerBase implements ServletConfig, Wrapper, NotificationEmitter
public abstract class ContainerBase extends LifecycleMBeanBase implements Container
每个容器都继承ContainerBase ContainerBase 继承 LifecycleMBeanBase
最终的基类就是 Lifecycle 通过监听器模式 tomcat 就可以管理各个容器的生命周期.
Container中请求的处理是通过Pipeline和Valve(管道和阀门)来实现的运用了责任链的设计默认
StandardPipeline 是管道的标准实现 用来管理各种valve阀门
public class StandardPipeline extends LifecycleBase
implements Pipeline, Contained {
@Override
public void addValve(Valve valve) {
// Validate that we can add this Valve
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
// Start the new component if necessary
if (getState().isAvailable()) {
if (valve instanceof Lifecycle) {
try {
((Lifecycle) valve).start();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.valve.start"), e);
}
}
}
// Add this Valve to the set associated with this Pipeline
if (first == null) {
first = valve;
valve.setNext(basic);
} else {
Valve current = first;
while (current != null) {
if (current.getNext() == basic) {
current.setNext(valve);
valve.setNext(basic);
break;
}
current = current.getNext();
}
}
container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
}
@Override
public Valve[] getValves() {
List<Valve> valveList = new ArrayList<>();
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
valveList.add(current);
current = current.getNext();
}
return valveList.toArray(new Valve[0]);
}
}
标准阀门的实现 只有一个invoke(),执行本阀门的invoke并调用管道内下一个阀门的invoke
final class StandardEngineValve extends ValveBase {
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
}
final class StandardContextValve extends ValveBase {
private static final StringManager sm = StringManager.getManager(StandardContextValve.class);
public StandardContextValve() {
super(true);
}
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Disallow any direct access to resources under WEB-INF or META-INF
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Acknowledge the request
try {
response.sendAcknowledgement();
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}
}
到这里tomcat的整体架构就说完了,附带了少部分源码,便于大家通过源码来理解
欢迎大家关注我的微信公众号 您的关注就是我不懈的动力