公司服务器上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
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
hostname 10.211.55.4
防火墙开放端口
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9999 -j ACCEPT
重启防火墙
/etc/init.d/iptables restart
配置授权
a.拷贝jmxremote.password.template到本地目录,名为jmxremote.password
cd /usr/java/jdk1.6.0_45/jre/lib/management cp jmxremote.password.template jmxremote.password
b.编辑jmxremote.access文件,添加用户和权限
tango readwrite \ create javax.management.monitor.*,javax.management.timer.* \ unregister
c.编辑jmxremote.password文件,设置用户密码
tango rmipassword
d.修改jmxremote.password文件为只读
chmod 600 jmxremote.password
用Jconsole测试RMI
a.启动Tomcat
./startup.sh
b.测试RMI,客户端键入如下命令,前提是java安装目录配置到PATH中
显示以上画面,则说明rmi连接成功!
2.编写程序
需求:
1.定时通过RMI通知remote jvm 执行gc任务,
2.执行次数和运行时间
代码片段如下:
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, "3"); 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:
java -classpath "..." org.tango.tools.Gc --host=10.211.55.4 --port=9999 --interval=10000 --try=10 --user=tango --pass=rmipassword
此方法是被逼无奈,最好还是检查工程代码,查看溢出原因!
下回说Jprofiler监控Tomcat
本文完!(下附工程代码,maven构建)