笔者从事应用服务器的领域多年,原来经历过2-3次应用服务器的部署改造,Tomcat的部署功能可以说不是很完善,笔者根据经验通过本文讲述一下,JAVA EE应用服务器通常是怎么做应用部署的;
1.区分热部署,自动部署,部署,解部署等名词
部署:
一个应用调用部署接口,部署接口将应用进行扫描解析,并查找当前war包中的xxx标签,将一个应用解析为内存对象,例如Tomcat中就是以StandardContext这种对象存在;
在应用请求访问的时候,请求到当前的应用,路由到应用内存对象中,拿已经解析的内存metadata的属性,查询信息,执行结果并返回;
Tomcat中的HostConfig一系列的deployWar,deployApplication,deployContextDescription方法都是
解部署:
应用部署之后解析之后生成的应用内存对象,在Tomcat中就是StandardContext这种对象,对应应用的卸载,将这个对象从内存中干掉,这样在查询应用列表就查不到当前应用了;
Tomcat中的HostConfig的undeploy方法
应用启动:
应用内存对象生成并不意味着,能够接受应用的请求访问,需要准备一下,初始化创建很多资源,如JNDI资源的准备,ref准备等等,关于这些准备就是在启动时进行的;
在Tomcat中,其实就是StandardContext的生命周期lifecycle的startInternal方法中的内容;
应用停止:
和应用启动相反;
但通常不同的应用服务器对于应用停止的理解是不一样的,因为毕竟一个应用启动的过程中,会创建n多的资源,而你在停止的时候,好不容易把这些资源给干掉,来回创建资源是很费事的;
所以,有的应用服务器通过一个标识来做应用的启动和停止的开关,这个开关用于应用请求中,当请求路由到应用内存对象的时候,如果该标识为false,那么代表着应用已经停止,请求这时候就会返回了;
在Tomcat中实现为pause属性,详细见context.reload
重部署:
重部署其实很简单,就是先解部署,再部署,上述的两个接口之间的组合关系;
但是比较高明的应用服务器的重部署做的确实很不错,很多资源是可以重复利用的,不是完全按照解部署再重部署去做;
Tomcat中的重部署接口抽取的不好,但可以看出就是先进行undeploy,再调用deployApps;
上述的5个接口构成了接口层。
自动部署:
如果说前面的5个是部署接口的话,自动部署就是一个机制;
该机制是搞一个目录,这个目录通过程序进行周期性的扫描,然后基于下列三种情况,调用前面的几个接口:
1.如果发现该目录有新文件,那么调用部署接口继续部署
2.如果发现该目录文件的时间戳发生变化,或者context.xml发生变化,那么调用重部署接口进行重部署
3.如果发现该目录的对应文件消失,那么调用解部署接口进行应用解部署
该目录叫做自动部署目录;
管理控制台部署:
其实很简单,就是大家经常在界面上上传一些war包等文件,这一步有一个upload的过程,利用的html页面的file组件,
上传到一个目录中,然后一般程序调用部署接口进行部署。
应用部署目录:
区别于自动部署目录,应用部署目录应该是一个独立的目录,该目录不存在自动部署周期性的扫描;
无论是管理控制台部署,还是自动部署,甚至你用程序JMX远程直接调用部署接口,无论啥招,应用部署目录中都应该存在该部署的应用,上述的5个接口都是从该位置开始进行部署的;
当然有一种情况除外,就是你需要指定一个目录部署,这个就是Tomcat中的DocBase的了
启动部署:
随着应用服务器的启动,如果在应用部署目录和配置文件中有对应的应用需要部署的话,那么随着应用服务器的启动,这些这些应用直接就会部署起来;
热部署:
所谓的热部署是在当前应用部署目录中启动的一个线程,该线程和自动部署的线程一样,也是周期定期的扫描;
但是这种扫描内容不是看看目录中有没有增减,部署描述文件是否发生变化,进而发生重部署等耗时操作
热部署要的是高效,深入监听的扫描应用中的classes等资源,如果发现资源一旦变化,能最大程度的让应用恢复到最新的状态;
如果要用Tomcat去解释的话,那么Tomcat的Context.reload就是一个典型的热部署;
2.应用部署的设计
对于一般的应用服务器来说,有如下的设计能满足应用部署系统的设计:
管理控制台调用部署接口层开放出来的JMX,restful等接口进行部署;
自动部署也是调用部署接口层的部署,解部署,重部署接口;
热部署调用的是reload方法;
启动部署调用的是部署接口层开放出来的部署接口;
当然,如果在一个JVM下,就没有必要搞什么JMX和restful了,损失性能和效率;
上图的右侧是应用部署流程:
1.应用包的解析:查看该应用是否是符合JAVA EE格式,如war包的格式,即使是目录的话,也应该看看是否有WEB-INF/classes这种目录;
2.应用 服务器部署描述符扫描:一般应用服务器都会带一些自己的特有的部署配置,这个配置就被叫做部署描述符,tomcat中也有,就是context.xml文件;
3.JAVA EE规范配置文件扫描:如web.xml这种,manifest.mf这种
4.原注释扫描:自从JAVA EE5之后,开始有一些原注释放在类当中,如servlet3.0规范@Servlet这种,都需要进行扫描
5.基于前面几个步骤,可以生成一些应用内存对象,如Tomcat中的StandardContext
6.应用这个时候需要准备启动类,单纯类似StandardContext还不够,例如应用中需要用到的一些资源信息,如JNDI资源,数据源的ref都要准备好
7.应用准备就绪,加入到应用服务器的应用列表中,在Tomcat中也就是Wrapper列表中,Tomcat中可以通过Mapper进行访问了
3.评价一下Tomcat的部署
1.Tomcat的部署功能并没有将这些接口都非常清晰的抽取出来,应该抽取出来
2.Tomcat中的自动部署目录和应用部署目录重合了(当然你部署在外面就另当别论了)
3.正因为目录重合了,自动部署功能和应用部署目录重合,所以自动部署和reload的东西有点傻傻的分不清,
4.自动部署目录中的war包解析完事,如果按照一般的JAVA EE应用服务器的做法,应该将其转移到应用部署目录中,
5.Tomcat的管理控制台很弱,提供最基础的功能
总结:
总体而言,Tomcat的部署系统虽然从设计角度算不上高明,但是麻雀虽小,五脏俱全,该有的都有,不过对于商用的应用服务器的部署系统要比tomcat健全的多,功能要多,并且设计也更为合理一些,不过tomcat作为一个开源项目,只要能用并且保持稳定其实就行了;