一次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

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中

        

wKioL1Pg2hCR0vo4AAEpPHxWUsA469.jpg

wKiom1Pg2P3Ald9dAAHq1b37KQU912.jpg

            显示以上画面,则说明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


    wKioL1Pg_snjwIRQAABRaeawpzY028.jpg


wKiom1Pg2zLB6Qc8AAC37s8TZvc213.jpg


此方法是被逼无奈,最好还是检查工程代码,查看溢出原因!

下回说Jprofiler监控Tomcat

本文完!(下附工程代码,maven构建)

你可能感兴趣的:(java,tomcat,JConsole,rmi)