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

深入剖析TOMCAT

程序员文章站 2022-03-22 16:45:03
...

TOMCAT


深入剖析TOMCAT

深入剖析TOMCAT

容器分类

Engine:整个CatalinaServlet引擎

Host:包含一个或者多个Context容器的虚拟主机

Context:web应用容器,可以有多个wrapper

Wrapper:粒度最小的容器,没有子容器

相关组件:载入器,管道,映射器等


请求响应流程

HttpConnector -->serverSocket.accept()-->HttpConnector.start--HttpConnector.run-->createProcessor()--> HttpProcessor.process(socket)-->解析填充req,res()-->connector.getContainer().invoke(request, response)-->容器.invoke-->(new SimplePipelineValveContext()).invokeNext--> valves[subscript].invoke-->basic.invoke-->HttpProcessor.process(socket).finishResponse;

 


生命周期

Lifecyle接口

public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public void start() throws LifecycleException;
public void stop() throws LifecycleException;

LifecycleEvent

LifecycleListener

LifecycleSupport

容器实现Lifecyle接口 可以调用addLifecycleListener(LifecycleListener listener)增加监听器至LifecycleSupport.LifecycleListener[],容器重写start,stop方法实现逻辑(对容器,子容器进行启动,关闭),同时发送事件告知监听器,监听器实现具体逻辑。

