重部署与热部署杂记

一。重部署(reloadable)


Web容器通常会有一个特殊的目录(比如说Tomcat中的“webapps”、JBoss中的“deploy”),该目录会被定期扫描,以找出新的web应用或是现有应用发生的改变。当扫描器检测到有一个已部署的.WAR应用被更新了时,扫描器就会引发一个重部署过程
一项被大多数web容器支持的附加功能就是所谓的“展开式部署(exploded deployment)”,也被称为“非打包式的”或是“目录”部署。这种方式不是部署一个.WAR的归档文件,而是可以部署一个有着与.WAR归档文件有着完全相同的内容布局的目录,因为打包一个WAR是一项代价不菲的操作,因此部署目录可以节省下来很不少的构建时间。不幸的是,即使使用目录部署,仍然逃脱不了修改一个.java文件要等待整个应用的重新初始化。在大部分的服务器中,部署描述符或是已编译类发生的任何变化都会引发一个热的重部署。
对于碎WAR或者目录部署这种方式,可以通过创建一个从特殊目录到你的工程工作区的符号链接(symlink)来省略这一复制过程。
如果使用Maven的话,则在工作区中做展开式的开发设置会很复杂。如果你的应用是一个单独的web应用的话,则你可以使用Maven的Jetty插件,该插件直接使用来自Mave的源和目标工程目录的类和资源。不幸的是,Maven的Jetty插件并不支持部署多个web应用、EJB模块或是EAR,在后一种情况中,你会卡在进行工件构建这一环节上。


大多数的web容器防止重部署时状态信息丢失的办法是容器做持久化的操作,即序列化HttpSession映射中的所有对象,然后再在新的类加载器中反序列化它们。
基本上,他们会复制所有的会话状态,而这就要求所有的会话属性都要实现Serializable(以确保会话属性能够被写到数据库或是文件中以备后用),这一实现在大多数情况下都是不做限定的。
会话的持久化功能在大多数主流的容器中已存在多年(比如说Tomcat中的Restart Persistence ),但众所周知,在Glassfish的v3之前的版本中,这一功能是缺失的。

在Tomcat中其调用StandardContext.reload()方法
    •    StandardContext.reload()方法被调用
    •    之前的WebappClassLoader实例被一个新的实例代替
    •    所有到servlet的引用都被丢弃
    •    新的servlet被创建
    •    这些servlet的Servlet.init() 方法被调用

OSGi基本上就是模块的一个集合,每个模块都被包装在自己的类加载器中,该集合可被随意丢弃和重新创建。在集合被重创建时,这些模块以与web应用完全相同的方式进行初始化,即每个模块的操作又与Tomcat类似,是一个重部署的工作。

近来一些web框架,比如说Tapestry 5、RIFE和Grails等,利用它们已需要维护应用的状态这样一个事实,采取了不同的做法。它们要确保状态是可序列化的,另外,就是要很容易可重创建的,这样的话在扔掉一个类加载器之后,就不存在任何需要重新初化的东西了
 由于组件的生命周期是由框架进行管理的,因此在新的类加载器中,在无需用户干预的情况下重建组件是很容易的事情,从而也造出了重载代码的效果。在后台, 旧的组件被销毁(类加载器被丢弃),新的组件被创建(在一个新的类加载器中该类被再次读入),旧的状态或被反序列化,或基于配置创建。

二。热部署:


为了解决修改个别类或配置引起整个应用重新部署的问题,目前主要有下面的几种技术:
HotSwap:
HotSwap:“HotSwap”是JPDA(Java Platform Debugger Architecture)中的一个特性,JPDA增强是自Java 2 SDK1.4新增的功能。HotSwap允许将JVM中的类定义替换为新的类定义,这就允许开发人员在debug时,将修改过的class替换JVM中旧 有的class,无需重新启动服务器。不过,目前HotSwap只支持对方法body的修改,不支持对类和方法签名的修改(比如修改类名,方法名,方法参数等)。考虑这些限制,也是有理由的,替换类定义,就需要新类和旧类之间有一个关联,这里关联就是类的全名(或许还有其他信息),类名都改了,就不知道替换哪个类了。至于方法签名的修改,应该是考虑到运行时方法的调用,通过方法签名替换已有的方法调用。

正如上面所述,HotSwap有很大的局限性。要依赖于IDE的集成,只能针对方法体的修改做更新。不能新建方法,添加域更甚至改变继承的层次结构。避免了无论何时只要有类的字节码被修改就要重载容器的这种要求。对HotSwap的一种替代式的方案是JRebel。

监控磁盘上实际已编译的.class文件,无论何时只要有文件被更新就更新类。

Jrebel:

与动态的类加载器不一样,[JRebel保留了所有现有的对象和类的标识和状态],允许开发者继续使用他们的应用而不会产生延迟。


注意,与Hotswap相比,MyObject指针指向了最新版本的MyObject.class

 

参考:http://article.yeeyan.org/view/213582/186226

 
原文地址:https://www.cnblogs.com/highriver/p/3088944.html