欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

tomcat 系列一 整体架构

程序员文章站 2022-07-14 11:26:00
...

tomcat 整体的架构

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的关系图
tomcat 系列一 整体架构
通过conf/server.xml文件也可以看出组件之间的关系
tomcat 系列一 整体架构

Connector架构

tomcat 系列一 整体架构
connector 通过ProtocolHandler来处理请求的,不同类型的ProtocolHandler来处理不同类型的请求

tomcat 系列一 整体架构
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()
tomcat 系列一 整体架构


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的总体架构
tomcat 系列一 整体架构
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(管道和阀门)来实现的运用了责任链的设计默认

tomcat 系列一 整体架构
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的整体架构就说完了,附带了少部分源码,便于大家通过源码来理解