tomcat优化总结

系统发生了比较严重的性能问题,因为事情紧急只能取消自己的休假计划,赶到现场调试系统。

到了之后,首先检查了Tomcat的配置文件server.xml,原来一直以为肯定是配置服务器的同学没有把Tomcat中默认的允许访问的最大数75给改掉,后来发现不是这个问题,在配置文件中设置Context的地方有一段非常的诡异:有一个Context的路径是在%Tomcat%/webapps/ROOT中的一个目录AAA,这样的话如果当一个用户访问URL: http://serverip:port/AAA 时,系统是应该使用ROOT/WEB-INF中类还是应该使用ROOT/AAA/WEB-INF中的类?把服务器中两个WEB-INF都下载下来,用JAD反编译其中的部分类,发现并不一致。最后经过分析,得出了TOMCAT在这种Context嵌套在ROOT Context中的情况,TOMCAT会使用ROOT目录中的WEB-INF。

然后为程序加入了数据库连接池配置,实践证明了如果不采用TOMCAT的数据库连接池技术,那么在并发访问数达到4000-5000的时候,Tomcat绝对支撑不到1分钟的。采用TOMCAT的数据库连接池技术后这时的TOMCAT能维持正常运行30分钟左右。数据库连接池配置的方式如下:修改tomcat配置文件server.xml,在context标签中加上:
1.
2.
4.
5.
6. factory
7. org.apache.commons.dbcp.
8. BasicDataSourceFactory
9.
10.
11. driverClassName
12. oracle.jdbc.driver.OracleDriver
13.
14.
15. url
16. jdbc:oracle:thin:@10.11.6.1:1521:dbname
17.
18.
19.
20. username
21. yourname
22.
23.
24. password
25. yourpasswd
26.
27.
28. maxActive
29. 1000
30.
31.
32. maxIdle
33. 20
34.
35. maxWait
36. -1
37.
38.
39.
maxActive是最大激活连接数,这里取值为1000,表示同时最多有1000个数据库连接。maxIdle是最大的空闲连接数,这里取值为20,表示即使没有数据库连接时依然可以保持20空闲的连接,而不被清除,随时处于待命状态。MaxWait是最大等待秒钟数,这里取值-1,表示无限等待,直到超时为止,也可取值9000,表示9秒后超时。
修改web.xml文文件,加入
[待加入的XML片断,竟然被系统过滤掉了,赫赫,留个站位符]
将Oracle的JDBC驱动classes12.jar拷贝到Tomcat安装目录的common/lib下。建立简单的测试页面test2.jsp:
1. Context initCtx = new InitialContext();
2.
3. Context envCtx = (Context) initCtx.lookup("java:comp/env");
4.
5. ds = (DataSource)envCtx.lookup("jdbc/OracleDB");
6.
7. Connection cn=ds.getConnection();

到这里数据库连接池配置基本完成了。但是如果半个小时服务器死掉一次的话,还是不能令人接受的。开始详细检查tomcat的输出文件%Tomcat%/logs/catalina.out,在这个文件中记录的是所有TOMCAT控制台的输出,一般在JAVA中的抱错信息都会在这里打印出来。自己分析后发现每次TOMCAT死掉之前,都是一堆java.net.SocketException: Too many open files这种错误。这个错误肯定不是程序的问题。
可能是因为每有一个TCP的连接到Linux服务器的80端口,都有一次文件的传输过程,Tomcat服务器会打开一个文件(比如图片文件),传送给请求的客户端浏览器,所以如果访问Tomcat的人数过多,会突破linux系统默认的1024个文件上限。
在/root/.bash_profile文件中加入:
ulimit -n 4096
可以在每次系统启动时候自动执行ulimit命令,把最大文件上传个数调整到4096个。注意ulimit这个命令是针对于一个开打的终端的,比如你在一个终端上面运行ulimit,但是影响到的只是你这个终端上运行的命令和程序的打开的文件数,其他的终端如果再打开,效果仍然是没有运行ulimit -n 4096之前的。大家可以实验一下。
这样之后,服务器大概能维持2小时左右的正常运行,使用TOP命令查看Java进程占用的内存后,发觉一个现象,就是内存使用到256M之后,不会往上增长了(服务器有8G的内存)。上网查了以后,知道了Tomcat默认可以使用的是256M的内存。由于在线人数过多,造成Tomcat默认可以使用的256M的内存不够使用,所以修改Tomcat的启动文件catalina.sh,在“echo “Using JAVA_HOME: $JAVA_HOME”” 后加入JAVA_OPTS=’-Xms256m -Xmx1024m’,256m表示初始化的时候给Tomcat初始内存256M,1024m表示Tomcat最大可使用的内存为1024M。
修改了这个之后,服务器比原先稳定了许多了,可是又发现在有的时候,进行用户登录的时候会报莫名其妙的数据库连接错误。终于在有一次使用ORACLE的客户端程序GOLDEN连接Oracle时,出现了ORA-00020:maximum number of process(150) exceeded 这样一个错误。这是由于数据库服务器访问的连接数过多,会出现ORA-00020:maximum number of process(150) exceeded的错误。Oracle 9i中默认的连接数为150,要修改这个配置文件,需要修改SPFILEORCL.ORA文件中的processes的值。(8.1.5中是init.ora文件,在9i中修改init.ora文件是无效的)这个文件由于是一个二进制的文件,不能直接使用notepad此类的编辑器打开,否则会报错误ORA-27101 Shared memory realm does not exist。使用UltraEdit或者EditPlus之类的可以编辑二进制文件的编辑器打开此文件(直接编辑二进制文件),然后在Windows服务中重新启动Oracle服务器即可。
现在的状况非常好,问题正在逐步的好转之中,不过系统的性能还是非常的差,网页的访问速度很糟糕。到安装Oracle的Win2003服务器上检查了一下Oracle服务器,发现硬盘的占用率很高,基本一致是100% 使用的状况。进入Oracle中进行分析,发现有两条SQL语句非常占用系统的资源,是造成瓶颈的两个SQL。
于是对于原先使用trim的SQL进行优化
由于trim命令会造成大量的硬盘读写(使用trim后造成索引无效),所以把所有使用trim命令的语句修改为使用rpad命令。
例如:
select sfzh from qjgkXSK where trim(sfzh)=:1
改为
select sfzh from qjgkXSK where sfzh=:rpad(1)

