Tomcat源码分析(五) -- Server

293 阅读4分钟

Tomcat中的 Server

  • Server 是一个接口
  • Server 的实现类是 StandardServer,我们直接看 StandardServer 类
  • Server 接口继承了 Lifecycle 接口,而 StandardServer 继承了 LifecycleBase 类,意味着 Lifecycle 接口中的方法是在 LifecycleBase 中实现的

StandardServer 中的属性

//等待关闭的接口 默认8005
private int port = 8005;
//等待关闭的地址 默认localhost
private String address = "localhost";
//Server 中维护了一组 Service 对象,这里可以看出 Server 跟 Service 的关系是一对多
private Service services[] = new Service[0];
//加锁的对象,直接创建一个 Object 对象
private final Object servicesLock = new Object();
//等待关闭的命令
private String shutdown = "SHUTDOWN";
//持有 Catalina 的引用
private Catalina catalina = null;
//这个 ServerSocket 是监听关闭服务的
private volatile ServerSocket awaitSocket = null;

StandardServer 的构造函数

public StandardServer() {
    super();
    //初始化了 NamingResourcesImpl 对象
    globalNamingResources = new NamingResourcesImpl();
    globalNamingResources.setContainer(this);
    if (isUseNaming()) {
        //添加 NamingContextListener 事件监听器
        namingContextListener = new NamingContextListener();
        addLifecycleListener(namingContextListener);
    } else {
        namingContextListener = null;
    }
}

StandardServer 的 initInternal 方法

protected void initInternal() throws LifecycleException {

    super.initInternal();

    // Register global String cache
    // Note although the cache is global, if there are multiple Servers
    // present in the JVM (may happen when embedding) then the same cache
    // will be registered under multiple names
    onameStringCache = register(new StringCache(), "type=StringCache");

    // Register the MBeanFactory
    MBeanFactory factory = new MBeanFactory();
    factory.setContainer(this);
    onameMBeanFactory = register(factory, "type=MBeanFactory");

    // Register the naming resources
    globalNamingResources.init();

    // Populate the extension validator with JARs from common and shared
    // class loaders
    if (getCatalina() != null) {
        ClassLoader cl = getCatalina().getParentClassLoader();
        // Walk the class loader hierarchy. Stop at the system class loader.
        // This will add the shared (if present) and common class loaders
        while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
            if (cl instanceof URLClassLoader) {
                URL[] urls = ((URLClassLoader) cl).getURLs();
                for (URL url : urls) {
                    if (url.getProtocol().equals("file")) {
                        try {
                            File f = new File (url.toURI());
                            if (f.isFile() &&
                                f.getName().endsWith(".jar")) {
                                ExtensionValidator.addSystemResource(f);
                            }
                        } catch (URISyntaxException e) {
                            // Ignore
                        } catch (IOException e) {
                            // Ignore
                        }
                    }
                }
            }
            cl = cl.getParent();
        }
    }
    // Initialize our defined Services
    //重点在这里,遍历所有的 service 并调用它们的 init 方法
    //注意这里的 services 里的内容是在 Catalina 对象解析配置文件的过程中添加的 Digester 对象的 parse 方法中
    for (int i = 0; i < services.length; i++) {
        //这里猜测应该有一个 StandardService 的类,最好断点跟进去
        //注意 server 跟 service 的关系是一对多
        services[i].init();
    }
}

StandardServer 的 startInternal 方法

protected void startInternal() throws LifecycleException {
    //发送 CONFIGURE_START_EVENT 事件
    fireLifecycleEvent(CONFIGURE_START_EVENT, null);
    //设置状态为 STARTING
    setState(LifecycleState.STARTING);

    globalNamingResources.start();

    // Start our defined Services
    synchronized (servicesLock) {
        for (int i = 0; i < services.length; i++) {
            //调用 service 的 start 方法
            services[i].start();
        }
    }
}

StandardServer 的 stopInternal 方法

protected void stopInternal() throws LifecycleException {
    //设置状态为 STOPPING
    setState(LifecycleState.STOPPING);
    //发送事件 CONFIGURE_STOP_EVENT
    fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);

    // Stop our defined Services
    //循环调用所有 Service 的 stop 方法
    for (int i = 0; i < services.length; i++) {
        services[i].stop();
    }

    globalNamingResources.stop();
    //停止关闭服务
    stopAwait();
}

StandardServer 的 destroyInternal 方法

protected void destroyInternal() throws LifecycleException {
    // Destroy our defined Services
    //循环调用 Service 的 destroy 方法
    for (int i = 0; i < services.length; i++) {
        services[i].destroy();
    }

    globalNamingResources.destroy();

    unregister(onameMBeanFactory);

    unregister(onameStringCache);

    super.destroyInternal();
}

StandardServer 的 addService 方法

