再谈WebSphere的类加载和故障排查

2009年6月15日 hashei 2 条评论

引言

上次在WebSphere的类加载机制和故障排查一文中整理了一下Classloader的一些概念和加载原理,但是概念的应用不是很明确,故障排查也没有具体的方法。所以今天再次整理了IBM developerworks里有参考价值的文章,希望在遇到ClassCastException、ClassNotFoundException、NoClassDefFoundException、UnsatisfiedLinkError的错误时提供解决思路。

IBM WebSphere 开发者技术期刊: 类路径冲突的鉴别》一文描述了应用迁移过程中所发生的“故障”,打引号那是因为WAS并没有发出ClassNotFoundException、NoClassDefFoundException等的错误信息,而是“并非预期中的表现”。最终排查的结果是:

其结果是 C:/Program Files/IBM/WebSphere Studio/Application Developer/v5.1.1/runtimes/base_v51/lib/jython.jar ,而不是我们期望的 WEB-INF/lib/jakarta-oro-2.0.7.jar

这是一个很典型的类加载错误例子,默认的PARENT_FIRST加载模式让类加载器从应用程序 类装入器中先加载了jython.jar(正好有需要的同名类),而不是Web 模块类装入器里正确的jakarta-oro-2.0.7.jar。解决的方法可以启用PARENT_LAST 加载模式即可。文章中检测类加载路径的Servelet可以作为参考,不过我觉得一般会用-verbose 命令行选项打开 IBM JVM 的详细输出、trace某个确定类的情况或者dump的方法找到类加载路径。

调试方法

《类装入问题解密,第 1 部分: 类装入和调试工具介绍》 介绍了这三种方法

可以用 -verbose 命令行选项打开 IBM JVM 的详细输出。当某些事件发生的时候(例如,类装入时),详细输出会在控制台上显示信息。要想得到额外的类装入信息,可以用详细类输出。可以用 -verbose:class 选项启动这个模式。

解释详细输出
详细输出列出已经打开的所有 JAR 文件,包括到这些 JAR 的完整路径。下面是一个示例:

...
[Opened D:\jre\lib\core.jar in 10 ms]
[Opened D:\jre\lib\graphics.jar in 10 ms]
...

所有装入的类都已经列出,同时还指出它们是从哪个 JAR 文件或目录装入的。例如:

...
[Loaded java.lang.NoClassDefFoundError from D:\jre\lib\core.jar]
[Loaded java.lang.Class from D:\jre\lib\core.jar]
[Loaded java.lang.Object from D:\jre\lib\core.jar]
...

阅读全文…

分类: Websphere系列, 排错 标签: ,

配置WebSphere使用LDAP实现安全性

2009年6月13日 hashei 没有评论

上文中所介绍的启用安全性的方法可以使用在简单的、非分布式的和独立应用服务器类型的运行时环境中,但是如果面对企业应用中如下的情况: 需要同其他使用 LDAP 的应用程序的互操作、需要集成原有的ACL来集中管理……这时候就要配置原有的LDAP服务器作为WebSphere安全性的认证方式(Authentication)。

要达成的任务:本例是在建立profile过程中就启用了管理控制台安全性,用户名和密码都为wasadmin,现在添加LDAP作为认证方式的补充。

一个典型的拓扑环境如下图:

websphere with ldap

操作过程

在“安全性”中点击“安全管理、应用程序和基础结构”,在用户帐户存储库中选用“联合存储库”,点击“设置为当前”。

点击配置,在“域中的存储库”里点击“将基本条目添加至域”,点击“添加存储库”

“存储库标识”填写便于记忆和管理的名字,这里写成“LDAP”;“目录类型”选择为“定制”,主机名填写LDAP服务器的主机名或IP地址,端口默认389;故障转移主机视实际情况填写。点击应用。

此时“组属性定义”由灰变可选,点击之。在“组成员属性名称”里填写“guid”,点击保存配置。

此时进入到“存储库应用”页面,刚才添加到存储库已经出现,在“用于在域中唯一标识这组条目的基本条目的专有名称”中输入刚才设置的存储库标识“LDAP”。此存储库中基本条目的专有名称则是LDAP域名的名称,例如“dc=ibm,dc=com”,点击应用。

在安全性首页面点击应用,勾选管理安全性,去掉应用程序安全性和Java 2安全性,点击应用,保存配置。

重启应用服务器,此时在“用户和组”的“管理用户”中,可以搜索到LDAP服务器中的用户。接下来你可以在管理用户角色中为某些用户分配was管理员、操作员、配置员、监视员等角色,或者为应用程序组件启用认证机制,这样访问应用时需要输入LDAP中的用户名密码。

安全第一-WebSphere启用全局安全性