((Lifecycle) context).addLifecycleListener(listener);
LifecycleSupport.fireLifecycleEvent(BEFORE_START_EVENT, null);
LifecycleListener.lifecycleEvent(LifecycleEvent event) {

日志收集

Logger<--LoggerBase

public static final int FATAL = Integer.MIN_VALUE;
public static final int ERROR = 1;
public static final int WARNING = 2;
public static final int INFORMATION = 3;
public static final int DEBUG = 4;
public Container getContainer();
public void setContainer(Container container);
public String getInfo();
public int getVerbosity();
public void setVerbosity(int verbosity);
public void addPropertyChangeListener(PropertyChangeListener listener);
public void log(String message);
public void log(Exception exception, String msg);
public void log(String message, Throwable throwable);
public void log(String message, int verbosity);
public void log(String message, Throwable throwable, int verbosity);
public void removePropertyChangeListener(PropertyChangeListener listener);

FileLogger

SystemErrLogger

SystemOutLogger

载入器

loader

public ClassLoader getClassLoader();
public Container getContainer();
public void setContainer(Container container);
public DefaultContext getDefaultContext();
public void setDefaultContext(DefaultContext defaultContext);
public boolean getDelegate();
public void setDelegate(boolean delegate);
public String getInfo();
public boolean getReloadable();
public void setReloadable(boolean reloadable);
public void addPropertyChangeListener(PropertyChangeListener listener);
public void addRepository(String repository);
public String[] findRepositories();
public boolean modified();
public void removePropertyChangeListener(PropertyChangeListener listener);

Session管理

Request#getSession()-->this.doGetSession(true):session.getSession()--> context.getManager()-->manager.createSession(sessionId):manager.findSession(this.requestedSessionId)

安全性

Realm领域对象

public Container getContainer();
public void setContainer(Container container);
public String getInfo();
public void addPropertyChangeListener(PropertyChangeListener listener);
public Principal authenticate(String username, String credentials);
public Principal authenticate(String username, byte[] credentials);
public Principal authenticate(String username, String digest,
                              String nonce, String nc, String cnonce,
                              String qop, String realm,
                              String md5a2);
public Principal authenticate(X509Certificate certs[]);
public boolean hasRole(Principal principal, String role);
public void removePropertyChangeListener(PropertyChangeListener listener);

class GenericPrincipal implements Principal

public GenericPrincipal(Realm realm, String name, String password) {
    this(realm, name, password, null);
}
public GenericPrincipal(Realm realm, String name, String password, List roles) {
    super();
    this.realm = realm;
    this.name = name;
    this.password = password;
    if (roles != null) {
        this.roles = new String[roles.size()];
        this.roles = (String[]) roles.toArray(this.roles);
        if (this.roles.length > 0)
            Arrays.sort(this.roles);
    }
}

LoginConfig

TOMCAT启动读取web.xml,如果包含Login-Config元素的配置,会创建loginconfig对象并设置对于属性加入验证阀

Authenticator

System.setProperty("catalina.base", System.getProperty("user.dir"));
Connector connector = new HttpConnector();
Wrapper wrapper1 = new SimpleWrapper();
wrapper1.setName("Primitive");
wrapper1.setServletClass("PrimitiveServlet");
Wrapper wrapper2 = new SimpleWrapper();
wrapper2.setName("Modern");
wrapper2.setServletClass("ModernServlet");

Context context = new StandardContext();
// StandardContext's start method adds a default mapper
context.setPath("/myApp");
context.setDocBase("myApp");
LifecycleListener listener = new SimpleContextConfig();
((Lifecycle) context).addLifecycleListener(listener);

context.addChild(wrapper1);
context.addChild(wrapper2);
// for simplicity, we don't add a valve, but you can add
// valves to context or wrapper just as you did in Chapter 6

Loader loader = new WebappLoader();
context.setLoader(loader);
// context.addServletMapping(pattern, name);
context.addServletMapping("/Primitive", "Primitive");
context.addServletMapping("/Modern", "Modern");
// add ContextConfig. This listener is important because it configures
// StandardContext (sets configured to true), otherwise StandardContext
// won't start

// add constraint
SecurityCollection securityCollection = new SecurityCollection();
securityCollection.addPattern("/");
securityCollection.addMethod("GET");

SecurityConstraint constraint = new SecurityConstraint();
constraint.addCollection(securityCollection);
constraint.addAuthRole("manager");
LoginConfig loginConfig = new LoginConfig();
loginConfig.setRealmName("Simple User Database Realm");
// add realm
Realm realm = new SimpleUserDatabaseRealm();
((SimpleUserDatabaseRealm) realm).createDatabase("conf/tomcat-users.xml");
context.setRealm(realm);
context.addConstraint(constraint);
context.setLoginConfig(loginConfig);

connector.setContainer(context);

try {
  connector.initialize();
  ((Lifecycle) connector).start();
  ((Lifecycle) context).start();

  // make the application wait until we press a key.
  System.in.read();
  ((Lifecycle) context).stop();
}
catch (Exception e) {
  e.printStackTrace();
}

StandardWrapper

singleThreadModel (STM)

servlet类可以继承STM接口,保证同一时间只有一个线程访问该servlet实例的service的方法,为了提高性能 servlet容器会创建多个servlet实例并发执行service,如service方法里面依赖外部资源,应该考虑可能引起同步问题

StandardWrapper

维护一个STM实例池 根据servlet完全限定名动态载入Servlet类,Servlet的service()是由StandardWrapperValue调用

public Servlet allocate() throws ServletException {
...
servlet.init(ServletConfig servletConfig)
}

ServletConfig

public interface ServletConfig {
String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
}

StandardWrapperFacade

包装类

StandardWrapperValue

StandardWrapper实例的基础阀:
1.执行与该servlet关联的所以过滤阀
2.执行servlet实例的service方法
为完成上述操作StandardWrapperValue.invoke还会执行下面操作
1.servlet = wrapper.allocate();
2.ApplicationFilterChain filterChain =createFilterChain(request, servlet);
3.调用过滤链的doFilte()方法,其中包括servlet实例的service方法
4.释放过滤链
6.若该service类不会被使用到,调用wrapper.unload( 5.wrapper.deallocate()
);

ApplicationFilterChain implements FilterChain

 public void doFilter(ServletRequest request, ServletResponse response)
    throws IOException, ServletException {}

ApplicationFilterConfig implements FilterConfig

 org.apache.catalina.core.StandardContext#start#filterStart#ApplicationFilterConfig(Context context, FilterDef filterDef)

 public ApplicationFilterConfig(Context context, FilterDef filterDef)
    throws ClassCastException, ClassNotFoundException,
           IllegalAccessException, InstantiationException,
           ServletException {
    super();
    this.context = context;
    setFilterDef(filterDef);
}

FilterDef

StandardContext

...

Host 和 Engine

 class StandardHost extends ContainerBase implements Deployer, Host{

 }

public class StandardEngine extends ContainerBase implements Engine {}

服务器组件和服务组件

public interface Server {
    public String getInfo();
    public NamingResources getGlobalNamingResources();
    public void setGlobalNamingResources
    (NamingResources globalNamingResources);
    public int getPort();
    public void setPort(int port);
    public String getShutdown();
    public void setShutdown(String shutdown);
    public void addService(Service service);
    public void await();
    public Service findService(String name);
    public Service[] findServices();
    public void removeService(Service service);
    public void initialize()
throws LifecycleException;
}


public interface Service {
    public Container getContainer();
    public void setContainer(Container container);
    public String getInfo();
    public String getName();
    public void setName(String name);
    public Server getServer();
    public void setServer(Server server);
    public void addConnector(Connector connector);
    public Connector[] findConnectors();
    public void removeConnector(Connector connector);
    public void initialize()
throws LifecycleException;

}

Digester库

通过编写servlet.XML配置Tomcat,web.xml配置servlet/jsp引用,TOMCAT解析web.xml,基于web.xml配置 context对象,Disester库提供了支持

public final class ContextConfig implements LifecycleListener {
    private static Digester webDigester = createWebDigester();

    lifecycleEvent(){
    ...
    if (event.getType().equals(Lifecycle.START_EVENT))
        start();
    else if (event.getType().equals(Lifecycle.STOP_EVENT))
        stop();   
    }
    start() {
    ...
    defaultConfig();//处理DefaultWebXml = "conf/web.xml"
    applicationConfig();/WEB-INF/web.xml
    }
}

关闭钩子

    Runtime.getRuntime().addShutdownHook(Thread hook);
====================================================================
    //tomcat的关闭钩子
    protected class CatalinaShutdownHook extends Thread {
    public void run() {
        if (server != null) {
            try {
                ((Lifecycle) server).stop();
            } catch (LifecycleException e) {
                System.out.println("Catalina.stop: " + e);
                e.printStackTrace(System.out);
                if (e.getThrowable() != null) {
                    System.out.println("----- Root Cause -----");
                    e.getThrowable().printStackTrace(System.out);
                }
            }
        }
    }
}

TOMCAT启动

Catalinna

    (new Catalina()).process(args)

    public void process(String args[]) {
    setCatalinaHome();
    setCatalinaBase();
    try {
        if (arguments(args))
            execute();
    } catch (Exception e) {
        e.printStackTrace(System.out);
    }
}

protected void execute() throws Exception {
    if (starting)
        start();
    else if (stopping)
        stop();

}

server.await();

Bootstrap

启动TOMCAT的入口类之一。运行startup.bat或者startup.sh文件上时候,实际上调用了该类的main()方法。main方法会创建3个类在入侵,并实例化Catalina类。然后他调用Catalina实例的process方法

HostConfig

public class HostConfig
implements LifecycleListener, Runnable {
    public void lifecycleEvent(LifecycleEvent event) {

    // Identify the host we are associated with
    try {
        host = (Host) event.getLifecycle();
        if (host instanceof StandardHost) {
            int hostDebug = ((StandardHost) host).getDebug();
            if (hostDebug > this.debug) {
                this.debug = hostDebug;
            }
            setDeployXML(((StandardHost) host).isDeployXML());
            setLiveDeploy(((StandardHost) host).getLiveDeploy());
            setUnpackWARs(((StandardHost) host).isUnpackWARs());
        }
    } catch (ClassCastException e) {
        log(sm.getString("hostConfig.cce", event.getLifecycle()), e);
        return;
    }

    // Process the event that has occurred
    if (event.getType().equals(Lifecycle.START_EVENT))
        start();
    else if (event.getType().equals(Lifecycle.STOP_EVENT))
        stop();

}

    protected void start() {

    if (debug >= 1)
        log(sm.getString("hostConfig.start"));

    if (host.getAutoDeploy()) {
        deployApps();
    }

    if (isLiveDeploy()) {
    //动态部署
        threadStart();
    }

}
    protected void deployApps() {
    if (!(host instanceof Deployer))
        return;
    if (debug >= 1)
        log(sm.getString("hostConfig.deploying"));

    File appBase = appBase();
    if (!appBase.exists() || !appBase.isDirectory())
        return;
    String files[] = appBase.list();
    //部署描述符
    deployDescriptors(appBase, files);
    //部署WAR
    deployWARs(appBase, files);
    //部署目录
    deployDirectories(appBase, files);
}
}

Deployer 部署器接口

public interface Deployer  {
    public static final String PRE_INSTALL_EVENT = "pre-install";
    public static final String INSTALL_EVENT = "install";
    public static final String REMOVE_EVENT = "remove";
    public String getName();
    public void install(String contextPath, URL war) throws IOException;
    public void install(URL config, URL war) throws IOException;
    public Context findDeployedApp(String contextPath);
    public String[] findDeployedApps();
    public void remove(String contextPath) throws IOException;
    public void start(String contextPath) throws IOException;
    public void stop(String contextPath) throws IOException;
}

StandardHost

    private Deployer deployer = new StandardHostDeployer(this);

StandardHostDeployer

start(String contextPath)
stop(String contextPath)
install(String contextPath, URL war)
install(URL config, URL war)

Manager应用程序的servlet类

管理已部署的应用程序

JMX管理资源

=============================================================================================

深入剖析TOMCAT深入剖析TOMCAT深入剖析TOMCAT深入剖析TOMCAT深入剖析TOMCAT深入剖析TOMCAT深入剖析TOMCAT深入剖析TOMCAT

相关标签: tomcat