public void addService(Service service) {
    //为 Service 对象设置 Server 为当前server
    service.setServer(this);
    //加锁
    synchronized (servicesLock) {
        //先扩容,再赋值
        Service results[] = new Service[services.length + 1];
        System.arraycopy(services, 0, results, 0, services.length);
        results[services.length] = service;
        services = results;

        if (getState().isAvailable()) {
            try {
                //调用 service 的 start 方法
                service.start();
            } catch (LifecycleException e) {
                // Ignore
            }
        }

        // Report this property change to interested listeners
        support.firePropertyChange("service", null, service);
    }

}

StandardServer 的 findService 方法

//这个很简单,就是遍历比对name属性
public Service findService(String name) {
    if (name == null) {
        return null;
    }
    synchronized (servicesLock) {
        for (int i = 0; i < services.length; i++) {
            if (name.equals(services[i].getName())) {
                return services[i];
            }
        }
    }
    return null;
}

StandardServer 的 await 方法

public void await() {
    // Negative values - don't wait on port - tomcat is embedded or we just don't like ports
    if (port == -2) {
        // undocumented yet - for embedding apps that are around, alive.
        return;
    }
    if (port==-1) {
        try {
            awaitThread = Thread.currentThread();
            while(!stopAwait) {
                try {
                    Thread.sleep( 10000 );
                } catch( InterruptedException ex ) {
                    // continue and check the flag
                }
            }
        } finally {
            awaitThread = null;
        }
        return;
    }

    // Set up a server socket to wait on
    try {
        //创建 ServerSocket 对象
        awaitSocket = new ServerSocket(port, 1,
                                       InetAddress.getByName(address));
    } catch (IOException e) {
        log.error("StandardServer.await: create[" + address
                  + ":" + port
                  + "]: ", e);
        return;
    }

    try {
        awaitThread = Thread.currentThread();

        // Loop waiting for a connection and a valid command
        while (!stopAwait) {
            ServerSocket serverSocket = awaitSocket;
            if (serverSocket == null) {
                break;
            }

            // Wait for the next connection
            Socket socket = null;
            StringBuilder command = new StringBuilder();
            try {
                InputStream stream;
                long acceptStartTime = System.currentTimeMillis();
                try {
                    //阻塞监听 socket 连接
                    socket = serverSocket.accept();
                    //设置超时时间为 10s
                    socket.setSoTimeout(10 * 1000);  // Ten seconds
                    //获取连接的输入流,后面会解析输入流的看是否是停止指令
                    stream = socket.getInputStream();
                } catch (SocketTimeoutException ste) {
                    // This should never happen but bug 56684 suggests that
                    // it does.
                    log.warn(sm.getString("standardServer.accept.timeout",
                                          Long.valueOf(System.currentTimeMillis() - acceptStartTime)), ste);
                    continue;
                } catch (AccessControlException ace) {
                    log.warn(sm.getString("standardServer.accept.security"), ace);
                    continue;
                } catch (IOException e) {
                    if (stopAwait) {
                        // Wait was aborted with socket.close()
                        break;
                    }
                    log.error(sm.getString("standardServer.accept.error"), e);
                    break;
                }

                // Read a set of characters from the socket
                int expected = 1024; // Cut off to avoid DoS attack
                while (expected < shutdown.length()) {
                    if (random == null)
                        random = new Random();
                    expected += (random.nextInt() % 1024);
                }
                while (expected > 0) {
                    int ch = -1;
                    try {
                        ch = stream.read();
                    } catch (IOException e) {
                        log.warn(sm.getString("standardServer.accept.readError"), e);
                        ch = -1;
                    }
                    // Control character or EOF (-1) terminates loop
                    if (ch < 32 || ch == 127) {
                        break;
                    }
                    command.append((char) ch);
                    expected--;
                }
            } finally {
                // Close the socket now that we are done with it
                try {
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    // Ignore
                }
            }

            // Match against our command string
            boolean match = command.toString().equals(shutdown);
            if (match) {
                //匹配成功跳出while循环,在后面的 finally 中会关闭 ServerSocket
                log.info(sm.getString("standardServer.shutdownViaPort"));
                break;
            } else
                log.warn(sm.getString("standardServer.invalidShutdownCommand", command.toString()));
        }
    } finally {
        //关闭ServerSocket
        ServerSocket serverSocket = awaitSocket;
        awaitThread = null;
        awaitSocket = null;

        // Close the server socket and return
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                // Ignore
            }
        }
    }
}

StandardServer 的 stopAwait 方法

//关闭 ServerSocket 服务
public void stopAwait() {
    stopAwait=true;
    Thread t = awaitThread;
    if (t != null) {
        ServerSocket s = awaitSocket;
        if (s != null) {
            awaitSocket = null;
            try {
                s.close();
            } catch (IOException e) {
                // Ignored
            }
        }
        t.interrupt();
        try {
            t.join(1000);
        } catch (InterruptedException e) {
            // Ignored
        }
    }
}

小结

  • StandardServer 主要是操作内部的 Service 数组
  • StandardServer 维护了一个关闭服务 ServerSocket