2009年6月11日 hashei 3 条评论

记得小时候有一次出去春游,带队的老师一直喜欢唠叨《方世玉》里李国邦的“安全第一”,那时候不怎么看得起这个懦弱胆小、明哲保身的胖男人,“安全第一”的口头禅也成了我调侃的对象。但是如今回想起他为信守承诺挺身而出并付出生命的镜头,却觉得他是电影里最贴近我们的普通人。

跑题了那么多,为的是说明WebSphere中启用管理安全性的必要性——否则谁都可以进入你的控制台修改配置,就算开发阶段没有安全要求,但是WebSphere没有Weblogic的那种锁定模式,所以当两个人同时修改配置并保存时,往往会发生操作丢失和冲突的问题。所以接下来介绍针对控制台的安全性设置,当然最直接的就是在安装profile的时候就启用管理安全性。

在管理控制台-安全中启用“全局安全性”,并把“应用程序安全性”、“执行Java 2安全性”选项前的勾去掉——我们今天只考虑控制台的安全性。

接下来对于“用户注册表”的选择,有三种方法:

最简单的——配置本地操作系统用户

    1. 单击安全性 > 全局安全性
    2. 在“用户注册表”下,单击本地操作系统
    3. 服务器用户标识字段中输入有效用户名。
    4. 服务器用户密码字段中输入用户密码。
    5. 可选: 选中授权时忽略大小写选项以使 WebSphere Application Server 在您使用缺省授权时能够执行不区分大小写的授权检查。
    6. 单击确定

这里的用户标识和密码,是指操作系统的用户和密码。就是说Windows环境下,你需要先在计算机管理的“本地用户和组”里设置一个帐号,类Unix环境需要先user add一个帐号并设置密码。优点是简单明了,缺点则是引入了另一层不安全——你的系统管理员帐号公开出来了,原因见引用。虽说一般都是使用WebSphere的安装运行帐号作为这里所设置的帐号(又有一个问题,如果是域环境中搭建Windows故障转移集群,那么这个帐号还必须是域管理员帐号),WebSphere管理员原本就知道这个帐号的,但往往开发人员也需要知道控制台的登录密码进行应用发布,这就造成了权限控制的不便。而且有些项目的安全策略需要定期修改系统密码,那更会造成种种不便。所以更常用的,是第二种“用户注册表”今天想了想,用的最多的其实是“联合存储库”,WAS建立Profiles启用安全性默认就是用这种模式

在非 admin 用户(Windows 平台)或非 root 用户(Unix 平台)的环境中,如何为 WAS 设置安全特性?

答:在非admin用户(Windows平台)/非root用户(Unix平台)环境中运行WAS时,在全局安全(global security)特性被启用的前提下,用户的注册表(registry)必须是LDAP或一个特定的注册表(自定义注册表)。

如果想使用本地操作系统的注册表,运行WAS的用户必须有管理员/root用户的权限来调用本地系统的认证或收集用户/组信息的API。

阅读全文…

WebSphere troubshooting-用工具分析GC Log

2009年6月9日 hashei 没有评论

要进行gc performance tuning,不得不对gc log进行分析。之前说到了“人肉”的方法,总觉得不够形象,无法让不了解的开发人员抑或是技术负责人有个直观的了解,所以本文介绍几个分析GC log的工具。

首先需要下载IBM Support Assistant,下载之后就可以从Update-Tools add on中下载我们需要的工具了,ISA使用方法。ISA把所有的工具集成在一个界面内,省去了设置启动参数的麻烦,同时能保持最及时的更新。分析垃圾回收日志,我主要用“The IBM Monitoring and Diagnostic Tools for Java™ – Garbage Collection and Memory Visualizer”和“IBM Pattern Modeling and Analysis Tool for Java Garbage Collector (PMAT)”这两个工具。我会用实际例子来说明如何使用这个工具。

用Garbage Collection and Memory Visualizer载入native_stderr.log,首先你会看到

gclog1 点击展开大图

这是一个500分钟的垃圾回收曲线图,可以观察到一天以内的大致情况。总的来说,蓝色的Used heap(after collection)运行在“平行通道”内,没有走“上升通道”(炒股的朋友应该知道上升通道的图形是咋样的)。所以在Report这个标签内,可以看到“The memory usage of the application does not indicate any obvious leaks.”。

Report中的Summary是需要关注的,它向我们显示了GC发生的次数,所用的policy(optthruput),平均停顿时间248ms,平均间隔时间3.37分钟,还有垃圾回收的速率(垃圾产生多并非不好,反而是吞吐率高的一种表现)。

Summary

