resin的配置文件类似xml,语法规范也遵循xml的写法,今天遇到了特殊字符的问题,数据库密码包含了特殊字符。
...
#sh start_server.sh
Starting Resin on Thu, 22 Apr 2010 18:39:48 +0800 (CST)
com.caucho.xml.XmlParseException: /home/resin/conf/resin.conf:8: malformed entity ref at `('
at com.caucho.xml.XmlParser.error(XmlParser.java:2769)
at com.caucho.xml.XmlParser.parseCharacterReference(XmlParser.java:1002)
at com.caucho.xml.XmlParser.parseValue(XmlParser.java:1192)
at com.caucho.xml.XmlParser.parseAttributes(XmlParser.java:702)
at com.caucho.xml.XmlParser.parseElement(XmlParser.java:603)
at com.caucho.xml.XmlParser.parseNode(XmlParser.java:377)
at com.caucho.xml.XmlParser.parseInt(XmlParser.java:248)
at com.caucho.xml.AbstractParser.parse(AbstractParser.java:645)
at com.caucho.util.Registry.parse(Registry.java:199)
at com.caucho.util.Registry.parse(Registry.java:174)
at com.caucho.server.http.ResinServer.init(ResinServer.java:311)
at com.caucho.server.http.ResinServer.main(ResinServer.java:1176)
其原因并不是“(”引起的,罪魁祸首是“&”
解决办法是使用&替换&
如:
xml文件中其他的几个特殊字符做同样处理即可:
* & = & (ampersand)
* < = < (left angle bracket, less-than sign)
* > = > (right angle bracket, greater-than sign)
* " = " (quotation mark)
* ' = ' (apostrophe)
说明:
本文是在apache2+resin3(开源版)环境下的配置,主要是对resin3配置进行了分析,详细调试请见caucho-doc ,apache2的调优见apache的man文档。实践总结,如转载请注明出处--2hei.net 谢谢.
Using Resin(R) under the GNU Public License (GPL).
See http://www.caucho.com for information on Resin Professional,
including caching, clustering, JNI acceleration, and OpenSSL integration.
resin配置文件: resin.conf
1、dependency-check-interval 参数调整
resin检查系统配置及java、jsp、resin.conf等文件的时间间隔。
默认值为2秒,适合开发及调试环境,如果是正式环境尽量把参数调大或者直接改为-1,不允许检查,也就是禁止了热部署。
-1s
2、缓存
改变cache-mapping的值:
3、jvm优化
jvm需要根据你的系统配置及应用来调整。
JVM OPTION PASSED TO RESIN MEANING
-Xms initial java heap size
-Xmx maximum java heap size
-Xmn the size of the heap for the young generation
将-Xms和-Xmx设置为一样大小是不错的选择。
如: bin/httpd.sh -Xms500M -Xmx500M -Xmn100M
更多的关于jvm优化参数如:young generation、Eden generation、older generation可见
Sun documentation on garbage collection
jvm的监控,google一下有很多的工具,如:jconsole jstat jstack
jconsole的使用见我的另外一篇文章 《使用Jconsole对java的内存使用情况(JVM)进行监控》
$jps
1229 Jps
1003 Resin
973 resin.jar
$jmap 973
Attaching to process ID 973, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_16-b02
0x0000000040000000 64K /home/jdk1.5.0_16/bin/java
0x00000030b2a00000 127K /lib64/ld-2.5.so
0x00000030b2e00000 1647K /lib64/libc-2.5.so
0x00000030b3200000 22K /lib64/libdl-2.5.so
0x00000030b3600000 600K /lib64/libm-2.5.so
0x00000030b3a00000 138K /lib64/libpthread-2.5.so
0x00000030b5a00000 111K /lib64/libnsl-2.5.so
0x00002aaab46ad000 26K /home/jdk1.5.0_16/jre/lib/amd64/libmanagement.so
0x00002aaab49de000 79K /home/jdk1.5.0_16/jre/lib/amd64/libnet.so
0x00002aeeac3c1000 9933K /home/jdk1.5.0_16/jre/lib/amd64/server/libjvm.so
0x00002aeeacd46000 43K /home/jdk1.5.0_16/jre/lib/amd64/native_threads/libhpi.so
0x00002aeeace61000 52K /lib64/libnss_files-2.5.so
0x00002aeead06c000 58K /home/jdk1.5.0_16/jre/lib/amd64/libverify.so
0x00002aeead17b000 171K /home/jdk1.5.0_16/jre/lib/amd64/libjava.so
0x00002aeead2a5000 78K /home/jdk1.5.0_16/jre/lib/amd64/libzip.so
jstat -gc 1489 1000 3
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
43648.0 43648.0 0.0 0.0 262208.0 101390.5 699072.0 18545.6 28032.0 15756.6 1 0.055 1 0.115 0.170
43648.0 43648.0 0.0 0.0 262208.0 101390.5 699072.0 18545.6 28032.0 15756.6 1 0.055 1 0.115 0.170
43648.0 43648.0 0.0 0.0 262208.0 101390.5 699072.0 18545.6 28032.0 15756.6 1 0.055 1 0.115 0.170
jstack 1489
Thread 1495: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.Object.wait() @bci=2, line=474 (Interpreted frame)
- java.lang.ref.Reference$ReferenceHandler.run() @bci=46, line=116 (Interpreted frame)
Thread 1489: (state = IN_NATIVE)
- java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Interpreted frame)
- java.net.SocketInputStream.read(byte[], int, int) @bci=84, line=129 (Interpreted frame)
- java.net.SocketInputStream.read() @bci=23, line=182 (Interpreted frame)
- com.caucho.server.resin.Resin.waitForExit() @bci=304, line=1265 (Interpreted frame)
- com.caucho.server.resin.Resin.main(java.lang.String[]) @bci=42, line=1367 (Interpreted frame)
4、JNI加速
resin不使用NIO而是使用了JNI的方式使用本地码的方式来提升效率,经验证,resin使用JNI的效率要高于使用NIO,
使用JNI是需要对resin进行编译,在./configure时把jni编译进去,
./configure --enable-jni 美中不足的是Resin Professional版本才提供此项功能。
下面是resin-doc的说明:
Resin does not use NIO - it uses JNI to handle low-level I/O calls with native code. The performance using this method was found to be much better than nio.
5、jsp第一次编译的处理
一般来讲,第一次访问jsp会自动进行编译,如果更新了过多的jsp、且系统访问很大的话,重启resin容易造成负载过高。
下面配置是启动app-server时,对所有的jsp进行编译,编译完毕后启动监听,这样启动时间会长一些,但是可以防止第一次访问编译造成系统负载大。
com.caucho.jsp.JspPrecompileListener
jsp
jspx
6、resin 与apache 性能的比较
resin3单独使用时性能也是不错,当然也可以跟apache配合使用。下面是resin-doc中的说法:
For JSP and Servlets, Resin standalone is certainly faster than Resin/Apache. Because of the extra overhead of the Resin/Apache connection, the Resin/Apache configuration is necessarily slower than Resin standalone.
可以看出各有优劣,
apache对于静态页面来说比较快。如果使用了SSL,apache+resin要比resin单独使用快一些,更为重要的是resin3的开源版本不支持ssl。
7、resin-server TIME_WAIT 过多的处理
thread-max指定了最大连接数,socket-timeout是socket超时时间
keepalive-max指定了长连接的数量,这是可以重复使用的连接,netstat -an时系统可以看到响应数量的ESTABLISHED状态
设定keepalive-max和把keepalive-timeout调小可以减少TIME_WAIT的数量。
256
65s
128
120s
一般来讲如果是Resin standalone方式,调整timeout并不是很重要,如果是apache+resin的方式,而且apache压力很大的情况下,需要调小timeout的值。
load-balance-idle-time是用来设置load-balance和分布式session的关闭时间,默认时间为keepalive-timeout - 1s
100s
8、关于watchdog
resin3启动是多了一个watchdog的进程。可以单独启动也可以跟随resin.jar一起启动,主要是用来监控resin jvm实例,在必要的时候重启。
-Dcom.sun.management.jmxremote
6600
查看 watchdog 状态
java -jar lib/resin.jar status
Resin/3.1.6 status for watchdog at 127.0.0.1:6600
server '' : active
password: missing
user: root
root: /home/resin/
conf: /home/resin/conf/resin.conf
resin3.1.3+jdk1.6+hibernate+struts
配置了多个域名上去,服务器内存2G,jvm -Xmx使用1536m (1.5G)
每每重新上传了程序后必须要重新启动resin服务,虽然非常确定了类已经编译过去了,
但是hibernate还要重新初始化一下,只要2-3次,服务便会报outOfMemoryError错误。
不知道是java程序写的不好,资源没有释放,还是hibernate占用了太多的内存
如果没有上传新类,则没有outOfMemoryError的情况发生。
郁闷之中,恰好手边来了新的伙计,Dell 2950服务器,四核,4G内存,正好可以测试一下。
配置了一下Java的 Web服务。
我想新机器内存大,今儿个哥们高兴,给丫配个3G看看,谁知Resin居然不给面子,没有起来。
以下启动是加载的内存:
-Xmx3072m
-Xss1m
-Xdebug
-Dcom.sun.management.jmxremote
网上相关文档有介绍 Max Heap 为内存的70%的。
[2hei.net]# java -Xmx3072m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
[2hei.net]# java -Xmx2560m -version
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode)
经过几番测试后,感觉4G内存加载的最大内存为2560m,也就是2.5G,再大的话,resin无法启动。
Apache 一般有两种日志格式:
通用日志格式(Common Log Format) 和 组合日志格式(Combined Log Format)
http.conf中默认格式如下:
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
也可以使用自定义,这里使用`分隔 日志参数
%h`%l`%u`%{%Y-%m-%d %H:%M:%S}t`%r`%s`%b`%{Referer}i`%{User-Agent}i`%{X-Up-Calling-Line-ID}i
输出结果如下:
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"
172.16.0.115`-`-`2008-03-13 11:00:03`GET /logo.gif HTTP/1.1`200`2893`http://172.16.0.252/index.jsp `Opera/9.26 (Windows NT 5.1; U; zh-cn)`-
%h 这是发送请求到服务器的客户的IP地址,如果客户和服务器之间存在代理,那么记录中的这个IP地址就是那个代理的IP地址,而不是客户机的真实IP地址。
%l 这是由客户端identd进程判断的RFC1413身份(identity),输出中的符号"-"表示此处的信息无效。除非在严格控制的内部网络中,此信 息通常很不可靠,不应该被使用。只有在将IdentityCheck指令设为 On 时,Apache才会试图得到这项信息。
%u 这是HTTP认证系统得到的访问该网页的客户标识(userid),环境变量REMOTE_USER会被设为该值并提供给CGI脚本。如果状态码是401,表示客户未通过认证,则此值没有意义。如果网页没有设置密码保护,则此项将是"-"。
%{%Y-%m-%d %H:%M:%S}t
这是服务器完成请求处理时的时间。
其格式是:
[日/月/年:时:分:秒 时区]
日 = 2数字
月 = 3字母
年 = 4数字
时 = 2数字
分 = 2数字
秒 = 2数字
时区 = (+|-)4数字
可以在格式字符串中使用 %{format}t 来改变时间的输出形式,其中的format与C标准库中的strftime()用法相同。
如:%Y-%m-%d %H:%M:%S --- 2008-03-13 11:00:03
%r 引号中是客户端发出的包含许多有用信息的请求行。可以看出,该客户的动作是GET ,请求的资源是/logo.gif ,使用的协议是HTTP/1.1 。另外,还可以记录其他信息,如:格式字符串"%m %U%q %H"会记录动作、路径、查询字符串、协议,其输出和"%r"一样。
%s 这是服务器返回给客户端的状态码。这个信息非常有价值,因为它指示了请求的结果,或者是被成功响应了(以2开头),或者被重定向了(以3开头),或者出错了(以4开头),或者产生了服务器端错误(以5开头)。
服务器响应吗列表 :
Successful 2xx
200 OK .....
201 Created
202 Accepted
203 Non-Auth
204 No Conte
205 Reset Co
206 Partial
Redirection 3xx
300 Multiple
301 Moved Pe
302 Found ..
303 See Othe
304 Not Modi
305 Use Prox
306 (Unused)
307 Temporar
Client Error 4x
400 Bad Req
401 Unautho
402 Payment
403 Forbidd
404 Not Fou
405 Method
406 Not Acc
407 Proxy A
408 Request
409 Conflic
410 Gone ..
411 Length
412 Precond
413 Request
414 Request
415 Unsuppo
416 Request
417 Expecta
Server Error 5x
500 Internal
501 Not Impl
502 Bad Gate
503 Service
504 Gateway
505 HTTP Ver
%b 最后这项是返回给客户端的不包括响应头的字节数。如果没有信息返回,则此项应该是"-",如果希望记录为"0"的形式,就应该用%B 。
%{Referer}i
"Referer"请求头。此项指明了该请求是被从哪个网页提交过来的,http://172.16.0.252/index.jsp 这个网页应该包含有/logo.gif 或者其连接。
%{User-Agent}i
"User-Agent"请求头。此项是客户端提供的浏览器识别信息。如:(Opera/9.26 (Windows NT 5.1; U; zh-cn) Mozilla/4.08 [en] (Win98; I ;Nav )
%{X-Up-Calling-Line-ID}i
如果使用手机访问,并且移动(联通)网关可以返回访问者的手机号码。
今儿个做了一下Linux下resin的访问压力测试,感觉比较好玩,resin独立作为http Server
单点不做任何负载的情况下,resin最高可以坚持到3000访问,访问量在接近4000时http无响应。
测试环境:
FC6 + oralce10g + resin3.1.3
PC机配置: AMD Sempron(tm) Processor 3800+ , 1G RAM
内网环境: Web-Server IP: 172.16.0.252
系统内核:
# uname -a
Linux 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:54:20 EDT 2006 i686 athlon i386 GNU/Linux
系统参数:
more /etc/sysctl.conf
kernel.shmmax = 2147483648 (2G) #oracle配置时 使用 2G 805306368 #768M
kernel.shmmni = 4096
kernel.shmall = 2097152
kernel.sem = 250 32000 100 128
kernel.threads-max = 8192
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
net.core.rmem_default=262144
net.core.rmem_max=262144
net.core.wmem_default=262144
net.core.wmem_max=262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_sack =1
net.ipv4.tcp_window_scaling = 1
相关参数值说明
(1)shmmax:该参数定义了共享内存段的最大尺寸,因为安装了oracle,将其设置为2G。
(2)shmmni:这个内核参数用于设置系统范围内共享内存段的最大数量。该参数的默认值是 4096 。通常不需要更改。
(3)shmall:该参数表示系统一次可以使用的共享内存总量(以页为单位)。缺省值就是2097152,通常不需要修改。
(4)sem:该参数表示设置的信号量。
(5)file-max:该参数表示文件句柄的最大数量。文件句柄设置表示在linux系统中可以打开的文件数量。
(6)threads-max:表示指定内核所能使用的线程的最大数目。
Resin 3.1.3配置
resin.conf
-Xmx768m
-Xss1m
-Xdebug
1M
10240
65s
128
15s
因为pro版,需要license,所以使用resin3.1.3开源版。
当测试访问量达到512时,系统无法接受新的请求。
所以需要修改resin源文件,参考网上相关文章。
vi com.caucho.server.port.Port.Port.java
com.caucho.server.port.Port
// Secure override for load-balancers/proxies
private boolean _isSecure;
private InetAddress _socketAddress;
// default timeout
private long _socketTimeout = DEFAULT;
private int _connectionMax = 512 ; 改为 10240
private int _minSpareConnection = 16;
private int _keepaliveMax = DEFAULT;
编译成功后替换resin.jar相应的类,重启resin服务
使用压力测试工具MS web application: 3000访问.
Top 命令显示如下:
vmstat显示:
Load:
resin-status:http://172.16.0.252/resin-status
数据库连接池
http://172.16.0.252/proxoolAdmins
#netstat -an|grep ESTABLISHED|wc -l 已经建立的连接数
670
#netstat -an|wc -l 所有连接
2971
压力测试持续了10分钟,结果除了系统负载比较大外(达到了19以上),访问速度和响应还算可以。
达到峰值后的系统,我觉得瓶颈出现在cpu上,达到90%以上。另外系统的tcp连接数量还是根据linux的内核设置有关。虽然已经将resin的http请求线程数放大到了10240,其实这或许只是个理论期望值吧。
不知道还有什么地方可以继续调优的,或许使用resin-pro版本能更加好些?