从WebLogic 6.1迁移到WebLogic 8.1
内容摘要
BEA 的名字与应用服务器是同义词。北美几乎所有运行在 Unix 操作系统上的应用程序都运行在 Bea Weblogic Server 平台上,特别是那些金融方面的应
文章正文
BEA 的名字与应用服务器是同义词。北美几乎所有运行在 Unix 操作系统上的应用程序都运行在 Bea Weblogic Server 平台上,特别是那些金融方面的应用。当前稳定的 WebLogic 8.1 版本要比较早的版本功能更多。向新版本迁移从来都具有挑战性和冒险性,但是这样做可以提高效率和增加新的功能,也有助于继续使用当前供应商的产品和支持。
在 WebLogic 6.1平台上开发的大多数应用程序都使用 JDK 1.3 或更早版本的 JDK。从 WebLogic 6.1 转移到 WebLogic 8.1 意味着使应用程序与 JDK 1.4.1 或更高的版本兼容,这是因为在WebLogic 8.1 发布时,配套的是JDK 1.4。所有大多数迁移风险在BEA网站bea.com上已讨论。这里我将给出一些个人观点。
这些将是我们讨论的要点。
从6.1向8.1的迁移,当前应用程序场境
迁移的常见问题
getter 方法和setter 方法
可序列化对象
WL cache
调整 JVM(Java 虚拟机)内存使用
带有语言属性的页指令
Java.net.SocketException:打开文件太多
其他问题
从6.1向8.1的迁移——当前应用程序场境
我们的应用程序将要迁移到 WebLogic 8.1。当前的环境是:
操作系统:Solaris 5.8 P4
WebLogic Server 8.1P2
Java Release 1.4.2_06
Actuate 7.1SP6
主流的关系数据库系统,对迁移没有影响
Struts1.1 Framework
Model II Web Architecture
迁移的常见问题
从WebLogic 6.1向WebLogic 8.1迁移的常见问题包括:类路径、系统路径、环境变量、数据源、部署、JSP 解析、安全性、服务器配置以及 XML 解析。所有这些内容都在www.bea.com作了详细讨论。
例如,我们拿 XML 解析来说。WebLogic 8.1不像WebLogic 6.1 及早期的版本,它不能容忍编码错误。因此,需要将编码标准从 Unicode 改成 utf-16。
同时,不再需要 JSP 重编译。因此,如下代码必须要从 web.xml 中删除掉:
<servlet>
<servlet-name>JSPClassServlet</servlet-name>
<servlet-class>WebLogic.servlet.JSPClassServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JSPClassServlet</servlet-name>
<url-pattern>*.JSP</url-pattern>
</servlet-mapping>
getter 方法和setter 方法
在 WebLogic 8.1 平台上运行的应用程序使用了 JDK 1.4 或者更早的版本。因此,当我们从 WebLogic 6.1迁移到 WebLogic 8.1 时,我们显然是迁移到了 JDK 1.4.1 或更晚的版本。JDK 更晚的版本遵守更严格的 Java 规范,这就意味着原来在较早版本的 JDK 下运行得很好的不合适代码将在 JDK 1.4.1 或更晚的版本中导致错误。
例如,使用标签库就会有一个错误:
uri=′/WEB-INF/tlds/taglib.tld′ prefix=′j2ee′:对于´Items’属性来说,没有用于 Tag 类的 setter 方法。´com.sun.j2ee.apps.application.taglib.list. SearchListTag’可能会发生,因为在 /template.JSP 第八行有一个错误:<%@ taglib uri="/WEB-INF/tlds/taglib.tld" prefix="j2ee" %>
这种失败发生在那些受Introspector API 支配的 JSP 和 bean 中。一个好的例子是getter 方法和 setter 方法。如果 setter 是一个整型,那么 getter 也必须是整型,而不能是字符串型。
可序列化对象
为了支持在内存中拷贝HTTP 会话,所有对象数据都必须是可序列化的。否则,会话复制就会失败。当启用了“debugging(调试)”时, WebLogic 输出了一条警告信息,表明会话还没有复制:
“Failed to replicate non-serializable object(复制不可序列化对象失败)”
如果发生了这类事情,请查找抛出该错误的页面,并且要确保所有置于会话中的数据都是可序列化的。每个存储在会话中的对象必须实现一个可序列化的接口用于复制。
WL 缓存
这种 cache 必须始终从每个节点上删除,用于 WebLogic 提取任何使用脚本修正过的代码。(通常情况下,在一个生产环境中有多个节点用于意外、容错和负载均衡。)WebLogic 8.1 服务器高速缓存标签具有如下属性:超时(timeout)、作用域(scope)、键(key)、异步(asyns)、名称(name)、大小(size)和刷新(flush)。当把 flush 设定为 true 时,缓存就被刷新了。下面是一个简单的 cache 标签:
<wl:cache>
<!--the content between these tags will only be
refreshed on server restart-->
</wl:cache>
使用cache 标签迫使每次新值计算时,已缓存过的值都要释放掉。 cache必须以名称属性来命名。size 属性将会清理所有值,而 key 属性将会清理特定值。WebLogic 8.1 有两个版本的cache,这样就给我们提供了一种选择,即使用软引用(soft reference)来缓存,以避免系统内存的过度使用。然而,当 WebLogic 运行在 Hotspot VM 上时,我们是不能使用软引用的。
调整 JVM(Java 虚拟机)内存使用
如果新环境的 JVM 堆大小是有限的,那么必须重新分解文件。如果我们在一个 JSP 页面上合并了太多的内容,那么就可能导致 JVM 内存问题。我们都知道,JSP 作为一个单独方法被编译到servlet 上。如果有更多的标签,那么 servlet 方法就会因为太大而不能被 JVM 理解。在那种情况下,用户将会看到一个错误信息,即“Illegal target of jump or branch(非法的跳跃目标或分支)。”这就意味着 JSP 已经超过了大小限制,因此需要将它们重新分解。
有一种解决方案是,如果需要更多的内存来运行这些文件的话,提高JVM堆的大小值。提高堆的大小会降低延迟,增加稳定性。因此,在binTogether.bat 文件中的 JVM 选项一行,将 -Xms64m 改成 -Xms256m(或者更高)。
另一种解决方案是,将一个较大的页面分解成很多较小的页面。然后在运行时,通过include 将它们放在一起。使用<%@include> 不会起作用,因为它是一个编译时的包含。
最后,还有个方法是,寻找保存这些标签的地方。例如,有这样一个标签<html:option>,它是扩展用于显示文本信息的,可以将以下代码:
<Html:option ... ><bean:message key="foo"/></html:option>
替换为:
<html:option ... key="foo"/>
这类例子越多,情况就会越好。除了<html:option> 之外,其他一些struts 标签是包含文本信息的捷径。如果可以提前构建一个适当的集合,就会考虑将<html:option> 序列替换为 <html:options> 。
一种方案是使用我们自己的标签。通过继承BodyTagSupport 来修改一些频繁使用的标签以便扩展标签支持,并且在 .tld 文件中使用 <body content>empty</body content> 来标志它们将会极大地降低生成的代码大小。它可能不会每次都能起作用,但是它确实有所帮助。
只要 JSP 很大时,就需要将com.sun.tools.javac.main.largebranch 变量设为 true。
在那种情况下,必须使用JRocket,它捆绑在 WebLogic 8.1 上。它比 JDK 能更好地处理内存。
带有语言属性的页面指令
在某些JSP代码中,属性语言的值要多次指定。这在WebLogic 6.1上是有效的,然而在向WebLogic 8.1迁移的代码中,我们只要对这些值指定一次,否则的话就会按照J2EE规范的要求抛出一个JSPException 异常。
Java.net.SocketException:太多打开的文件
在转换到 WebLogic 8.1 之后,服务器就会停止运行,并发送如下消息。它也许跟迁移无关,但是必须解决这个问题。
<Critical> <WebLogicServer> <BEA-000204>
<Failed to listen on port 7001, failure count: 1, failing for 0 seconds,
java.net.Socke tException: Too many open files>
应该立即采取的措施是在/etc/system 中将rlim_fd_max 的值提高为8192。但是这样可能导致使用数上升至7000,因而它不是可行的解决方案。
最好的策略是,在操作系统中调整好TCP参数。
Java.lang.OutOfMemoryError
该错误就是一个运行时异常(Runtime Exception),它试图在 WLS 8.1 SP3 中使用Sybase Pool 来执行一个存储过程(procedure)。这个错误发生在我们使用 WebLogic 8.1 SP3 的时候。BEA 意识到了这个问题,并在 WebLogic 8.1SP4 中已经将它解决。对于那些想要使用8.1SP3 的人来说,BEA 正在通过 JAR 文件的方式提供一个补丁。
其他问题
a) 带有语言属性的页面指令
在某些文件中的JSP代码中,属性语言值要多次指定。这在WebLogic 6.1上有效,然后迁移到WebLogic 8.1之后,我们就必须确保这些值的指定次数只能是一次,否则就会根据J2EE规范抛出一个JSPException 异常。
b) 在分级模式下部署应用程序
WebLogic 8.1 可以让应用程序在多种模式下部署,这要视情况而定。在部署单一服务器时,域总是使用no_stage 模式。
c) 定义上下文root
我们的应用程序是孤立的,因此需要将如下代码片断加入到web.xml文件中。
<context-root>isoft/iSoft</context-root>
结束语
在所有应用程序中,不管应用服务器的手册如何规定,代码都必须强制遵循J2EE规范。
在 WebLogic 6.1平台上开发的大多数应用程序都使用 JDK 1.3 或更早版本的 JDK。从 WebLogic 6.1 转移到 WebLogic 8.1 意味着使应用程序与 JDK 1.4.1 或更高的版本兼容,这是因为在WebLogic 8.1 发布时,配套的是JDK 1.4。所有大多数迁移风险在BEA网站bea.com上已讨论。这里我将给出一些个人观点。
这些将是我们讨论的要点。
从6.1向8.1的迁移,当前应用程序场境
迁移的常见问题
getter 方法和setter 方法
可序列化对象
WL cache
调整 JVM(Java 虚拟机)内存使用
带有语言属性的页指令
Java.net.SocketException:打开文件太多
其他问题
从6.1向8.1的迁移——当前应用程序场境
我们的应用程序将要迁移到 WebLogic 8.1。当前的环境是:
操作系统:Solaris 5.8 P4
WebLogic Server 8.1P2
Java Release 1.4.2_06
Actuate 7.1SP6
主流的关系数据库系统,对迁移没有影响
Struts1.1 Framework
Model II Web Architecture
迁移的常见问题
从WebLogic 6.1向WebLogic 8.1迁移的常见问题包括:类路径、系统路径、环境变量、数据源、部署、JSP 解析、安全性、服务器配置以及 XML 解析。所有这些内容都在www.bea.com作了详细讨论。
例如,我们拿 XML 解析来说。WebLogic 8.1不像WebLogic 6.1 及早期的版本,它不能容忍编码错误。因此,需要将编码标准从 Unicode 改成 utf-16。
同时,不再需要 JSP 重编译。因此,如下代码必须要从 web.xml 中删除掉:
<servlet>
<servlet-name>JSPClassServlet</servlet-name>
<servlet-class>WebLogic.servlet.JSPClassServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JSPClassServlet</servlet-name>
<url-pattern>*.JSP</url-pattern>
</servlet-mapping>
getter 方法和setter 方法
在 WebLogic 8.1 平台上运行的应用程序使用了 JDK 1.4 或者更早的版本。因此,当我们从 WebLogic 6.1迁移到 WebLogic 8.1 时,我们显然是迁移到了 JDK 1.4.1 或更晚的版本。JDK 更晚的版本遵守更严格的 Java 规范,这就意味着原来在较早版本的 JDK 下运行得很好的不合适代码将在 JDK 1.4.1 或更晚的版本中导致错误。
例如,使用标签库就会有一个错误:
uri=′/WEB-INF/tlds/taglib.tld′ prefix=′j2ee′:对于´Items’属性来说,没有用于 Tag 类的 setter 方法。´com.sun.j2ee.apps.application.taglib.list. SearchListTag’可能会发生,因为在 /template.JSP 第八行有一个错误:<%@ taglib uri="/WEB-INF/tlds/taglib.tld" prefix="j2ee" %>
这种失败发生在那些受Introspector API 支配的 JSP 和 bean 中。一个好的例子是getter 方法和 setter 方法。如果 setter 是一个整型,那么 getter 也必须是整型,而不能是字符串型。
可序列化对象
为了支持在内存中拷贝HTTP 会话,所有对象数据都必须是可序列化的。否则,会话复制就会失败。当启用了“debugging(调试)”时, WebLogic 输出了一条警告信息,表明会话还没有复制:
“Failed to replicate non-serializable object(复制不可序列化对象失败)”
如果发生了这类事情,请查找抛出该错误的页面,并且要确保所有置于会话中的数据都是可序列化的。每个存储在会话中的对象必须实现一个可序列化的接口用于复制。
WL 缓存
这种 cache 必须始终从每个节点上删除,用于 WebLogic 提取任何使用脚本修正过的代码。(通常情况下,在一个生产环境中有多个节点用于意外、容错和负载均衡。)WebLogic 8.1 服务器高速缓存标签具有如下属性:超时(timeout)、作用域(scope)、键(key)、异步(asyns)、名称(name)、大小(size)和刷新(flush)。当把 flush 设定为 true 时,缓存就被刷新了。下面是一个简单的 cache 标签:
<wl:cache>
<!--the content between these tags will only be
refreshed on server restart-->
</wl:cache>
使用cache 标签迫使每次新值计算时,已缓存过的值都要释放掉。 cache必须以名称属性来命名。size 属性将会清理所有值,而 key 属性将会清理特定值。WebLogic 8.1 有两个版本的cache,这样就给我们提供了一种选择,即使用软引用(soft reference)来缓存,以避免系统内存的过度使用。然而,当 WebLogic 运行在 Hotspot VM 上时,我们是不能使用软引用的。
调整 JVM(Java 虚拟机)内存使用
如果新环境的 JVM 堆大小是有限的,那么必须重新分解文件。如果我们在一个 JSP 页面上合并了太多的内容,那么就可能导致 JVM 内存问题。我们都知道,JSP 作为一个单独方法被编译到servlet 上。如果有更多的标签,那么 servlet 方法就会因为太大而不能被 JVM 理解。在那种情况下,用户将会看到一个错误信息,即“Illegal target of jump or branch(非法的跳跃目标或分支)。”这就意味着 JSP 已经超过了大小限制,因此需要将它们重新分解。
有一种解决方案是,如果需要更多的内存来运行这些文件的话,提高JVM堆的大小值。提高堆的大小会降低延迟,增加稳定性。因此,在binTogether.bat 文件中的 JVM 选项一行,将 -Xms64m 改成 -Xms256m(或者更高)。
另一种解决方案是,将一个较大的页面分解成很多较小的页面。然后在运行时,通过include 将它们放在一起。使用<%@include> 不会起作用,因为它是一个编译时的包含。
最后,还有个方法是,寻找保存这些标签的地方。例如,有这样一个标签<html:option>,它是扩展用于显示文本信息的,可以将以下代码:
<Html:option ... ><bean:message key="foo"/></html:option>
替换为:
<html:option ... key="foo"/>
这类例子越多,情况就会越好。除了<html:option> 之外,其他一些struts 标签是包含文本信息的捷径。如果可以提前构建一个适当的集合,就会考虑将<html:option> 序列替换为 <html:options> 。
一种方案是使用我们自己的标签。通过继承BodyTagSupport 来修改一些频繁使用的标签以便扩展标签支持,并且在 .tld 文件中使用 <body content>empty</body content> 来标志它们将会极大地降低生成的代码大小。它可能不会每次都能起作用,但是它确实有所帮助。
只要 JSP 很大时,就需要将com.sun.tools.javac.main.largebranch 变量设为 true。
在那种情况下,必须使用JRocket,它捆绑在 WebLogic 8.1 上。它比 JDK 能更好地处理内存。
带有语言属性的页面指令
在某些JSP代码中,属性语言的值要多次指定。这在WebLogic 6.1上是有效的,然而在向WebLogic 8.1迁移的代码中,我们只要对这些值指定一次,否则的话就会按照J2EE规范的要求抛出一个JSPException 异常。
Java.net.SocketException:太多打开的文件
在转换到 WebLogic 8.1 之后,服务器就会停止运行,并发送如下消息。它也许跟迁移无关,但是必须解决这个问题。
<Critical> <WebLogicServer> <BEA-000204>
<Failed to listen on port 7001, failure count: 1, failing for 0 seconds,
java.net.Socke tException: Too many open files>
应该立即采取的措施是在/etc/system 中将rlim_fd_max 的值提高为8192。但是这样可能导致使用数上升至7000,因而它不是可行的解决方案。
最好的策略是,在操作系统中调整好TCP参数。
Java.lang.OutOfMemoryError
该错误就是一个运行时异常(Runtime Exception),它试图在 WLS 8.1 SP3 中使用Sybase Pool 来执行一个存储过程(procedure)。这个错误发生在我们使用 WebLogic 8.1 SP3 的时候。BEA 意识到了这个问题,并在 WebLogic 8.1SP4 中已经将它解决。对于那些想要使用8.1SP3 的人来说,BEA 正在通过 JAR 文件的方式提供一个补丁。
其他问题
a) 带有语言属性的页面指令
在某些文件中的JSP代码中,属性语言值要多次指定。这在WebLogic 6.1上有效,然后迁移到WebLogic 8.1之后,我们就必须确保这些值的指定次数只能是一次,否则就会根据J2EE规范抛出一个JSPException 异常。
b) 在分级模式下部署应用程序
WebLogic 8.1 可以让应用程序在多种模式下部署,这要视情况而定。在部署单一服务器时,域总是使用no_stage 模式。
c) 定义上下文root
我们的应用程序是孤立的,因此需要将如下代码片断加入到web.xml文件中。
<context-root>isoft/iSoft</context-root>
结束语
在所有应用程序中,不管应用服务器的手册如何规定,代码都必须强制遵循J2EE规范。
代码注释
[!--zhushi--]