让我们再切回Line plot视图,现在可以框选某一个时间段进行放大,同时在右边Axes中选择X轴的坐标系,默认的是相对时间,以分钟为单位,适用于你的应用程序总在启动N个小时后出现问题。如果是每天固定时间发生性能问题,那么应该选用绝对时间。

默认的曲线开启了Heap size和Used heap(after collection),你可以根据需要,在VGC Pause Date和VGC Date、VGC Heap Data中勾选你需要查看的曲线。比如你觉得程序响应时间很长,那么可以勾选上Intervals between garbage collection triggers和Pause time,看看上一条曲线是否和下面一条靠的“太近”。

阅读全文…

各司其职-WebSphere的动静分离

2009年6月5日 hashei 5 条评论

前一篇文章说到了前端优化对响应时间的提升效果,不过要用到这种好处,首先要做的就是让WebSphere个组件各司其职——IBM Http Server处理静态文件,WebSphere Application Server处理动态内容——所谓的“动静分离”。

先了解一下WAS是如何处理静态内容的:

静态内容被返回到用户的方式至少有三种。它们是:

  1. 静态内容通过 WebSphere Application Server 中的 File Serving 功能从 WAR 文件返回(缺省情况)
  2. 静态内容从 Web 服务器返回
  3. 静态内容从 Caching Proxy Server 返回,如从 WebSphere Edge Server(以下称为 Edge Server)产品中的 Caching Proxy Server 返回。

我们来看一个例子,下图中的应用程序是默认安装的BusinessObjects的Crystal Reports Explorer组件:

web speed before Optimization

简洁的页面,却也有415K的内容,本地打开速度为2.3S。接下来我们把静态页面转移到IHS上,看看结果如何。

打开位于 WAR 文件下的 WEB-INF 扩展中的 ibm-web-ext.xmi 文件,编辑或者添加fileServingEnabled=”false”来禁用Application Server 的文件服务功能。同样修改config目录下的ibm-web-ext.xmi 文件(注:应该是在程序打包时就禁用fileServingEnabled功能,修改文件的话注意各个地方的统一)。重启应用。

再次刷新程序首页,发现已无法访问。我们重新生成、传播插件,比较前后的差别,发现

