Jetty服务器启动过程分析

本文详细分析了Jetty服务器的启动过程,包括start.jar启动分析和XmlConfiguration的作用。start.jar解析命令行参数和start.ini配置,然后通过XmlConfiguration创建并启动Server。XmlConfiguration根据xml文件组装Server,包括线程池、connector和handler等组件。Jetty启动时,先启动handler,再启动用户自定义组件(实现LifeCycle接口),最后启动Connector接收用户请求。

先大致看一下外部启动一个Jetty服务器的过程,然后再展开分析
1.java start.jar进行启动,解析命令行参数并读取start.ini中配置的所有参数。
2.解析start.config确定jetty模块的类路径并确定首先执行的MainClass。
3.可以选择是否另起一个进程来,如果不另起进程,则通过反射方式来调用MainClass,start.ini中配置的JVM参数不会生效。
4.MainClass默认是XmlConfiguration,解析etc/jetty.xml,etc/jetty-deploy.xml等,创建实例并组装Server(是根据在start.ini中定义的顺序创建,顺序很重要,这里的IOC是jetty自己实现的)然后调用start()启动Server()。

1.start.jar启动分析

我们可以通过java -jar start.jar 命令来启动jetty,所以首先从start.jar开始分析。这个jar中包含了解析命令行参数的Main类,Main主要负责解析命令行中传入的参数以及start.ini文件中配置的参数。start.ini 中定义了 JVM 需要的参数以及 etc 目录中用到的xml配置文件和启动jetty启动时需要加载的模块,如下图:
这里写图片描述
然后由Config类解析出start.ini中OPTIONS选项指定的模块包位置并加入到classpath中,这些模块包都定义在在start.config文件中,通过在 start.ini 中定义 OPTIONS 以及在 start.config 中定义模块路径就可以确定把哪些 jar 加入到环境变量中。
以上准备工作做完之后就可以真正开始服务器处理了,这时候可以在本进程中直接通过反射方式启动,但缺点是start.ini中配置的JVM参数就如同虚设了,
因为Java进程已经起来了,不能再按照新的堆参数进行设置了;第二种方式就是重新启动一个进程,这样就可以重新设置堆参数了,start.ini 中得到了启动参数start.config 中有了MainClass和Classpath需要的jar包,则可以直接用java xxx方式启动了,要使用这种方式启动只需要在 start.ini 中配置 –exec 参数即可。
这里的MainClass默认是XmlConfiguration类,它默认做几件事情:1.对start.ini中定义的配置文件进行解析,例如/etc/jetty.xml等。2.通过自己的IOC将这些组件组装在一起,最后调用start()方法启动这些组件。
下面是start.jar中的Main类的main()方法:

public static void main(String[] args)
    {
        boolean test=false;
        try
        {
            Main main = new Main();
            //解析启动时在命令行传入的参数和start.ini中配置的参数
            StartArgs startArgs = main.processCommandLine(args);
            test=startArgs.isTestingModeEnabled()
            //通过拼接好的参数启动XmlConfiguration类,有通过反射和另起一个jvm进程两种方式
            main.start(startArgs);
        }
        catch (UsageException e)
        {
            StartLog.error(e.getMessage());
            usageExit(e.getCause(),e.getExitCode(),test);
        }
        catch (Throwable e)
        {
            usageExit(e,UsageException.ERR_UNKNOWN,test);
        }
    }

上面讲到的如果在start.ini中配置了–exec参数就会另起一个进程是在main.start()方法实现,具体的代码如下:

// execute Jetty in another JVM
        if (args.isExec())
        {
            CommandLineBuilder cmd = args.getMainArgs(true);
            cmd.debug();
            ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
            StartLog.endStartLog();
            final Process process = pbuilder.start();
            Runtime.getRuntime().addShutdownHook(new Thread()
            {
                @Override
                public void run()
                {
                    StartLog.debug("Destroying " + process);
                    process.destroy();
                }
            });

            copyInThread(process.getErrorStream(),System.err);
            copyInThread(process.getInputStream(),System.out);
            copyInThread(System.in,process.getOutputStream());
            process.waitFor();
            System.exit(0); // exit JVM when child process ends.
            return;
        }

注意上面的注释,如果XMLConfiguration启动的进程结束了,那么start.jar对应的进程也会结束掉。

2.XmlConfiguration分析

上面说到默认的MainClass是XmlConfiguration,这个类的main()函数中负责解析xml配置文件利用自己的IOC组装Server。这里主要是用到xml文件来组装Server的过程,默认使用的是etc/jetty.xml,也可以在start.ini中指定其它文件,主要的流程是从xml文件中创建Server类,以及填充Server所需要的线程池 、connector、handler等组件. xml的部分配置如下,可以看到配置了connector handler和threadPool。
这里写图片描述

在XmlConfiguration解析完配置之后,就开始启动服务,jetty的启动是从Server的启动开始的。从XmlConfiguration中的main函数中可以看到,对那些继承了LifCycle的组件,会调用start()方法进行启动,而Server也是一个handler,所以会在下面的方法中进行启动。

 // For all objects created by XmlConfigurations, start them if they are lifecycles.
        for (Object obj : objects) {
            if (obj instanceof LifeCycle) {
                LifeCycle lc = (LifeCycle) obj;
                if (!lc.isRunning()) {
                    lc.start();
                }
            }
        }

XMLConfiguration解析完配置之后就开始真正启动服务了,Jetty的启动是从Server开始的。Server启动的时序图如下:
这里写图片描述

可以看到先配置好用户在xml文件中配置的核心组件,将它们作为bean加入到内部的bean数组中,ThreadPool也是作为自定义组件加入的。然后调用Server的start()方法进行启动,先启动handler处理器,再启动用户自定义组件,这里的用户自定义组件需要实现LifeCycle,最后再启动Connector接受用户请求。关闭的流程是相反的,先关闭Connector,再关闭用户自定义组件,最后再关闭handler处理器。
至此Jetty也就算是正式启动起来了,至于里面的Connector是如何接受用户请求、一系列Handler是如何处理请求、ThreadPool如何为前面两张提供线程,都会在后面的源码阅读中进行解析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值