引言
上次在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]
...
阅读全文…
上文中所介绍的启用安全性的方法可以使用在简单的、非分布式的和独立应用服务器类型的运行时环境中,但是如果面对企业应用中如下的情况: 需要同其他使用 LDAP 的应用程序的互操作、需要集成原有的ACL来集中管理……这时候就要配置原有的LDAP服务器作为WebSphere安全性的认证方式(Authentication)。
要达成的任务:本例是在建立profile过程中就启用了管理控制台安全性,用户名和密码都为wasadmin,现在添加LDAP作为认证方式的补充。
一个典型的拓扑环境如下图:

操作过程
在“安全性”中点击“安全管理、应用程序和基础结构”,在用户帐户存储库中选用“联合存储库”,点击“设置为当前”。
点击配置,在“域中的存储库”里点击“将基本条目添加至域”,点击“添加存储库”
“存储库标识”填写便于记忆和管理的名字,这里写成“LDAP”;“目录类型”选择为“定制”,主机名填写LDAP服务器的主机名或IP地址,端口默认389;故障转移主机视实际情况填写。点击应用。
此时“组属性定义”由灰变可选,点击之。在“组成员属性名称”里填写“guid”,点击保存配置。
此时进入到“存储库应用”页面,刚才添加到存储库已经出现,在“用于在域中唯一标识这组条目的基本条目的专有名称”中输入刚才设置的存储库标识“LDAP”。此存储库中基本条目的专有名称则是LDAP域名的名称,例如“dc=ibm,dc=com”,点击应用。
在安全性首页面点击应用,勾选管理安全性,去掉应用程序安全性和Java 2安全性,点击应用,保存配置。
重启应用服务器,此时在“用户和组”的“管理用户”中,可以搜索到LDAP服务器中的用户。接下来你可以在管理用户角色中为某些用户分配was管理员、操作员、配置员、监视员等角色,或者为应用程序组件启用认证机制,这样访问应用时需要输入LDAP中的用户名密码。
记得小时候有一次出去春游,带队的老师一直喜欢唠叨《方世玉》里李国邦的“安全第一”,那时候不怎么看得起这个懦弱胆小、明哲保身的胖男人,“安全第一”的口头禅也成了我调侃的对象。但是如今回想起他为信守承诺挺身而出并付出生命的镜头,却觉得他是电影里最贴近我们的普通人。
跑题了那么多,为的是说明WebSphere中启用管理安全性的必要性——否则谁都可以进入你的控制台修改配置,就算开发阶段没有安全要求,但是WebSphere没有Weblogic的那种锁定模式,所以当两个人同时修改配置并保存时,往往会发生操作丢失和冲突的问题。所以接下来介绍针对控制台的安全性设置,当然最直接的就是在安装profile的时候就启用管理安全性。
在管理控制台-安全中启用“全局安全性”,并把“应用程序安全性”、“执行Java 2安全性”选项前的勾去掉——我们今天只考虑控制台的安全性。
接下来对于“用户注册表”的选择,有三种方法:
最简单的——配置本地操作系统用户
-
- 单击安全性 > 全局安全性。
- 在“用户注册表”下,单击本地操作系统。
- 在服务器用户标识字段中输入有效用户名。
- 在服务器用户密码字段中输入用户密码。
- 可选: 选中授权时忽略大小写选项以使 WebSphere Application Server 在您使用缺省授权时能够执行不区分大小写的授权检查。
- 单击确定。
这里的用户标识和密码,是指操作系统的用户和密码。就是说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。
阅读全文…
要进行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,首先你会看到
点击展开大图
这是一个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分钟,还有垃圾回收的速率(垃圾产生多并非不好,反而是吞吐率高的一种表现)。

让我们再切回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个组件各司其职——IBM Http Server处理静态文件,WebSphere Application Server处理动态内容——所谓的“动静分离”。
先了解一下WAS是如何处理静态内容的:
静态内容被返回到用户的方式至少有三种。它们是:
- 静态内容通过 WebSphere Application Server 中的 File Serving 功能从 WAR 文件返回(缺省情况)
- 静态内容从 Web 服务器返回
- 静态内容从 Caching Proxy Server 返回,如从 WebSphere Edge Server(以下称为 Edge Server)产品中的 Caching Proxy Server 返回。
我们来看一个例子,下图中的应用程序是默认安装的BusinessObjects的Crystal Reports Explorer组件:
简洁的页面,却也有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)。
大小从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上实施动静分离的。
之前的几篇文章,都是从中间件的角度来思考程序该如何优化。可是我们知道,一个应用的响应时间,除了从中间件接受请求到返回请求之间的处理时间,还包括在网络上传输的时间、浏览器展现的时间。如果你的应用是对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压缩功能。
最及时的声音