一次Tomcat溢出的临时处理
公司服务器上Tomcat不知哪个项目有隐患代码,经常溢出,不停的重启! 起初打算用Jprofiler监控下内存(回头会准备个完整的例子),但发现线上环境bin目录下的.sh被修改的乱七八糟,导致某些.sh无法运行,所以就打算写个RMI的定时gc程序,现用虚拟机模拟下线上环境环境信息如下:
Red Hat Enterprise Linux Server release 6.3 (Santiago)
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
apache-tomcat-6.0.41
jprofiler7 linux-x64
ip: 10.211.55.4
------------------------------------------------------------------------------------------------------------------------
1.配置Tomcat RMI
Tomcat打开RMI
1
JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Djava.rmi.server.hostname=10.211.55.4 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false"
配置hostname
1
hostname 10.211.55.4
防火墙开放端口
1
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9999 -j ACCEPT
重启防火墙
1
/etc/init.d/iptables restart
配置授权
a.拷贝jmxremote.password.template到本地目录,名为jmxremote.password
1
2
cd /usr/java/jdk1.6.0_45/jre/lib/management
cp jmxremote.password.template jmxremote.password
b.编辑jmxremote.access文件,添加用户和权限
1
2
3
tango readwrite \
create javax.management.monitor.*,javax.management.timer.* \
unregister
c.编辑jmxremote.password文件,设置用户密码
1
tango rmipassword
d.修改jmxremote.password文件为只读
1
chmod 600 jmxremote.password
用Jconsole测试RMI
a.启动Tomcat
1
./startup.sh
b.测试RMI,客户端键入如下命令,前提是java安装目录配置到PATH中
显示以上画面,则说明rmi连接成功!
2.编写程序
需求:
1.定时通过RMI通知remote jvm 执行gc任务,
2.执行次数和运行时间
代码片段如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public static void main(String[] args) throws IOException, MalformedObjectNameException {
Properties properties = Console.parseArguments(args);
//
final String host = properties.getProperty(HOST, "localhost");
final String port = properties.getProperty(PORT, "1099");
final String interval = properties.getProperty(INTERVAL);
final String tryCount = properties.getProperty(TRY);
final String rmiServer = getRMIServer(host, port);
final String user = properties.getProperty(USER);
final String pass = properties.getProperty(PASS);
final String report = properties.getProperty(REPORT, "./gc.out");
//
final Invoke invoke = new Invoke() {
@Override
public Object execute(JMXConnector connector) throws IOException, MalformedObjectNameException {
MBeanServerConnection mBeanServerConnection = connector.getMBeanServerConnection();
MemoryMXBean memoryMXBean = JMX.newMBeanProxy(mBeanServerConnection, ObjectName.getInstance("java.lang:type=Memory"), MemoryMXBean.class);
memoryMXBean.gc();
return null;
}
};
if (interval == null) {
execute(rmiServer, user, pass, invoke);
} else {
final int i = interval.matches("\\d+") ? Integer.parseInt(interval) : 6000;
final int t = tryCount.matches("\\d+") ? Integer.parseInt(tryCount) : 3;
final File reportFile = new File(report);
if (!reportFile.exists()) {
reportFile.createNewFile();
} else if (reportFile.isDirectory()) {
throw new RuntimeException(new MessageFormat("can`t write file {0},file is directory!").format(new String[]{reportFile.getAbsolutePath()}));
} else if (!reportFile.canWrite()) {
throw new RuntimeException(new MessageFormat("can`t write file {0},file is readonly!").format(new String[]{reportFile.getAbsolutePath()}));
}
new Thread(new Runnable() {
private final ThreadLocal<AtomicInteger> error = new ThreadLocal<AtomicInteger>();
private final ThreadLocal<AtomicInteger> local = new ThreadLocal<AtomicInteger>();
private final ThreadLocal<Date> start = new ThreadLocal<Date>();
@Override
public void run() {
local.set(new AtomicInteger(0));
error.set(new AtomicInteger(0));
start.set(new Date());
while (true) {
AtomicInteger errorAtomic = error.get();
try {
if (errorAtomic.get() > t) {
return;
}
execute(rmiServer, user, pass, invoke);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
errorAtomic.addAndGet(1);
}
report();
}
}
private void report() {
AtomicInteger runAtomic = local.get();
AtomicInteger errorAtomic = error.get();
Date date = start.get();
runAtomic.addAndGet(1);
try {
FileOutputStream fileOutputStream = new FileOutputStream(reportFile);
PrintWriter writer = new PrintWriter(fileOutputStream, false);
writer.write("run : ".concat(String.valueOf(runAtomic.get())));
writer.write("\r\n");
long l = (new Date().getTime() - date.getTime()) / 1000;
writer.write("run time: ".concat(String.valueOf(l).concat("s")));
writer.write("\r\n");
writer.write("error : ".concat(String.valueOf(errorAtomic.get())));
writer.write("\r\n");
writer.flush();
writer.close();
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
throw new RuntimeException(e);
}
}
}).start();
}
}
get start:
1
java -classpath "..." org.tango.tools.Gc --host=10.211.55.4 --port=9999 --interval=10000 --try=10 --user=tango --pass=rmipassword
此方法是被逼无奈,最好还是检查工程代码,查看溢出原因!
下回说Jprofiler监控Tomcat
本文完!(下附工程代码,maven构建)
页:
[1]