工作中的点点滴滴,慢慢积累。

发布新日志

  • websphere报Connection reset by peer的原因

    2007-01-19 11:16:25

    经常出现的Connection reset by peer: 原因可能是多方面的,不过更常见的原因是:
    ①:服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;
    ②:客户关掉了浏览器,而服务器还在给客户端发送数据;
    ③:浏览器端按了Stop;
  • oracle学习二

    2007-01-16 16:38:03

    windows下的目录在C:\oracle\admin\oracle\pfile下的init.ora文件里的job_queue_processes参数代表oracle最大接收的进程数。
    unix下的目录是/home/app/oracle/admin.DB_NAME/pfile/initORACLE_SID.ORA

    oracle9i net services 的tnsnames.ora文件在windows与unix下的目录在
    windows2000下:C:\oracle\ora92\network\admin\tnsnames.ora
    UNIX 下:/home/app/oracle/product/90.1/network/admin/tnsnames.ora

    服务器端有listener.ora用来与客户端进行通讯的监听配置文件
    windows2000下 C:\oracle\ora92\network\admin\listener.ora
    /home/app/oracle/product/9.2.0/network/admin/listener.ora

    在windows系统中启动监听进程的启动方法
    一:命令行语句,C:\〉lsnrctl start(stop)
    二:在控制面板\管理工具\服务中启动(关闭)oracleorahome92TNSListener的服务。

    当客户端的机器名host变了,服务器端的监听配置文件的host也需要改,并且要一致才可以连接上。但是如果host处写上ip地址就不会有这样的问题了。

    今天到此为止了!




  • eclipse

    2007-01-16 11:32:37

    eclipse的使用真难,我觉得是挺难得,我想在新建一个类,结果半天也激活不了“完成”的按钮,折腾了我半天终于找到原因了,原来我没有输入类名,哈哈。。。。。。。。哈哈。。。。。。。。想想自己都觉的好笑。
    不过还是觉得eclipse作为java的开发工具也是很好的。
    哈哈。。。。。。。哈哈。。。。。。。继续笑。
  • loadrunner调用java的类二

    2007-01-12 16:54:27

    昨天晚上发现,如果java的类的接口是数组或者别的类型的参数,Loadrunner就很难处理了,必须要把接口转变成简单类型才好进行参数化的处理。

    昨天导入的是简单的类文件,如果这个类又调用了其他的类,别的类在jar包中,不需要把jar包解压,然后把类一一导入,只需要在CLASSPATH中把相关jar包的路径加入就好。

  • loadrunner调用java的类

    2007-01-11 13:11:09

    最近公司需要测试几个具有一定功能类的性能,虽然我觉得这已经是白盒测试的范畴了,但是领导要求这样做,我也就只好进行技术的研究.要求就是能够传参数给类,并且可以接收到类返回的参数,并且进行正确与否的判断。
    第一步,总的思路。
    以前我都是用loadrunner直接进行录制,但是有些协议的确不好弄不知道怎样进行录制,像vb,c++,java语言做的东西我觉最简单的方式就是直接调用相关的类文件,动态链接库,直接用代码的方式进行调用。在这种思想下,于是试着在loadrunner中写程序调用java类。
    第二步,做符合要求的实验用的java类。
    说实话难度太大了对我来说,我一点不懂java,好在我知道C++,但是java的代码编写方式和编译环境,都是我从来没有见过的。慢慢学,多多问,好不容易最初级别的搞定了这些,首先要装j2sdk在系统盘下。,然后再系统环境变量中添加上%java_home%\bin;就可以用cmd命令进行java的编译和运行的操作了。编译和运行的命令分别是你所写java类目录下的运行javac test.java和java test 参数,例如,如果你的类在c:\test目录下,你就应该在cmd中使用cd \test,转到这个目录下,再用javac test.java和java test 参数进行操作。
    我从网上找到了一个现成的简单的java类,现将源代码放在下面。
    package MAIN;
    import java.io.PrintStream;
    public class Birthday
    {
            public String year;
            public String month;
            public String day;
            public Birthday()
            {
                year="1900";
                month="01";
                day="01";
            }
            public Birthday(String y,String m,String d)
            {
                year=y;
                month=m;
                day=d;
                System.out.println("OK");
            }
            public String getBirthday()
            {
                String fullbirthday=month+'/'+'/'+day+'/'+year;
                return fullbirthday;
            }
    }
    类很简单,用上述方法编译也是很容易就通过了。

    第三步,如何在Loadrunner中将这个类调用起来。
    想了很久,决定用java vuser这种脚本的方式进行写java代码,这点代码是一定要写的。熟悉一阵子java语言之后,决定用import将类引入,于是问题又来了,*.class文件该放在什么地方呢,中间试验的过程暂且不表,将最后结果写在这里就好。目前我得到的结果是将*.class文件放在,你loadrunner安装的路径下classes\main这个目录下。懂java的很容易就搞定了这一步,包括路径和import的语句。
    于是Loadruner中的java代码如下:
    import lrapi.lr;
    import MAIN.Birthday;

    public class Actions
    {

        public int init() {
            return 0;
        }//end of init


        public int action() {
                    Birthday bir=new Birthday("1981","6","1");
            //bir.getBirthday
            System.out.println(bir.getBirthday());
            return 0;
        }//end of action


        public int end() {
            return 0;
        }//end of end
    }
    注意红色的字体,这里完成了对类的调用和初始化,并且传递了参数进去,最后调用类的方法,把一个值返回,并打印出这个值,至于怎样检查这个值是否正确就很简单了,这里就不累赘了.
    一天一点积累!工作上我的座游铭。

    最后发现,loadrunner中有很详细介绍资料,哎,感慨自己的英文水平呀!
    最后发现loadrunner导入类的路径是可以自己设置的,不需要专门把所有的类都放到classes目录下,具体设置的地方在runtime settings里面class path项里进行设置就可以了,每一个脚本都可以这样设。关于具体的并发的时候如何取脚本,这些有关于laodrunner的布置问题,这里不多说。

  • java的import、package、文件命名规则

    2007-01-10 17:49:36

    以下文章属网上收集,不属于本人原创。以后再转的时候,我会留意把作者也注上的。

    java的import、package、文件命名规则

     package语句:由 于java编译器为每个类生成一个字节码文件,且文件名与类名相同,因此同名的类有可能发生冲突。为了解决这一问题,java提供包来管理类名空间,包实 际提供了一种命名机制和可见性限制机制。而在java的系统类库中,把功能相似的类放到一个包(package)中,例如所有的图形界面的类都放在 java.awt这个包中,与网络功能有关的类都放到java.net这个包中。用户自己编写的类(指.class文件)也应该按照功能放在由程序员自己 命名的相应的包中,例如上例中的javawork.helloworld就是一个包。包在实际的实现过程中是与文件系统相对应的,例如 javawork.helloworld所对应的目录是path\javawork\helloworld,而path是在编译该源程序时指定的。比如在 命令行中编译上述HelloWorldApp.java文件时,可以在命令行中敲入"javac -d f:\javaproject HelloWorldApp.java",则编译生成的HelloWorldApp.class文件将放在目录f:\javaproject\ javawork\helloworld\目录下面,此时f:\javaprojcet相当于path。但是如果在编译时不指定path,则生成的. class文件将放在编译时命令行所在的当前目录下面。比如在命令行目录f:\javaproject下敲入编译命令"javac HelloWorldApp.java",则生成的HelloWorldApp.class文件将放在目录f:\javaproject下面,此时的 package语句相当于没起作用。

      但是,如果程序中包含了package语句,则在运行时就必须包含包名。例如, HelloWorldApp.java程序的第一行语句是:package p1.p2;编译的时候在命令行下输入"javac -d path HelloWorldApp.java",则HelloWorldApp.class将放在目录path\p1\p2的下面,这时候运行该程序时有两种方 式:
      第一种:在命令行下的path目录下输入字符"java p1.p2.HelloWorldApp"。
      第二种:在环境变量classpath中加入目录path,则运行时在任何目录下输入"java p1.p2.HelloWorldApp"即可。

      
    import语句:如 果在源程序中用到了除java.lang这个包以外的类,无论是系统的类还是自己定义的包中的类,都必须用import语句标识,以通知编译器在编译时找 到相应的类文件。例如上例中的java.awt是系统的包,而javawork.newcentury是用户自定义的包。比如程序中用到了类 Button,而Button是属于包java.awt的,在编译时编译器将从目录classpath\java\awt中去寻找类Button, classpath是事先设定的环境变量,比如可以设为:classpath=.;d:\jdk1.3\lib\。 classpath也可以称为类路径,需要提醒大家注意的是,在classpath中往往包含多个路径,用分号隔开。例如classpath=.;d:\ jdk1.3\lib\中的第一个分号之前的路径是一个点,表示当前目录,分号后面的路径是d:\jdk1.3\lib\,表示系统的标准类库目录。在编 译过程中寻找类时,先从环境变量classpath的第一个目录开始往下找,比如先从当前目录往下找java.awt中的类Button时,编译器找不 着,然后从环境变量classpath的第二个目录开始往下找,就是从系统的标准类库目录d:\jdk1.3\lib开始往下找java.awt的 Button这个类,最后就找到了。如果要从一个包中引入多个类则在包名后加上".*"表示。

      如果程序中用到了用户自己定义的包中的 类,假如在上面程序中要用到javawork.newcentury包中的类HelloWorldApp,而包javawork.newcentury所 对应的目录是f:\javaproject\javawork\newcentury,classpath仍旧是classpath=.;d:\ jdk1.3\lib\,则编译器在编译时将首先从当前目录寻找包javawork.newcentury,结果是没有找到;然后又从环境变量 classpath的第二个目录d:\jdk1.3\lib\开始往下找,但是仍然没有找到。原因在于包javawork.newcentury是放在目 录f:\javaproject下面。因此,需要重新设定环境变量classpath,设为classpath=.;d:\jdk1.3\lib\;f: \javaproject\ 。所以编译器从f:\javaproject开始找包javawork.newcentury就可以找到。

      
    源文件的命名规则:如 果在源程序中包含有公共类的定义,则该源文件名必须与该公共类的名字完全一致,字母的大小写都必须一样。这是java语言的一个严格的规定,如果不遵守, 在编译时就会出错。因此,在一个java源程序中至多只能有一个公共类的定义。如果源程序中不包含公共类的定义,则该文件名可以任意取名。如果在一个源程 序中有多个类定义,则在编译时将为每个类生成一个.class文件。
  • Java的import语句

    2007-01-10 17:47:41

    以下文章属网上收集,不属于本人原创。

    程序员可以使用两种import语句:

    单类型导入(single-type-import),例如import java.io.File;

    按需类型导入(type-import-on-demand),例如 import java.io.*;

    关于这两种导入类型大家各有所爱,众说纷纭。这里分析一下这两种导入类型的大致工作原理供大家参考。

    单类型导入比较好理解,仅仅导入一个public类或者接口。而对于按需类型导入,有人误解为导入一个包下的所有类,其实不然,看名字就知道,他只会按需导入,也就是说它并非导入整个包,而仅仅导入当前类需要使用的类。

    既然如此是不是就可以放心的使用按需类型导入呢?非也,非也。因为单类型导入按需类型导入对类文件的定位算法是不一样的。java编译器会从启动目录(bootstrap),扩展目录(extension)和用户类路径下去定位需要导入的类,而这些目录进仅仅是给出了类的顶层目录。编译器的类文件定位方法大致可以理解为如下公式:

    顶层路径名 \ 包名 \ 文件名.class = 绝对路径

    对于单类型导入很简单,因为包明和文件名都已经确定,所以可以一次性查找定位。

    对于按需类型导入则比较复杂,编译器会把包名和文件名进行排列组合,然后对所有的可能性进行类文件查找定位。例如:

    package com;

    import java.io.*;

    import java.util.*;

    当你的类文件中用到了File类,那么可能出现File类的地方如

    File  \\ File类属于无名包,就是说File类没有package语句,编译器会首先搜索无名包

    com.File  \\ File类属于当前包

    java.lang.File  \\编译器会自动导入java.lang包

    java.io.File

    java.util.File

    需要注意的地方就是,编译器找到java.io.File类之后并不会停止下一步的寻找,而要把所有的可能性都查找完以确定是否有类导入冲突。假设此时的顶层路径有三个,那么编译器就会进行3*5=15次查找。

    了解以上原理之后,我们可以得出这样的结论:按需类型导入是绝对不会降低Java代码的执行效率的,但会影响到Java代码的编译速度

    查看JDK的源代码就知道SUN的软件工程师一般不会使用按需类型导入。因为使用单类型导入至少有以下两点好处:

    1。提高编译速度。

    2。避免命名冲突。(例如:当你import java.awt.*;import java.util.*后,使用List的时候编译器将会出编译错误)

    当然,使用单类型导入会使用你的import语句看起来很长。

  • BEA WebLogic平台下J2EE调优攻略

    2007-01-10 16:05:01

    BEA WebLogic平台下J2EE调优攻略
    目录

    前 言
    第一章 应用程序调优
    1.1.1 通用代码调优
    1.1.2 减小没有必要的操作
    1.1.3 使用合适的类型
    1.1.4 尽量使用pool,buffer和cache
    1.2 JDBC代码调优
    1.2.1 严格资源使用
    1.2.2 实用技巧
    1.2.3 优化SQL语句
    1.3 Web代码调优
    1.3.1 HttpSession的使用
    1.3.2 JSP代码调优
    1.3.3 Servlet代码调优
    1.4 JMS代码调优
    1.4.1 注意必要的事项,避免使用不必要的特征
    1.4.2 消息类型的选择
    1.4.3 确认方式的选择和JMS事务
    1.5 EJB代码调优
    1.5.1 有效使用设计模式
    1.5.2 使用EJB和WebLogic的特性
    1.5.3 缓存资源
    1.5.4 如何选择和使用Entity Bean
    1.5.5 其他的一些小技巧
    第二章 应用服务器调优
    2.1 JVM调优
    2.1.1 垃圾收集和堆大小
    2.1.2 jRockit调优
    2.2 Server调优
    2.2.1 尽量使用本地I/O库
    2.2.2 调整默认执行线程数
    2.2.3 调整连接参数
    2.2.4 创建新的执行队列
    2.3 JDBC调优
    2.3.1 调整连接池配置
    2.4 WEB调优
    2.4.1 调整WEB应用描述符
    2.5 JMS调优
    2.6 EJB调优
    2.6.1 调整pool和cache
    2.6.2 优化事务隔离级别和事务属性
    2.6.3 其他一些小技巧
    第三章 数据库调优
    3.1.1 Oracle性能优化
    3.1.2 Oracle的其他调整
    第四章 操作系统调优
    4.1 操作系统调整
    4.1.1 HP-UX
    4.1.2 Solaris
    4.1.3 AIX
    4.1.4 Linux
    4.1.5 Windows
    第五章 性能监控和性能分析
    5.1 性能瓶颈
    5.2 操作系统监控
    5.3 数据库监控
    5.4 WebLogic监控
    5.4.1 JVM监控
    5.4.2 Console监控
    5.4.3 实用工具分析
    5.5 应用程序分析
    总结
    参考文献
    关于作者

    前 言 (目录)

       随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供商的重视。而对于最终客户来说,在一个高效、稳定地实现他 们的业务需求已经是他们的基本要求。所以J2EE调优显得非常重要,而BEA WebLogic Server是业界领先的应用服务器,BEA WebLogic平台下的J2EE调优也就尤为重要,她将为我们提供普遍的J2EE调优方案。最近网络、杂志上的J2EE调优文章层出不穷。本人也将自己 平时工作中的一些经验积累分享给大家,抛砖引玉。

      本文从J2EE应用架构(下图)来分别剖析系统调优,首先我们一般会从应用程序出 发,去审核代码,做到代码级的优化,然后再调整应用服务器(BEA WebLogic8.1)和数据库 (Oracle9i)的参数,最后当然是调整操作系统和网络的性能(包括硬件升级)。诚然,在我遇到的很多项目中,都是出现了性能问题后才想到调优,而且 一般都是先进行系统参数调整,实在解决不了才会对代码进行检查.实际上,我们应当将代码级的调优放在应用设计时来做,测试生产时修改代码将是一件极其痛苦 的事情。


    WebLogic平台J2EE应用架构


    第一章 应用程序调(目录)
    1.1.1 通用代码调优

    1.1.2 减小没有必要的操作
       对象的创建是个很昂贵的工作,所以我们应当尽量减少对象的创建,在需要的时候声明它,初 始化它,不要重复初始化一个对象,尽量能做到再使用,而用完后置null有利于垃圾收集。让类实现Cloneable接口,同时采用工厂模式,将减少类的 创建,每次都是通过clone()方法来获得对象。另外使用接口也能减少类的创建。对于成员变量的初始化也应尽量避免, 特别是在一个类派生另一个类时。

       异常抛出对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为, fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被 抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。 异常只能用于错误处理,不应该用来控制程序流程。

      此外, 建议关闭Debug输出,尽量少用串行化、同步操作和耗时昂贵的服务(如Date())。

    1.1.3 使用合适的类型

      当原始类型不能满足我们要求时,使用复杂类型。String和StringBuffer的区别自不必说了,是我们使用最多的类型,在涉及到字符运算时,强烈建议使用StringBuffer。在做String匹配时使用intern()代替equal()。

      带有final修饰符的类是不可派生的, 如果指定一个类为final,则该类所有的方法都是final。

      Java编译器会寻找机会内联所有的final方法,这将能够使性能平均提高50%。类的属性和方式使用final或者static修饰符也是有好处的。

      调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。所以尽量使用局部变量。

      ArrayList和Vector,HashMap和Hashtable是我们经常用到的类,前者不支持同步,后者支持同步,前者性能更好,大多数情况下选择前者。

    1.1.4 尽量使用pool,buffer和cache
      使用pool、buffer和cache能大大提高系统的性能,这在J2EE的大部分技术中都是适用的。

       在WebLogic中就大量使用了池:JDBC Connection Pool、Socket Pool、Object Pool和Thread Pool。I/O操作中,buffer是必须的,特别是对大文件的操作,不然容易造成内存溢出。字节操作最快,所以尽可能采用write(byte []),Buffered FileOutputStream比Buffered FileWriter要快,因为FileWriter需要Unicode到Byte的转换。

      而后面讲到的JDBC、JSP、EJB和JMS我们都非常建议使用buffer和cache。为HttpServletResponse设置buffersize,使用wl-cache,缓存在JNDI树上获取的对象等等。

      此外,使用JDK 1.4的非阻塞I/O对性能也有很大提高。

    1.2 JDBC代码调优
    1.2.1 严格资源使用
       JDBC代码调优最大的原则就是使用WebLogic的连接池,而不是自己直连数据库。在我接触的很多自己实现连接池的项目中,大部分遇到死锁和连接泄 漏的问题,最后得不得修改代码。而WebLogic提供了功能强大,性能良好的数据库连接池,我们要做的只是封装一个连接管理类,从JNDI树上获取数据 源并缓存,得到连接,并提供一系列关闭数据库资源的方法。

      对任何资源使用的原则是用完即关,不管是数据库资源、上下文环境,还是文 件。数据库资源的泄漏极易造成内存泄漏,乃至系统崩溃。在使用完数据库资源后依次关闭ResultSet,Statement和Connection,而 在一个数据库连接多次进行数据库操作时要特别注意ResultSet和Statement依次关闭。

    try{
      //open connection
      pstmt =conn.prepareStatement(strSql1);
      pstmt.executeUpdate();
      pstmt.close();
      pstmt =conn.prepareStatement(strSql2);
      rs=pstmt.executeQuery();
      while (rs.next()){
      //process
     }
    rs.close();
    pstmt.close();
     }catch(Exception e){
      //close rs,psmt,con
    }finally{
      //close rs,psmt,con
    }

    1.2.2 实用技巧
       在JDBC操作中还有一些小的技巧跟大家分享:由于获取连接时默认自动提交方式,使用connection.setAutoCommit(false) 关闭自动提交,使用PreparedStatement,批量更新,业务复杂或者大数据量操作时使用存储过程,尽量使用RowSet,此外设置记录集读取 缓存FetchSize和设置记录集读取方向FetchDirection对性能也有一定的提高。

    1.2.3 优化SQL语句
       SQL语句的优化牵涉到很多数据库的知识,需要与索引配合,因此需要DBA对代码中的SQL进行检查测试。常见的,select *不提倡使用,效率极差,建议显式获取列,即使是所有字段也应罗列,而取总数时使用count(*),为提高cache的命中率,尽量做到SQL重用。对 于大数据量的查询,可以充分利用Oracle数据库的特性,每次取出m-n行的数据,实现分页查询。另外,提高性能的好选择可能就是把所有的字符数据都保 存为Unicode,Java以Unicode形式处理所有数据,因此,数据库驱动程序不必再执行转换过程。

    1.3 Web代码调优
    1.3.1 HttpSession的使用
      应用服务器保存很多会话时,容易造成内存不足,所以尽量减少session的使用,放置session
    里的对象不应该是大对象,最好是简单小对象,实现串行化接口。当会话不再需要时,应当及时调用invalidate()方法清除会话。而当某个变量不需要时,及时调用removeAttribute()方法清除变量。请勿将EJB对象放置在session中。

    1.3.2 JSP代码调优
       目前,在JSP页面中引入外部资源的方法主要有两种:include指令,以及include动作。 include指令:例如<%@ include file="copyright.html" %>,该指令在编译时引入指定的资源。在编译之前,带有include指令的页面和指定的资源被合并成一个文件。被引用的外部资源在编译时就确定, 比运行时才确定资源更高效。
    include动作:例如<jsp:include page="copyright.jsp" />。该动作引入指定页面执行后生成的结果。由于它在运行时完成,因此对输出结果的控制更加灵活。但是,只有当被引用的内容频繁地改变时,或者在对 主页面的请求没有出现之前,被引用的页面无法确定时,使用include动作才合算。

      对于那些无需跟踪会话状态的jsp,关闭自 动创建的会话可以节省一些资源。使用如下page指令: <%@ page session="false"%> ;尽量不要将JSP页面定义为单线程,应设置为<%@page isThreadSafe=”true”%>;在JSP页面最好使用输出缓存功能,如: <%@page buffer="32kb"%>;尽量用wl:cache定制标记来缓存静态或相对静态的内容,缓存jsp:include操作的结果能显著提高应 用程序的运行性能。

    1.3.3 Servlet代码调优
       Servlet代码调优比较简单:在Servlet之间跳转时,forward比sendRedirect更有效;设置 HttpServletResponse 缓冲区,如:response.setBufferSize(20000);在init()方法里缓存静态数据,而在destroy()中释放它;建议在 Servlet里使用ServletOutputStream输出图片等对象;避免在Servlet和Jsp中定界事务等。

    1.4 JMS代码调优
    1.4.1 注意必要的事项,避免使用不必要的特征
       JMS提供了强有力的消息处理机制,但是为了最大限度的提高JMS系统的性能,应避免使用不需要使用的特征,同时也要注意必要的事项。比如:尽量使用接 收程序能直接使用的最简单、最小的消息类型;消息选择器要尽可能简单(最好不使用),尽量不要使用复杂的操作符,如like、in或者between等, 使用字符串数据类型的速度最慢;务必为特定的应用程序定义特定的JMS连接工厂,并且禁用默认的JMS连接工厂;不要在javax.*与 weblogic.*的名字空间中使用JNDI名称;尽量使用异步消费者,线程不必封锁以等待消息的到达;使用完JNDI树上的资源后注意关闭。

    1.4.2 消息类型的选择
       标准JMS提供了五种消息类型,而TextMessage应用最为普遍, 当发送的消息是几种原始数据类型的集合体时,最好使用MapMessage消息类型,而不要使用ObjectMessage,以便减少不同系统间的耦合。 此外消息是否使用压缩要慎重考虑,压缩未必能减少消息大小。如果生产者、消费者和目的地并置在同一WebLogic Server内部,通常不使用压缩。WebLogic特有的XMLMessage能为运行于消息主体之上的消息选择器提供内嵌式支持,而且易于数据交换。 因此,建议应用程序之间传送消息使用XML消息格式,而应用程序内部间传送消息使用二进制消息格式。

    1.4.3 确认方式的选择和JMS事务
       使用事务性会话时,尽量使用恰当的消息确认方式:如果需求允许,使用NO_ACKKNOWLEDGE;非持久的订阅者使用 DUPS_OK_ACKNOWLEDGE或者MULTICAST_NO_ACKNOWLEDGE。而使用JTA的UserTransaction,确认方 式将被忽略。在使用JMS事务时,无效的消息会导致事务的回滚,以致消息重发这样的死循环。此时,可以将无效消息发送到错误消息队列,并提交JMS事务, 这将确保消息不会再次传递。

    1.5 EJB代码调优
    1.5.1 有效使用设计模式
       GoF 的《设计模式》为我们实现高性能、易扩展的J2EE应用提供理论保障和技术支持。而EJB作为J2EE的核心组件和技术,善用设计模式对系统性能影响很 大。Service Locator 和Value Object 已为我们所熟悉,Floyd Marinescu的《EJB Design Patterns》中的Session Fa?ade、Message Fa?ade、EJB Command和Data Transfer Object等设计模式更是为我们提供设计典范:缓存对EJBHome的访问;使用门面模式,不暴露Entity Bean,用Session Bean封装Entity Bean;如果可以异步处理,则用MDB代替Session Bean;封装业务逻辑在轻量级JavaBean中;使用值对象等简单对象传递数据;不直接使用get/set方法操作Entity Bean。当然过度使用模式或者牵强套用模式也是不提倡的,总的原则就是减少网络流量,改进事务管理。

    1.5.2 使用EJB和WebLogic的特性
       使用EJB和WebLogic的新特性往往能提高性能。与EJB2.0特性相关的技巧有:一个Application中使用本地接口,对于Entity Bean肯定使用本地接口,避免远程调用的开销;使用CMP管理关系,而不是BMP,EJB2.0中CMP的性能大大改善,性能和移植性都优于BMP;使 用ejbSelect进行内部查询;使用home方法进行外部查询和批处理; 数据库驱动级联删除等。

      与WebLogic特性相关的 技巧有:使用自动生成主键,WebLogic为Oracle和Sqlserver两种数据库的CMP提供了自动生成主键功能,节约了Entity Bean产生主键的时间,同时设key-cache-size不小于100;WebLogic管理事务性能更好,使用容器管理,而不是Bean管理事务; WebLogic提供了为CMP动态查询和批量插入功能,对性能也有很大帮助。

    1.5.3 缓存资源
       对SLSB或者MDB来说,使用setMesssageDrivenContext()或者ejbCreate()方法缓存特定资源,在 ejbRemove()方法里释放; 对SLSB或者MDB来说,使用setSessionContext()或者ejbCreate()方法缓存特定资源,在ejbRemove()方法里释 放;对Entity Bean来说,使用setEntityContext ()方法缓存特定资源,在unSetEntityContext ()方法里释放。

    1.5.4 如何选择和使用Entity Bean
      1. 在设计EJB时,要适当考虑EJB的粒度, 细粒度的EJB在事务管理和资源管理的开销太大,尽量创建粗粒度的 EJB , 不要太粗,粗到能满足实际需求就可以;

      2. Entity Bean不是唯一方式,如果只有一个很小的数据子集被经常改变,建议采用JDO;

      3. 在操作大数据量的时候,直接采用JDBC比Entity Bean更有效;

      4. 避免采用返回很大数据组的finder方法,如 FindAll() 方法,因为它的实现代价太大;

      5. 考虑设置域组field groups,减少没有必要并昂贵的属性加载,如BLOB;

      6. 对于EJB1.1或者BMP,可以设置is-modified-method-name属性,根据isModified()的值来判断是否调用ejbStore()等方法,减少没有必要运算;

      7. 避免连接多个表创建BMP,可以使用视图,存储过程或者O/R Mapping等方式。

    1.5.5 其他的一些小技巧
      1. 考虑使用 javax.ejb.SessionSynchronization 接口,提供在Rollback之后恢复数据的方法: afterBegin(), beforeCompletion(), afterCompletion();
      2. 使用完SFSB之后,调用remove()方法释放实例;
      3. 假如你不需要EJB服务的时候,建议使用普通Java类;
      4. 避免EJB之间相互调用;
      5. 使用多读模式。

    第二章 应用服务器调优(目录)
    2.1 JVM调优
    2.1.1 垃圾收集和堆大小

       垃圾收集(GC)是指JVM释放Java堆中不再使用的对象所占用的内存的过程,而Java堆(Heap)是指Java应用程序对象生存的空间。堆大小 决定了GC的频度和时间。堆越大,GC频度低,速度慢。堆越小,GC频度高,速度快。所以GC和堆大小是一组矛盾。为了获取理想的Heap堆大小,需要使 用-verbosegc参数(Sun jdk: -Xloggc:<file>)以打开详细的GC输出。分析GC的频度和时间,结合应用最大负载所需内存情况,得出堆的大小。
    通常情 况下,我们建议使用可用内存(除操作系统和其他应用程序占用之外的内存)70-80%,为避免堆大小调整引起的开销,设置内存堆的最小值等于最大值即:- Xms=-Xmx。而为了防止内存溢出,建议在生产环境堆大小至少为256M(Platform至少512M),实际环境中512M~1G左右性能最佳, 2G以上是不可取的,在调整内存时可能需要调整核心参数进程的允许最大内存数。对于sun和hp的jvm,永久域太小(默认4M)也可能造成内存溢出,应 增加参-XX:MaxPermSize=128m。建议设置临时域-Xmn的大小为-Xmx的1/4~1/3, SurvivorRatio为8。

       为了获得更好的性能,建议在启动文件设置WebLogic为产品模式,此时sun和hp jvm JIT引擎为-server,默认情况下打开JIT编译模式对性能也有帮助。调整Chunk Size和Chunk Pool Size也可能对系统的吞吐量有提高。此外还需关闭显示GC: -XX:+DisableExplicitGC。

      当然在Intel平台上使用jRockit(使用参数-jrockit)无疑大大提高WebLogic性能。

    2.1.2 jRockit调优
       jRockit支持四种垃圾收集器:分代复制收集器、单空间并发收集器、分代并发收集器和并行收集器。默认状态下,JRockit使用分代并发收集器。 要改变收集器,可使用-Xgc:<gc-name>,对应四个收集器分其他为gencopy, singlecom, gencon以及parallel。为得到更好的响应性能,应该使用并发垃圾回收器:-Xgc:gencon,可使用-Xms和-Xmx设置堆栈的初始大 小和最大值,要设置护理域-Xns为-Xmx的10%。而如果要得到更好的性能,应该选用并行垃圾回收器:-Xgc: parallel,由于并行垃圾回收器不使用nursery,不必设置-Xns。

      如果你的线程大于100或者在linux平台下,可以尝试使用瘦线程模式:-Xthinthread,同时关闭Native IO:-Xallocationtype:global。

      jRockit 还提供了强大的图形化监控工具Jrockit Management Console。欲详细了解JRockit可访问:http://edocs.bea.com/wljrockit/docs81/index.html


    2.2 Server调优
       WebLogic Server的核心组件由监听线程,套接字复用器和可执行线程的执行队列组成。当服务器由监听线程接收到连接请求后,将对它的连接控制权交给等待接收请求 的套接字复用器。然后套接字复用器读取离开套接字的请求,并将此请求及相关安全信息或事务处理环境一起置入适当的执行队列中(一般为默认的执行队列)。 当有一个请求出现在执行队列中时,就会有一个空闲的执行线程从该队列中取走发来的该请求,并返回应答,然后等待下一次请求。因此要提高WebLogic的性能,就必须从调整核心组件性能出发。

    2.2.1 尽量使用本地I/O库
    WebLogic Server有两套套接字复用器:Java版和本地库。采用小型本地库更有效,尽量激活Enable Native IO(默认),此时UNIX默认使用CPUs+1个线程,Window下为双倍CPU。如果系统不能加载本地库,将会抛出 java.lang.UnsatisfiedLinkException,此时只能使用Java套接字复用器,可以调整socket readers 百分比,默认为33%。该参数可以在Console Server Tuning Configuration配置栏里设置。

    2.2.2 调整默认执行线程数
       理想的默认执行线程数是由多方面的因素决定的,比如机器CPU性能、总线体系架构、I/O、操作系统的进程调度机制、JVM的线程调度机制。 WebLogic生产环境下默认的线程为25个,随着CPU个数的增加,WebLogic可以近乎线性地提高线程数。线程数越多,花费在线程切换的时间也 就越多,线程数越小,CPU可能无法得到充分利用。为获取一个理想的线程数,需要经过反复的测试。在测试中,可以以25*CPUs为基准进行调整。当空闲 线程较少,CPU利用率比较低时,可以适当增加线程数的大小(每五个递增)。对于PC Server 和Window 2000,则最好每个CPU小于50个线程, 以CPU利用率为90%左右为佳。由于目前WebLogic执行线程没有缩小线程数的功能,所以应将参数Threads Increase设置为0,同时不应改变优先级的大小。

    2.2.3 调整连接参数
       WebLogic Server用Accept Backlog参数规定服务器向操作系统请求的队列大小,默认值为50。当系统重载负荷时,这个值可能过小,日志中报Connection Refused,导致有效连接请求遭到拒绝,此时可以提高Accept Backlog 25%直到连接拒绝错误消失。对于Portal类型的应用,默认值往往是不够的。Login Timeout和SSL Login Timeout参数表示普通连接和SSL连接的超时时间,如果客户连接被服务器中断或者SSL容量大,可以尝试增加该值。这些参数可以在Console Server Tuning Configration配置栏里找到。

    2.2.4 创建新的执行队列
       创建新的执行队列有助于解决核心业务优先、避免交叉阻塞、死锁和长时间处理的业务等问题。通常会将自己的执行队列和默认的执行队列设置不同的优先级,这 里优先级不应设为9或者10。 定义一个新的执行队列很容易,利用View Excute Queue选项中的Configure a new Excute Queue链接即可定制新的执行队列。创建新的执行队列后,用户需要为应用程序的J2EE组件配置分配策略,以便它可以找到新的队列。举个例子:要将 servlet或jsp捆绑到一个特定的执行队列,必须替换web.xml文件项,将wl-dispatch-policy初始化参数设置为自己的执行队 列名。

    <servlet>
    <servlet-name>servletname</servlet-name>
    <jsp-file>/directoryname/deployment.jsp</jsp-file>
    <init-param>
    <param-name>wl-dispatch-policy</param-name>
    <param-value>NewExecuteQueueName</param-value>
    </init-param>
    </servlet>

      我们可以为一个jsp或者servlet乃至一个WEB应用设置自己的执行队列。同时也可以为EJB设置自己的执行队列。对于执行时间比较长的MDB,建议使用自己的执行队列。

    2.3 JDBC调优
    2.3.1 调整连接池配置

       JDBC Connection Pool的调优受制于WebLogic Server线程数的设置和数据库进程数,游标的大小。通常我们在一个线程中使用一个连接,所以连接数并不是越多越好,为避免两边的资源消耗,建议设置连 接池的最大值等于或者略小于线程数。同时为了减少新建连接的开销,将最小值和最大值设为一致。

      增加Statement Cache Size对于大量使用PreparedStatement对象的应用程序很有帮助,WebLogic能够为每一个连接缓存这些对象,此值默认为10。在保 证数据库游标大小足够的前提下,可以根据需要提高Statement Cache Size。比如当你设置连接数为25,Cache Size为10时,数据库可能需要打开25*10=250个游标。不幸的是,当遇到与PreparedStatement Cache有关的应用程序错误时,你需要将Cache Size设置为0。

      尽管JDBC Connection Pool提供了很多高级参数,在开发模式下比较有用,但大部分在生产环境下不需调整。这里建议最好不要设置测试表, 同时Test Reserved Connections和Test Released Connections也无需勾上。 当然如果你的数据库不稳定,时断时续,你就可能需要上述的参数打开。

      最后提一下驱动程序类型的选择,以Oracle为例, Oracle提供thin驱动和oci驱动,从性能上来讲,oci驱动强于thin驱动,特别是大数据量的操作。但在简单的数据库操作中,性能相差不大, 随着thin驱动的不断改进,这一弱势将得到弥补。而thin驱动的移植性明显强于oci驱动。所以在通常情况下建议使用thin驱动。而最新驱动器由于 WebLogic server/bin目录下的类包可能不是最新的,请以Oracle网站为准: http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc9201.html

    2.4 WEB调优
    2.4.1 调整WEB应用描述符

       WEB应用除代码之外的调优比较简单,仅仅是对一些WEB应用描述符的调整。首先关闭Session Monitoring Enabled,仅仅在Cluster环境下设置Session复制(优先使用内存复制),在保证应用正常运行的情况下,设置较短的Session超时时 间。 同时生产环境下无需检查Jsp和servlet:JSPPage Check Secs和Servlet Reload Check Secs均设为-1,关闭JSPKeep Generated 和JSPVerbose对性能也有帮助。此外,还可以对jsp进行预编译,有两种方法:激活precompile选项;使用weblogic.appc事 先编译,建议采用后者。

    2.5 JMS调优
      1. 增加-Dweblogic.JMSThreadPoolSize=n(至少为5),以提高处理JMS的线程数,在jRockit上增加-XXenablefatspin以减少加锁冲突;
      2. 采用文件存储策略,将同步写策略设置为Direct-Write,同时在windows平台上启用磁盘写入缓存;
      3. 使用分布式目的地时,激活连接工厂Load Balancing Enabled ,Server Affinity Enabled;
       4. 为减少服务器不必要的JMS请求路由,如果多个目的地之间存在事务,则部署在同一JMS服务器上,尽量将连接工厂部署到JMS服务器所在的 WebLogic实例上,集群环境下,则最好将连接工厂部署到集群中的所有服务器上,而集群中每个JMS服务器和目的地成员尽量使用类似的设置;
      5. 启用消息分页存储功能,以释放内存,可以为JMS服务器和目的地设置, 激活Messages Paging Enabled和Bytes Paging Enabled,同时使用限额防止服务器耗尽接收消息的所有可用内存空间;
      6. 在运行WebLogic Server进程之外的生产者务必使用流控制, 并增大Send Timeout;
      7. 将JMS Server Expiration Scan Interval设很大的值,能禁止主动扫描过期消息;
      8. 使用FIFO或者LIFO方式处理目的地消息;
      9. MDB的max-beans-in-free-pool不应大于最大MDB线程数(默认线程数/2+1)。

    2.6 EJB调优
    2.6.1 调整pool和cache

       initial-beans-in-free-pool定义SLSB启动时实例的个数,默认为0,可以调大到正常并发数的大小,以减少初始响应时间。 max-beans-in-free-pool为最大个数,默认1000对SLSB来说,在频繁创建和删除实例的情况下很有帮助,一般不用调整,至少设为 默认线程数,过大容易造成内存溢出。而对Entity Bean来说,由于是匿名的,所以当频繁使用finder、home和create方法时可以调大。

      对SFSB来说,尽量将max- beans-in-cache参数设置得足够的大,以满足Bean实例对最大并发用户数的要求,可以避免有状态会话Bean过多的钝化行为。而idle- timeout-seconds尽量设置小,如果SFSB不用于存储Web应用会话状态可以设置为0。

      对于Entity Bean来说, max-beans-in-cache同样可以首先采用默认值1000,监控实例缓存和钝化的情况,再做适当调整。

       并行策略concurrency-strategy定义了实体Bean如何管理锁,有四种策略: Exclusive、Databse、ReadOnly、Optimistic。效率依次提高,可靠性依次降低,尽量避免使用互斥策略,如果Bean无需 更新操作,使用只读策略,更甚的是,如果Bean的内容不会改变,可设置read-timeout-seconds为0,乐观并行策略时采用事务间缓存策 略,在entity-cache描述符中将cache-between-transactions元素设为true。

    2.6.2 优化事务隔离级别和事务属性
      对EJB组件来说,有四种事务隔离水平:

    • TRANSACTION-SERIALIZABLE:在处理完成之前拒绝其他处理的读入、可扩展性或插入数据操作;
    • TRANSACTION-REPEATABLE-READ:防止处理修改正在被其他处理调用的数据;
    • TRANSACTOIN-READ-COMMITTED:防止对正在被其他处理修改的数据执行写锁定;
    • TRANSACTION-READ-UNCOMMITTED:允许处理读入未受权的数据以及允许在向结果中添加记录时可以忽略处理。

       以上隔离水平依次降低,效率和性能依次提高。因此,建议选用满足在业务数据完整性要求前提下水平最低的隔离级别。

      对于事务属性的设置也是如此,对于删除、修改和插入操作设置为Required,而对于只读操作设置为Supports或者NotSupports。

    2.6.3 其他一些小技巧
      1. 利用finders-load-bean的默认值true,既可以避免“n+1”的查询问题,又可以提高系统的性能;
      2. 使用delay-updates-until-end-of-tx参数的默认值true,除非应用程序对某些变化有特别的要求;
      3. 应用程序在每个业务方法调用后不需要进行存在性检查,将check-exists-on-method设定为false,以提高程序的性能;
      4. 同一应用内, 将enable-call-by-reference设置为 true;
      5. reentrant设置为false,避免事先加载子数据。

    第三章 数据库调优(目录)
    3.1.1 Oracle性能优化

      Oracle9i的性能优化除了调整kernal之外就是主要对Oracle启动文件的调整,即调整SGA的参数。注意,不同操作系统不同位数的机器最优的参数不是一样的,这里主要有windows和unix之分,32位和64位之分。
    首先需要调大进程数和游标数,一般默认的值对实际应用来说都比较小,比如说,进程数可以调到300,游标数可以调到500。

       其次,看一个经验公式: OS 使用内存+ SGA + session*(sort_area_size + hash_area_size +2M)<0.7RAM,通常认为此时的SGA比较合理。这里sort_area_size为64k, hash_area_size为128k(当排序多的时候需要增大sort_area_size,按调整后的值计算),session表示最大并发进程 数,假设100个。假如1G内存的机器,OS占用200M,PGA占用200M左右,那么SGA可以设为400-500M,如果2G内存可以1G给 SGA,8G可以5G给SGA。不过对于32位数据库来说,通常最多只能使用1.7G内存。

      然后,SGA内参数设置的基本原则是: data buffer 通常可以尽可能的大,shared_pool_size 要适度,log_buffer 通常大到几百K到1M就差不多。具体的:data buffer 1G内存可以设置500M,2G设为1.2G,8G可设为5G 。shared_pool_size不易过大,通常应该控制在200M--300M,如果使用了大量的存储过程,可以根据SGA的值增大到500M,如果 增大后命中率得不到提高,则增加是无益的。具体的:1G内存可以设置100M,2G设为150M,8G可设为300M。如不使用Java, java_pool_size 10-20M即可。large_pool_size如果不设置MTS,在20M -30M 即可,假如设置 MTS,可以考虑为 session * (sort_area_size + 2M)。

      最后,关于内存的设置可根据statspack信息和v$system_event,v$sysstat,v$sesstat,v$latch 等view信息来考虑微调。

    3.1.2 Oracle的其他调整
      为了Oracle高效率的运行,除了上面提到的内存因素之外,还有就是需要良好的数据库设计:表、视图、索引和日志的合理规划和建立。I/O的性能也是重要因素,应尽量减少页交换和页分配。此外,就是改善检查点的效率。

    第四章 操作系统调优(目录)
    4.1 操作系统调整

       操作系统影响应用程序运行性能的因素主要有:硬件的配置(CPU、内存、硬盘等),核心参数,TCP/IP参数以及补丁的情况等。这里对操作系统的优 化,除了更新最新的补丁程序以保证应用程序正常运行之外,就是调整TCP/IP参数,文件描述符,对于个别操作系统还有其他特别的参数调整。下面将依次介 绍不同操作系统的情况,更多的信息请参考各操作系统的文档。

    4.1.1 HP-UX
      对于HP-UX,你首先需要安装Java Patch:
    http://www.hp.com/products1/unix/java/patches/index.html,然后需要确认下面文档中的核心参数是否满足(可以使用sam命令修改核心参数):http://e-docs.bea.com/platform/suppconfigs/configs81/hpux11_risc/81sp3.html#80105

      调整TCP参数: ndd -set /dev/tcp tcp_conn_req_max 1024, 将侦听队列的最大允许长度调整到1024。 有时操作系统限制进程使用的最大内存数小于你要配置的内存大小,则需要调整该值。

      读者可以从http://docs.hp.com/hpux/onlinedocs/TKP-90203/TKP-90203.html了解更多的HP-UX调整建议。

    4.1.2 Solaris
      调整TCP的参数,等待时间间隔tcp-time-wait-interval建议设置为60000ms: /usr/sbin/ndd ?set /dev/tcp tcp_time_wait_interval 60000;
    其他参数调整如下:

    tcp_xmit_hiwat/tcp_recv_hiwat 131072
    tcp_conn_req_max_q/tcp_conn_req_max_q0 16384

      调整一个进程打开的文件描述符的数量:软限制和硬限制以及散列表的大小,修改/etc/system文件:

    set tcp:tcp_conn_hash_size=32768
    set rlim_fd_cur=8192
    set rlim_fd_max=8192

    更多的调整信息请查阅: http://docs.sun.com/db/doc/806-7009(Solaris9)。

    4.1.3 AIX
       AIX用no命令调整TCP参数,等待时间间隔tcp_timewait: no -o tcp_timewait=4,将tcp.timewait参数设置为4个15秒间隔,即1分钟。运行no -a命令将显示网络当前的所有属性值。由于UDP_SENDSPACE默认的缓存大小是8k,为减少I/O异常,需调整为32k:

      no -o udp_sendspace=32768。此外, 当WebLogic HTTP请求忙时,可以调整侦听队列的最大长somaxconn到8192(默认值是1024)。

      更多信息:http://publib16.boulder.ibmo.com/pseries/en-us/aixbman/prftungd/prftungd.htm

    4.1.4 Linux
       调整Linux系统使用sysctl命令修改TCP参数等待时间间隔:sysctl -w ip_ct_tcp_timeout_time_wait=60;调整打开文件的最大数:在/etc/sysctl.conf文件中,添加: Fs.file-max=65535,然后运行sysctl -p;调整打开文件描述符最大数为8192:在/etc/security/limits.conf文件,添加:WebLogic hard nofile 8192(仅针对WebLogic用户),然后在WebLogic启动文件里运行ulimit-n 8192激活设置。

    更多信息请查阅:http://ipsysctl-tutorial.frozentux.net/ipsysctl-tutorial.html

    4.1.5 Windows
       Windows系统的调整通过修改注册表HKEY-LOCAL-MACHINESYSTEMCurrent ControlSetServices文件夹来完成。可以调整TcpipParameters子文件夹中的等待时间间隔时间 TcpTimedWaitDelay参数的值。侦听队列最大长度的默认值为15,为修改它,可在InetinfoParameters子目录中创建 DWORD条目ListenBackLog。
    此外,Windows2000的Service Pack(要求sp3以上)也会影响系统稳定性: http://e-docs.bea.com/platform/suppconfigs/configs81/win2ksvr_as_data_pentium/81sp3.html

    第五章 性能监控和性能分析(目录)
    5.1 性能瓶颈
      最后,介绍一下实际分析J2EE应用性能的常用命令和工具。对于实现一个高性能的J2EE应用来说,掌握了J2EE调优的理论经验还是不够的。掌握性能监控,发现瓶颈和问题诊断才是保证J2EE系统持续高效运行的关键。
    瓶 颈指的是限值所有吞吐操作以及严重影响反应时间的系统内资源。在分布式系统内寻找并纠正瓶颈是非常困难的,需要有经验的团队来解决。瓶颈会发生在Web服 务器上,程序代码中,应用服务器上,数据库,操作系统或者网络,硬件上。经验表明,瓶颈很容易发生在如下地方:数据库连接与队列中;应用服务器的程序代码 中;应用服务器和Web服务器硬件上;网络和TCP配置中。实际中可以着力对这些环节进行监控。

    5.2 操作系统监控
       操作系统层面的性能监控主要是对内存、CPU、I/O和交换区的使用情况进行监控分析。windows平台可以通过任务管理器和perfmon工具查 看。如果是unix系统可以使用stat系列命令(vmstat, mpstat, iostat)监控内存、CPU和I/O的即时变化,使用swap命令查看交换区的使用情况。如果操作系统安装了top、topas、glance等使用 工具,则使用top、topas、glance将能更为方便地看到WebLogic进程对操作系统的内存,CPU和I/O资源使用的即时变化情况。

      而网络方面的性能可以通过ping和netstat等命令来监控,主要几个关键的网络统计值,如数据包再发送、重复数据包和数据包侦听丢失。

      说明:本文提到的unix命令并非适用所有操作系统,仅供参考。

    5.3 数据库监控
      数据库层面的监控这里为oracle9i为例来说明,可以采用oracle自带的工具Oracle
    Interprise Manager Console来监控session和sql的执行情况。还有其他专业的数据库监控工具可以使用,比如QUEST的spotlight(http://www.quest.com/spotlight-portal/)可以非常形象和直观地对Oracle数据库的CPU、内存、I/O、Data Buffer Size、Shared Pool Size、Redo Buffer等参数进行即时监控,并自动对不正常的参数以红色显示。

    5.4 WebLogic监控
    5.4.1 JVM监控

      采用java参数-verbose:gc 来分析JVM的GC非常繁琐,而且不直观。使用-Xloggc:gc.log 参数将GC日志写入文件,采用GC 工具HPjtune (http://www.javaperformancetuning.com/tools/hpjtune/index.shtml)进行分析,可以轻松看出当前jvm参数配置是否合理。

       严格意义上来说HPjtune是一个分析工具,不是监控工具。这里不得不提及jRocket,Intel平台上最快的JVM, 在WebLogic启动命令中增加-Xmanagement参数,就可以执行beajrockit81sp3_142_04in下console命令监 控WebLogic的内存使用和CPU负载情况。设置Tools/Preferences菜单中的Mode of operation属性为developer, jRocket将提供Method Profiler工具,她能够将所有在JRockit Java虚拟机上执行的成员方法的调用次数、执行的总时间和每次调用的执行时间都统计出来,进行代码级调优,这是jRockit的又一大优势。


    5.4.2 Console监控
      WebLogic Console除了管理配置功能之外,提供了丰富的监控功能。通过WebLogic Console,首先我们可以查看服务器的运行情况。

    5.4.2.1 Server监控
       通过使用服务器的Performance Monitoring选项卡,可以查看到请求吞吐量,执行队列积压情况以及JVM栈利用情况。而通过点击Performance Genaral选项卡中” Monitor all Active Queues...”可以查看所以执行线程的当前统计数据。此外Monitoring选项卡还可以监控JTA和JMS等Service的情况。


    5.4.2.2 JDBC监控
       在连接池Monitoring选项卡中,WebLogic Console为每一个数据库连接池提供了实时统计信息。其中有三个重要参数可以反应WebLogic Server的健康状况:Connections High、Wait Second High和Waiters High。Connection High表示从服务器启动开始后到达池的最大连接数量,如果大于池的最大数量,则需要调整Maxium Capacity。Waiters High表示在没有可用连接的情况下,应用程序等待连接的最大个数。我们可以根据Waiters High的大小调整连接池容量。更多的参数可以通过Customize this view链接添加,参数含义参考:http://e-docs.bea.com/wls/docs81/ConsoleHelp/domain_jdbcconnectionpool_monitor.html#1104829

    5.4.2.3 WEB监控
      Web Application Monitoring选项卡可以监控WEB应用的Session个数,以及Servlet的响应情况,激活Session Monitoring Enabled可以获取所有session的统计情况。更多信息请参考:
    http://e-docs.bea.com/wls/docs81/ConsoleHelp/web_applications.html#1106723

    5.4.2.4 JMS监控
       Welogic Console JMS监控功能比较多,不仅在Server JMS Monitoring选项卡可以监控Active JMS Connections, Pooled JMS Connections和Active JMS Servers的连接和使用情况。还可以监控JMS Session Pool、Active JMS Destinations和Durable Subscribers的消费和生产情况。比如,我们可以监控到JMS Queue的接收和消费消息的数量和字节数。有关JMS监控的详细情况可参见:http://edocs.bea.com/wls/docs81/ConsoleHelp/jms_monitor.html

    5.4.2.5 EJB监控
      EJB监控包括对SLSB,SFSB,Entity Bean,MDB四种EJB的监控。本人认为EJB监控提供了非常丰富的运行时统计信息(http://e-docs.bea.com/wls/docs81/ConsoleHelp/ejb.html#1105036),非常有利于我们对EJB进行性能调优。

       SLSB选项卡为用户提供实例池的运行时统计信息。Pool Miss Ratio 表示实例池的Miss率,Pool Waiter Total Count 表示线程等待bean 实例的累计时间,Pool Timeout Total Count表示超时的线程数。当Pool Miss Ratio较大时,可以增加max-beans-free-pool。

      SFSB可以关注Cache Miss Ratio和Activation Count。Cache Miss Ratio过大时,调大max-bean-in-cache未必有帮助,需要尝试不用的max-bean-in-cache以获得最低的Cache Miss Ratio。激活将严重减慢应用程序的速度,如果某一个bean的Activation Count的值过高,那么需要考虑增加max-bean-in-cache的大小。
    Entity Bean结合了SLSB的free pool和SFSB的cache。可以结合上面的策略进行监控。

      而MDB仅比SLSB多一个参数JMSConnection Alive,报告EJB是否成功连接到JMS目的地。

    更多Console监控信息可参见http://edocs.bea.com/wls/docs81/ConsoleHelp/index.html

    5.4.3 实用工具分析
       WebLogic除了提供Console进行应用监控之外,用户还可以编写JMX程序或者通过SNMP协议进行监控。而QUEST Spotlight for WebLogic Server提供了类似WebLogic Console类似的监控功能,并对异常情况显红。
    这 里不得不提到实战中经常用来分析性能瓶颈的工具THREAD DUMP,统一的命令是使用 weblogic.Admin 命令 THREAD_DUMP。而在 windows上还可以使用<Ctrl>+<Break> 来创建诊断问题所需的线程转储Thread Dump,而在unix上使用kill -3 <wlspid>命令。我们从中可以看到WebLogic后台线程的运行情况,通常需要每隔10秒左右持续执行几次以助诊断问题。更多信息可 以参考BEA实战集锦。

    5.5 应用程序分析
       应用程序分析除了凭借程序员丰富的经验和敏锐的洞察力去人工检查代码之外,使用厂家的工具也是节省时间的不错选择。目前市场上有Borland Optimizeit Enterprise Suite和QUEST Jprobe两个产品可以用来分析性能瓶颈,垃圾收集,内存泄漏,线程死锁和代码复盖等。Hpjmeter是一个免费的工具,也具有以上类似的性能分析功 能。

      而Borland Optimizeit Server Trace,HP OpenView Transaction Analyzer和Mercury LoadRunner J2EE breakdown都可以用来分解J2EE应用从客户端访问到最终数据库操作每一层次花费的时间,甚至精确到每一个方法的执行时间。Server Trace还具有检查内存泄漏,连接泄漏和错误警告等功能,一般在测试环境中使用。而HP OTVA的优势在于运行时监控,LoadRunner优势在于压力测试。

    总结(目录)
       J2EE调优是一门实践和经验科学,是一个复杂而往复的过程。其原则是:合理。合理,看似简单,细细品味,意味深长。本文所述的调优策略并不是一成不变 的,只是为了给大家一个参考建议,让大家少走弯路,关键是根据实际环境调优。欢迎有兴趣的朋友在论坛上积极讨论和批评指正。

    参考文献(目录)
    [1]BEA WebLogic Server edocs: http://e-docs.bea.com/wls/docs81/perform/index.html
    [2]Gregory Nyberg & Robert Patrick :Mastering BEA WebLogic Server
    [3]Jack Shirasi:Java Performance Tuning

    关于作者(目录)
    周 海根(dev2dev ID:zhouhg) 合力思软件(中国)有限公司技术顾问,BEA Certified Specialist,BEA dev2dev撰稿人。多年从事J2EE开发工作,目前致力于技术支持工作,主要研究J2EE技术在WebLogic上的应用、调优。有着西电人的务实, 喜欢专研技术,是个体育狂热者。
    联系方式: 010-85251858-1053,zhouhaigen@hotmail.com


     

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1422380

  • JAVA面试32问

    2007-01-10 16:02:13

    http://www.blogcn.com/blog/trackback.asp?mydiary=40601063
  • Web性能测试资料及工具

    2007-01-10 16:00:08

     Web性能测试资料及工具

      1) Jmeter Wiki首页,Jmeter为一个开源的100%Java开发的性能测试工具
      ::URL::http://wiki.apache.org/jakarta-jmeter/

      2) Apache Benchmark使用说明
      ::URL::http://httpd.apache.org/docs-2.0/programs/ab.html

      3) 一些Java相关测试工具的介绍,包含可以与Tomcat集成进行测试的工具
      ::URL::http://blog.csdn.net/wyingquan/

      4) LoadRunner? 是一种预测系统行为和性能的工业标准级负载测试工具。它通过模拟数据以千万计用户来实施并发负载来对整个企业架构进行测试,来帮助您更快的查找和发现问题。
      ::URL::http://www.mercury.com/us/products/performance-center/loadrunner/


      2. 文中介绍的相关内容的介绍

      1) Apache 2.x + Tomcat 4.x做负载均衡,描述了如何利用jk配置集群的负载均衡。
      ::URL::http://raibledesigns.com/tomcat/index.html

      2) 容量计划的制定,收集了许多有关制定web站点容量计划的例子:
      ::URL::http://www.capacityplanning.com/

      3) 评测Tomcat5负载平衡与集群,
      ::URL::http://www.javaresearch.org/article/showarticle.jsp?column=556&thread=19777

      4) Apache与Tomcat的安装与整合之整合篇
      ::URL::http://www.javaresearch.org/article/showarticle.jsp?column=23&thread=18139

      5) 性能测试工具之研究,介绍了性能测试工具的原理与思路
      ::URL::http://www.51testing.com/emagzine/No2_2.htm

      6) Java的内存泄漏
      ::URL::http://www.matrix.org.cn/resource/article/409.html

      7) Web服务器和应用程序服务器有什么区别?
      ::URL::http://www.matrix.org.cn/resource/article/1429.html

      8) 详细讲解性能中数据库集群的问题
      ::URL::http://www.theserverside.com/articles/article.tss?l=DB_Break  
  • loadrunner调用C++的dll

    2007-01-10 15:48:20

    51Testing陈卫俊(落叶夏日)的这篇文章,转来保存,谢过。
    场景介绍       
            最近在做类似于QQ的通信工具的性能测试时发现了一些问题,现总结出来与大家分享一下。希望大家在使用LoadRunner时不仅仅停在只是录制/播放角本,而全面提升角本的编程技术,解决复杂场景。
            本次测试中碰到的问题是这样的,在消息的传送过程中遇到了DEC加密的过程,LoadRunner录制到的全是加密的消息,比如我录制了某一个用户的登 陆,发送消息,退出,但由于是加密的,只能单个用户使用,但如果我想并发多少个用户就存在很多问题,最直接的一个问题就是用户名是加密的,密码是加密的, 当然你可以说让程序那里注掉加密的代码进行明码的测试,当然也是一种办法。但程序组提出了要使用更真实的方法来模拟,这时就必需使用下面介绍的方法。
            一开始是直接把API移植到LoadRunner中来,不过由于加密算法异常复杂,有几层循环,而角本是解释执行的,进行一次加密运算可能需要好几分钟, 当然在角本里可以把角本本身运行的时间去掉,但这样做显然没有直接调用DLL来的效率高。由于程序组比较忙,所以无法提供DLL给测试,所以测试完成了 DLL的编写,并在LoadRunner中调用成功,高效的完成了用户信息加密,参数关联,成功的完成了测试。
    动态链接库的编写
      在Visual C++6.0开发环境下,打开FileNewProject选项,可以选择Win32 Dynamic-Link Library建立一个空的DLL工程。
      1. Win32 Dynamic-Link Library方式创建Non-MFC DLL动态链接库

       每一个DLL必须有一个入口点,这就象我们用C编写的应用程序一样,必须有一个WINMAIN函数一样。在Non-MFC DLL中DllMain是一个缺省的入口函数,你不需要编写自己的DLL入口函数,用这个缺省的入口函数就能使动态链接库被调用时得到正确的初始化。如果 应用程序的DLL需要分配额外的内存或资源时,或者说需要对每个进程或线程初始化和清除操作时,需要在相应的DLL工程的.CPP文件中对DllMain ()函数按照下面的格式书写。
     
    BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
    {
    switch( ul_reason_for_call )
    {
    case DLL_PROCESS_ATTACH:
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    default:
        break;
    }
    return TRUE;
    }
      
            参数中,hMoudle是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符); ul_reason_for_call是一个说明动态库被调原因的标志,当进程或线程装入或卸载动态链接库的时候,操作系统调用入口函数,并说明动态链接 库被调用的原因,它所有的可能值为:DLL_PROCESS_ATTACH: 进程被调用、DLL_THREAD_ATTACH: 线程被调用、DLL_PROCESS_DETACH: 进程被停止、DLL_THREAD_DETACH: 线程被停止;lpReserved为保留参数。到此为止,DLL的入口函数已经写了,剩下部分的实现也不难,你可以在DLL工程中加入你所想要输出的函数 或变量了。

      我们已经知道DLL是包含若干个函数的库文件,应用程序使用DLL中的函数之前,应该先导出这些函数,以便供给应用程序使 用。要导出这些函数有两种方法,一是在定义函数时使用导出关键字_declspec(dllexport),另外一种方法是在创建DLL文件时使用模块定 义文件.Def。需要读者注意的是在使用第一种方法的时候,不能使用DEF文件。下面通过两个例子来说明如何使用这两种方法创建DLL文件。

      1)使用导出函数关键字_declspec(dllexport)创建MyDll.dll,该动态链接库中有两个函数,分别用来实现得到两个数的最大和最小数。在MyDll.h和MyDLL.cpp文件中分别输入如下原代码:
     
    //MyDLL.h
    extern "C" _declspec(dllexport) int desinit(int mode);
    extern "C" _declspec(dllexport) void desdone(void);
    extern "C" _declspec(dllexport) void des_setkey(char *subkey, char *key);
    extern "C" _declspec(dllexport) void endes(char *block, char *subkey);
    extern "C" _declspec(dllexport) void dedes(char *block, char *subkey);
    //MyDll.cpp
    #include"MyDll.h"
    //这里我用了比较大小的函数代替了我要实现的函数
    int desinit(int a, int b)
    {
    if(a>=b)return a;
    else
    return b;
    }
    int desdone(int a, int b)
    {
    if(a>=b)return b;
    else
    return a;
    }
    该 动态链接库编译成功后,打开MyDll工程中的debug目录,可以看到MyDll.dll、MyDll.lib两个文件。LIB文件中包含DLL文件名 和DLL文件中的函数名等,该LIB文件只是对应该DLL文件的"映像文件",与DLL文件中,LIB文件的长度要小的多,在进行隐式链接DLL时要用到 它。读者可能已经注意到在MyDll.h中有关键字"extern C",它可以使其他编程语言访问你编写的DLL中的函数。
    LoadRunner调用动态链接库
            上面完成动态链接库开发后,下面就介绍动态链接库如何被LoadRunner进行调用,其实也是很简单的。在LoadRunner中的DLL调用有局部调用与全局调用,下面介绍局部调用。
    首先把你编译的DLL放在角本路径下面,这里是MyDll.dll,MyDll.lib.然后在Action中使用
    lr_load_dll("MYDll.dll"),此函数可以把DLL加载进来,让你调用DLL里面的函数,而DLL中的运算是编译级的,所以效率极高,代码样例如下:
    #include "lrs.h"
    Action()
    {
            //
            int nRet = 6;
            char srckey[129];
            memset(srckey, 'a', 128);
            lr_message(lr_eval_string(srckey));
            lr_load_dll("MyDLL.dll");
            nRet = desinit(5,8);
            lr_message("比较的结果为%d",nRet);
        return 0;
    }
    运行结果
            比较的结果为8

            全局的动态链接库的调用则需要修改mdrv.dat,路径在LoadRunner的安装目录下面(LoadRunner/dat directory);在里面修改如例:
            [WinSock]
    ExtPriorityType=protocol
    WINNT_EXT_LIBS=wsrun32.dll
    WIN95_EXT_LIBS=wsrun32.dll
    LINUX_EXT_LIBS=liblrs.so
    SOLARIS_EXT_LIBS=liblrs.so
    HPUX_EXT_LIBS=liblrs.sl
    AIX_EXT_LIBS=liblrs.so
    LibCfgFunc=winsock_exten_conf
    UtilityExt=lrun_api
    ExtMessageQueue=0
    ExtCmdLineOverwrite=-WinInet No
    ExtCmdLineConc=-UsingWinInet No
    WINNT_DLLS=user_dll1.dll, user_dll2.dll, ...
    //最后一行是加载你需要的DLL
            这样你就可以在LR中随意的调用程序员写的API函数,进行一些复杂的数据加密,准备的一些操作,进行复杂的测试。同时如果你觉的有大量高复杂的运算也可以放在DLL中进行封装,以提高效率。
  • oracle的学习心得一

    2007-01-10 15:16:46

    oracle的sql语句有一点奇怪,好像必须要把所有者带上才可以顺利被执行。
    例如:
    SELECT TEST.TEST1
    FROM SYSTEM.TEST

    今天还在pl/sql中学会oracle的insert和update的sql语句的写法,
    iinsert into <table_name>
      (<column_list>)
    values
      (<value_list>)

    update <table_name>
         set <column_assignment>
       where <where_clause>;
    其中字符串用''包含起来!

我的存档

数据统计

  • 访问量: 16403
  • 日志数: 12
  • 建立时间: 2007-01-10
  • 更新时间: 2007-01-19

RSS订阅

Open Toolbar