对于表结构的建议:表结构中如果长度小于200的字段,建议使用char类型,而不是Varchar类型。

然后发现在生成一个唯一序列号的时候,程序中有一个锁表的操作,造成一个最大的瓶颈。原先的做法是先是锁住一个表,然后取得最大值,最后把最大值加一,写入数据库中。
1. ps = conn.prepareStatement("LOCK TABLE "+Global.xsk+" IN EXCLUSIVE MODE");
2. ps.executeUpdate();
3. ps = conn.prepareStatement("select max(SNO) from "+Global.xsk+" where SNO is not null");
4. rs = ps.executeQuery();
5. rs.next();
6. if (rs.getString(1)!=null)
7. {
8. temp = Global.formatString(""+(Integer.parseInt(rs.getString(1))+1),"0",6);
9. }
10. else
11. {
12. temp = "000001";
13. }

改进后的做法是加入一个ORACLE的自增1的sequence(Oracle和MySQL、DB2等不同,它没有主键auto-increasement这种功能)
1. ps = conn.prepareStatement("select seq_qjgksno.nextval from dual");
2. rs = ps.executeQuery();
3. rs.next();
4. temp = Global.formatString("" + (Integer.parseInt(rs.getString(1))), "0", 6);


做完这些时候,感到系统的问题都解决了,不过后来的情况还是几个小时会死机一次,这次是报一个Java虚拟机的错误,估计是因为一开始别人装的是1.5beta版的关系。
总结一下这次的优化的经验:
1.要抓住事物的主要矛盾。其实一开始针对WEB服务器中的很多优化都是次要矛盾,当解决了最后的2个SQL语句的问题后,前面的很多问题都不会出现的,比如那个Linux 1024个默认打开文件数的问题,最后发现如果系统数据库访问的速度足够快,根本不会有那么多打开的文件数的,往往是大家用系统时很慢,所以造成了不断用F5刷新,把Tomcat活活搞死。
2.在这种很重要的场合下改动程序或者配置一定要谨慎谨慎再谨慎。我在修改Oracle的配置文件的时候,一开始没有备份,以后那是一个文本文件,我就是直接开打修改一个数字而已。但是虽然用notepad打开的时候显示出来的是文本,但是这个文件在被notepad打开时一些二进制的东西被破坏了,造成了Oracle服务器启动不起来,那时候自己都要被吓死了,还好有个同学的机器上也有Oracle9i,而且都是按照默认配置的,直接打电话叫他把那个文件通过MSN发了过来。如果没有类似的文件,或者服务器装的比较怪异,那么就惨了,千古罪人的。后来我基本每做一个操作,都不图快,而是随时备份,做的比较稳健了。
3.在改那个程序的时候不断的有考生打电话来咨询服务器的问题,那个时候压力非常大,一定要顶住压力,如果感觉吃不消了,不妨先休息下,然后效率可能会更加高。
4.事前一定要做好测试工作。
最后附上一些Linux中可能会在检测性能时候用到的命令:A.察看某个进程打开的文件数:先用ps -aux找到pid,然后运行lsof -p %pid% wc -l
B.察看80端口的连接数netstat -natgrep -i “80″wc -l

你可能感兴趣的:(tomcat)