<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/*”/>

变为了

<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/updatehandler.jsp”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/updatehandler.csp”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/updatehandler2.csp”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/*.jsp”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/*.jsv”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/*.jsw”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/j_security_check”/>
<Uri AffinityCookie=”JSESSIONID” AffinityURLIdentifier=”jsessionid” Name=”/adhoc/ibm_security_logout”/>

原先不管三七二十一的转发,现在Application Server 已经智能地重新生成了插件文件,以便让 Web 服务器服务静态内容。插件文件将 servlet 和 JSP 的动态 URL 传递回到Application Server。现在要做的就是配置Web服务器来对静态的URL加以识别。我把adhoc.war中的静态内容拷贝到了HTTPServer\htdocs下,同时修改httpd.conf文件,添加

Alias /adhoc/ “e:/IBM/HTTPServer/htdocs/adhoc/”

重启Apache,再次访问,首页又出现了,而停止IHS服务器,你会发现页面有开“天窗”,说明访问的静态资源是在Apache上的。于是我开启了IHS的deflate压缩功能,同时加上Expires头部,那么那些经常处理业务的人员,就不用每次都下载重复的图片,重复的CSS了,而且发请求得到304 Not Modified的动作,都会被省略(刷新的时候不会,但点击页面的时候就会少很多request)。

web speed after Optimization

大小从415K缩小到106K,时间减少到1.48S,提升的空间还是很大的。

当然好技术不能滥用,过度的优化也是万恶之源——简单如动静分离也会带来应用发布更新上的不便,在行动前要了解自己现有的性能情况,明确自己的目的,分析自己的网络拓扑,然后规划好详细的优化步骤,确保这些动作都是可以回滚的。在 WebSphere Application Server 中处理静态内容 这篇文章是你动手前所需要好好阅读的。

摘录总结性的一段

在什么情况下您会选择每一个先前所描述的选项呢?您如何权衡每一个解决方案的利弊呢?下面一组指导原则可以帮助您对静态内容作出决定:

  • 如果您在 WebSphere 的安装中性能不成什么问题,那么请不要想那些更复杂的设置。将您的静态内容保存在 WAR 文件中然后让 file serving servlet 服务它们会比较容易且更加节省成本。
  • 如果在 WebSphere 的安装中性能是个问题,那么就请将文件解压缩,这样会提高您站点的整体性能。但是,解除打包与替换静态内容可能影响效率,除非这个过程可以通过使用上面提到的技术来重复。
  • 如果您有性能需要,并且有能力支付这项花费,那么从长远看最好的解决方案是使用高速缓存代理服务器。像 WebSphere Edge Server 这样的产品(包括执行诸如负载平衡、动态(JSP/servlet)高速缓存以及内容管理这样任务的组件)可以提供额外的性能帮助。

http://www.redbooks.ibm.com/Redbooks.nsf/RedbookAbstracts/tips0223.html?Open 这篇tip是说明如何在WebSphere上实施动静分离的。

优化你的前端-《高性能网站建设指南》读后感

2009年6月3日 hashei 没有评论

之前的几篇文章,都是从中间件的角度来思考程序该如何优化。可是我们知道,一个应用的响应时间,除了从中间件接受请求到返回请求之间的处理时间,还包括在网络上传输的时间、浏览器展现的时间。如果你的应用是对Internet提供服务的,就不得不考虑这一层情况,否则中间件、数据库做了大量优化,能承担很大的并发量,却因为前端没有做过优化导致响应时间过长、用户体验变差,那么是相当郁闷的一件事。

我自己也亲身经历过这样的情况。一个OA项目开发完成后需要做性能测试,发现登录的响应速度很慢,loadrunner显示的吞吐率很高,完成的事务数却不多。用TPV查看WebSphere的使用率,发现JVM回收很正常,于是以为瓶颈在数据库查询上,但是数据库查询SQL执行的很快。最后用Firefox启用Firebug插件,不看不要紧,一看吓一跳:首页有8M大。虽然是内网,但也禁不住这么折腾啊。原来是客户上传了一张照片,程序没有做任何处理就在首页作为新闻放出了缩略图,所以网络流量很高,但是完成的登录数寥寥无几。

于是花了两天时间,在路上和中午阅读了一下《 高性能网站建设指南》。本书是由原Yahoo的Chief Performance撰写。书很薄,2个小时就能看完,但是内容却很丰富,15章章章有精彩。除了要修改代码的“减少HTTP请求”、“使用外部和CSS”、“避免CSS表达式”、“使Ajax可缓存”,更多的是不用修改任何代码,只要做一些配置就能享受到的性能提升——“添加Expires头”、“将样式表放在顶部”、“将脚本放在底部”、“精简JavaScript”、“配置Etag”。虽然这些内容似乎网上随处可见,但是原理解释到位,又结合实验数据说明,外加完整的示例代码的文章却不多见。看完这本书,可以让你不仅知其然,更知其所以然。

我的博“聚沙成塔-小哈的记事簿”也根据这些原则做了优化,把图片和CSS的Expires头都设置为了“增加10年”,这样第二次访问我的网页会迅速很多。同时启用了WordPress2.7默认关闭的gzip功能,同时使用了smartoptimizer工具来压缩CSS和JS,这样整个页面的传输量小了近1/3。由此我也能停用了SuperCache插件(其实就俺这些访问量用不着supercache,当时启用也是为了访问速度的考虑),启用Postviews来记录文章访问的情况。就这么简简单单的一些配置,让我的Yslow标准成绩从D提升到了C(还有些优化牵涉到CSS的修改,本人不是很擅长,还有些方面因为是个人博客不能避免的会引用到其它的服务),Small Site or Blog成绩为B。

怎么样,有没有兴趣买来读一读。如果只想具体了解一些的话,可以先看看Yahoo的这篇文章《Best Practices for Speeding Up Your Web Site》,和大牛Fenng《高性能网站建设指南》读后随感

最后附上简单有效的配置,在.htaccess文件中,新加入

<IfModule mod_expires.c>
<FilesMatch “\.(gif|jpg|jpeg|png|swf|css|js|htm?|xml|txt)$”>
ExpiresActive On
ExpiresDefault “access plus 10 years”
</FilesMatch>
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*\.(js|css))$ smartoptimizer/?$1
<IfModule mod_expires.c>
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*\.(js|css|htm?|xml|txt))$ smartoptimizer/?$1
</IfModule>
<IfModule !mod_expires.c>
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*\.(gif|jpg|jpeg|png|swf|css|js|htm?|xml|txt))$ smartoptimizer/?$1
</IfModule>
</IfModule>
<FilesMatch “\.(gif|jpg|jpeg|png|swf|css|js|htm?|xml|txt)$”>
FileETag none
</FilesMatch>

即可添加长期的Expires头,转发js、css被smartoptimizer压缩,关闭Etag。

在根目录的index.php中define(‘WP_USE_THEMES’, true);后添加

if(ereg(‘gzip’,$_SERVER['HTTP_ACCEPT_ENCODING'])){
if(substr($_SERVER['REQUEST_URI'],0,10)!=’/wp-content/uploads/’)
ob_start(‘ob_gzhandler’);
}

wordpress的gzip压缩功能。