zoukankan      html  css  js  c++  java
  • 服务端tomcat的简单监控

    由于线上对tomcat监控处于失控的状态(只能通过跳转,简单地jstack/jstat进行监控),故需要针对tomcat快速查看其运行状态
     

    Tomcat-manager

     
    在tomcat/webapps中存在目录 manager,用于初步监控tomcat jvm相关参数指标。此时,用户需要手动编辑conf/tomcat-users.xml配置文件,加入一行:
     
    <user username="servermon" password="passwd" roles="manager-gui"/>
     
     
    用于声明可以进行管理tomcat的后端用户名和密码,此时就可以通过下面的url查看tomcat的整体服务状态,了解jvm堆的状态以及线程列表,并查看到所有的应用列表:
     
    http://localhost:8080/manager/status/all,通过用户名和密码进行登录操作,如果登录出错可能会出现401和403错误:
     


     
     
    但我们部署的tomcat都没有设置manager服务(webapps目录都已经将应用之外的目录删除掉了),而且其能够查看的指标也少的可怜。
     

    Psi-Probe

     
    项目源码所在地址:https://github.com/psi-probe/psi-probe,从github上clone下代码后,调用mvn clean package命令,进行编译,将生成的war包复制到需要监控的tomcat/webapps目录下,重新启动tomcat,生成的war包在目录./web/target/probe.war下。
     
    psi-probe是lambdaprobe的一个分支版本,用于对Tomcat进行监控,比tomcat的manager强大很多。psi就是一个形如叉子的符号Ψ,希腊字母的第23个字母,用来代表fork。为啥需要分支呢,因为lambdaprobe已经多年没有更新(大致在2006年就停止发布新版本了)。
     
    关于psi-probe的权限说明,可以参考文档:http://blog.csdn.net/fbysss/article/details/6221917http://www.iigrowing.cn/tomcat_xing_neng_jian_kong_gong_ju_probe_jian_jie.html,需要注意的是,使用probe同样要求使用配置好 tomcat-users.xml。
     
    部署完成后,就可以通过 localhost:8080/probe 链接查看tomcat中的所有的相关信息:
     


     
     
     
    但是上述监控工具都不能针对java虚拟机中的具体类型进行细致的监控(针对我们定义的每个对象),我们需要找到一款可以检测tomcat内部的jmx客户端:http://stackoverflow.com/questions/5004958/web-based-jmx-console-for-tomcat
     

    配置JMX使用jconsole监测远程tomcat

     
    <!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
    编写配置文件 jstatd.java.policy策略文件:
     
    # cat jstatd.java.policy
    grant codebase "file:${java.home}/../lib/tools.jar" {
     permission java.security.AllPermission;
    };
     
     
    开启jstatd守护进程
     
    jstatd -J-Djava.security.policy=/root/jstatd.all.policy -J-Djava.rmi.server.logCalls=true(开启日志功能)
    
     
     
    jstatd -J-Djava.security.policy=jstatd.all.policy
    Could not create remote object
    access denied ("java.util.PropertyPermission" "java.rmi.server.ignoreSubClasses" "write")
    java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.rmi.server.ignoreSubClasses" "write")
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
        at java.security.AccessController.checkPermission(AccessController.java:884)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.System.setProperty(System.java:789)
        at sun.tools.jstatd.Jstatd.main(Jstatd.java:139)
     
     
    http://docs.oracle.com/javase/7/docs/technotes/tools/share/jstatd.html,编写该文件不需要自作聪明地将java.home设置成其他属性,只需要按照文档中说明的即可。
     
    在启动tomcat的时候(修改执行tomcat的文件,catalina.sh),需要加入以下JVM参数:
     
    -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.1.165
    
     
    说明:
    1.-Dcom.sun.management.jmxremote.port:这个是配置远程connection的端口号的,要确定这个端口没有被占用;
    2.-Dcom.sun.management.jmxremote.ssl=false 指定了 JMX 是否启用 ssl;
    3.-Dcom.sun.management.jmxremote.authenticate=false指定了JMX 是否启用鉴权(需要用户名,密码鉴权),
    2,3两个是固定配置,是 JMX的远程服务权限的;
    4.-Djava.rmi.server.hostname:这个是配置server的IP的;
     
    在CentOS环境中启动jstatd仍然出现错误,
     
    Could not bind /JStatRemoteHost to RMI Registry
    java.rmi.ConnectIOException: Exception creating connection to: 0.0.0.2; nested exception is:
        java.net.SocketException: Invalid argument or cannot assign requested address
        at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:631)
        at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
        at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
        at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341)
        at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
        at java.rmi.Naming.rebind(Naming.java:177)
        at sun.tools.jstatd.Jstatd.bind(Jstatd.java:57)
        at sun.tools.jstatd.Jstatd.main(Jstatd.java:143)
    Caused by: java.net.SocketException: Invalid argument or cannot assign requested address
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:579)
        at java.net.Socket.connect(Socket.java:528)
        at java.net.Socket.<init>(Socket.java:425)
        at java.net.Socket.<init>(Socket.java:208)
        at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
        at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147)
        at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
        ... 7 more
    
     
    通过阅读下面的文档 http://my.oschina.net/xiaotian120/blog/207015,经过服务器上的一番调研,发现问题出现在hostname上,服务端调用 hostname -i 命令,显示出来的服务器主机名为0.0.0.2(这一点日志中有体现)。
     
    如果需要手动设置密码,可以参考:http://wiki.jikexueyuan.com/project/tomcat/monitoring-management.html,来加入鉴权相关命令,编辑访问权限文件jmxremote.access, 以及密码文件jmxremote.password。 
     

    JMX监测程序中的某些行为 

    <!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
     
    JMX是一个框架,提供了一种功能,可以实时查询应用程序中通过JMX向外部公布的相应参数或者是其他应用程序,同时也可以通过JMX来实时地调用应用程序使用JMX向外部公布的接口,来完成一些功能操作。
     
    我们还是从JMX能给我们提供什么好处入手来理解吧。举一个应用实例:在一个系统中常常会有一些配置信息,比如服务的IP地址,端口号什么的,那么如何来写这些代码呢? 
     
    1、初级程序员一般是写死在程序里,到要改变时就去改程序,然后再编译发布; 
     
    2、程序熟手则一般把这些信息写在一个配置文件里(JAVA一般都是*.properties文件),到要改变时只要改配置文件,但还是重新启动系统,以便读取配置文件里的新值; 
     
    3、程序好手则会写一个段代码,把配置值缓存起来,系统在读值的时候,先看看配置文件有 没有更动。如有更改则重读一遍,否则从缓存里读取值 
     
    4、程序高手则懂得取物为我所用,用JMX!把配置属性集中在一个类,然后写一个叫MBean的东东,再配置一下就轻松搞定了。而且JMX自动提供了一个WEB页面来给你来改变这些 配置信息。
     


     
     
    通过JMX可以轻松地为应用程序添加管理功能,在尽可能少的改变原有系统代码基础上实现对原系统的管理。
     
     
    概念 含义  
    Managable resource 可被管理的资源可以是应用程序,设备或者存在的能够被java程序所访问或者包装的实体。通过JMX可以管理这些资源。应用程序能够暴露自己的组件,API或者附加的资源,使得JMX能够管理应用程序。可被管理的资源甚至可以是网络上的设备,例如打印机。可被管理的资源作为一个实体被JMX MBean所管理。  
    MBean
    MBean(managed bean)是一个Java类,符合JMX specification所规定的命名和继承规范。实例化的MBeans是Java对象,其中所暴露出来的接口(management interface)能够操作和访问manageable resources。这些接口是由MBean的属性和操作组成。
    Management application通过访问MBean来访问属性和调用操作。MBean分三种类型:Standard,Dynamic和Model MBean.每一种类型都是针对于特定的manageable resource来使用的。
     
    JMX Agent JMX agent是一个Java process,能够为管理MBean的集合提供服务,是MBean Server的容器。这些服务可以是建立MBean的之间的关系,动态加载类,监控服务,作为计时器。  
    Management application 一个management application可以是任何的用户程序,用于和任意多的JMX agent之间建立接口。对于一些设计好的符合JMX技术的management appliction,JMX agents能够建立和该management application的联系,JMX agents也能够建立和那些先前没有考虑用JMX技术的management application建立联系。  
    传输和安全性 JMX 指定了在 MBeanServer 和 JMX 客户之间通信所使用的协议,协议可以在各种传输机制上运行。可以使用针对本地连接的内置传输,及通过 RMI、socket 或 SSL 的远程传输(可以通过 JMX Connector API 创建新的传输)。认证是由传输执行的;本地传输允许用相同的用户 ID 连接到运行在本地系统上的 JVM;远程传输可以用口令或证书进行认证。本地传输在 Java 6 下默认就是启用的。要在 Java 5.0 下启用它,需要在 JVM 启动时定义系统属性 com.sun.management.jmxremote。“Monitoring and Management using JMX” 这份文档(请参阅参考资料)描述了启用和配置传输的配置步骤。  
     
     
     

    新建第一个MXBean

     
     
    注册时使用MBeanServer进行注册的操作,给定对应的mbean,mbeanServer会根据该bean实现的接口去寻找其对应的MBean定义。
     
            
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            ControllerMBean controllerMBean = new ControllerBean();
            mbs.registerMBean(controllerMBean, new ObjectName("MyAppmbean:name=controller"));
     
     
    出现问题
     
    javax.management.NotCompliantMBeanException: jmx.ControllerBean: Class jmx.ControllerBean is not a JMX compliant MXBean
        at com.sun.jmx.mbeanserver.Introspector.throwException(Introspector.java:466)
        at com.sun.jmx.mbeanserver.Introspector.getMXBeanInterface(Introspector.java:357)
        at com.sun.jmx.mbeanserver.Introspector.checkCompliance(Introspector.java:166)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:317)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
        at jmx.Main.main(Main.java:16)
     
     
    经过分析JMX.isMXBeanInterface方法,可以看出,在registerMBean的时候,会根据当前类实现的接口列表,查找符合MXBean定义的接口,如果接口不符合MXBean的定义就会抛出上面的错误,如何使得接口满足MXBean类型,一种是接口名称以“MXBean”结尾,一种是加入@MXBean Annotation。
     
    public static boolean isMXBeanInterface(Class<?> interfaceClass) {
            if (!interfaceClass.isInterface())
                return false;
            if (!Modifier.isPublic(interfaceClass.getModifiers()) &&
                !Introspector.ALLOW_NONPUBLIC_MBEAN) {
                return false;
            }
            MXBean a = interfaceClass.getAnnotation(MXBean.class);
            if (a != null)
                return a.value();
            return interfaceClass.getName().endsWith("MXBean");
            // We don't bother excluding the case where the name is
            // exactly the string "MXBean" since that would mean there
            // was no package name, which is pretty unlikely in practice.
        }
     
     
    Spring与JMX的整合
     
     
    对于标准的MBean来说,主要是通过MBeanExporter来实现的,比如上面我们提到的MBean,就可以通过配置mbServer以及mbean的方式管理MXBean:
     
        
    <bean id="mbServer" class="org.springframework.jmx.export.MBeanExporter">
            <property name="autodetectModeName" value="AUTODETECT_ALL"/>
        </bean>
    
        <bean name="mydomain:myobj=MyObjectMBean" class="com.api.example.jmx.ControllerBean"/>
     
     
    上面的配置中,MBeanExporter会查找本地MBean Server,指定的探测模式autodetectModeName为AUTODETECT_ALL,无需手动向MBean Server进行注册,便可以管理配置中的MBean对象。
     

    基于注解的MBean管理

     
    @ManagedResource表示指定该类的实例作为MBean注册到MBean Server中,然后通过对属性和方法分别使用@ManagedAttribute和@ManagedOperation来指定暴露的属性和方法,
     
    @Component
    @ManagedResource(objectName = "org.springexample.jmx:name=ServerManager", description = "Server Manager")
    public class ServerManagerImpl {
    
        private String serverName = "springServer";
        private boolean serverRunning = true;
        private int minPoolSize = 5;
        private int maxPoolSize = 10;
    
        @ManagedAttribute(description = "The server name.")
        public String getServerName() {
            return serverName;
        }
    
        @ManagedAttribute(description = "Server's running status.")
        public boolean isServerRunning() {
            return serverRunning;
        }
    
        @ManagedAttribute(description = "Whether or not the server is running.", currencyTimeLimit = 20, persistPolicy = "OnUpdate")
        public void setServerRunning(boolean serverRunning) {
            this.serverRunning = serverRunning;
        }
    
        @ManagedOperation(description = "Change db connection pool size.")
        @ManagedOperationParameters({
                @ManagedOperationParameter(name = "min", description = "Minimum pool size."),
                @ManagedOperationParameter(name = "max", description = "Maximum pool size.")
        })
        public int changeConnectionPoolSize(int minPoolSize, int maxPoolSize) {
            Assert.isTrue(minPoolSize > 0, "Minimum connection pool size must be larger than 0, min=" + minPoolSize);
            Assert.isTrue(maxPoolSize > minPoolSize, String.format("Minimum connection pool size must be smaller than maximum, min=%s, max=%s", minPoolSize, maxPoolSize));
    
            this.minPoolSize = minPoolSize;
            this.maxPoolSize = maxPoolSize;
    
            int diff = maxPoolSize - minPoolSize;
    
            Random random = new Random();
            int currentSize = (minPoolSize + random.nextInt(diff));
    
            return currentSize;
        }
    
    }
     
     
    基于spring基于注解的MBean管理可以针对一个普通的Java类,指定暴露的属性和方法,此时在spring applicationContext中声明的内容就要少很多,只需要声明扫描的package,以及mbean-export即可。
     
    <context:component-scan base-package="com.api.example"/>
    <context:mbean-export/>
     
     
    示例中我们就可以简单地动态修改类似池话的一些配置资源。
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    The Quad
    将OrCAD Capture CIS的设计文件(.dsn)导入到PADS Logic VX.2.3
    OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件
    Eclipse IDE 添加jar包到Java工程中
    PADS Logic VX.2.3 修改软件界面语言
    切换Allegro PCB Editor
    Allegro PCB Design GXL (legacy) 将brd文件另存为低版本文件
    Allegro PCB Design GXL (legacy) 设置自动保存brd文件
    Could not create an acl object: Role '16'
    windows 下apache开启FastCGI
  • 原文地址:https://www.cnblogs.com/mmaa/p/5789858.html
Copyright © 2011-2022 走看看