Java监视活动Web会话

时间:2013-11-07 03:46:41

标签: java api session tomcat listener

我需要实现一个基于Web的应用程序,一旦部署在tomcat上,就可以监视部署在同一个tomcat上的所有应用程序的活动会话。

假设tomcat有2个应用程序正在运行1)ReportGenerator 2)DataSyncManager。我需要使用以下统计信息显示这两个应用程序的活动会话。

Seesion #   Application    Session Start Time

1234    ReportGenerator     XXXX
56748   DataSyncManager     XXXX
55565   DataSyncManager     XXXX

此外,我还要求即时终止会话。可能吗?请指教。

我知道这是类似tomcat /的管理控制台。但我需要将其实现为具有自定义日志记录和监视功能的自定义应用程序。请告诉我哪些框架/ api可用于捕获关于tomcat的活动会话及其统计信息。

4 个答案:

答案 0 :(得分:8)

我使用标准API和规范,没有第三方框架或库,使用通用方法实现了此功能。该解决方案已广泛用于部署在glassfish应用服务器和jboss中的许多企业级系统。它也已成功用于weblogic(12c)。但是,该方法应该适用于支持标准JMX规范的任何应用程序服务器或servlet容器。

tldr; 版本是为了创建两个JMX bean接口和一个http会话监听器。其中一个JMX bean接口为每个受监视的应用程序创建一个实例,并负责跟踪每个受监视应用程序的所有会话,它基本上提供每个应用程序的所有会话的统计信息。另一个JMX bean接口为每个受监视的应用程序中创建的每个会话创建一个实例。 http会话侦听器监视每个应用程序的会话并执行两项操作。通知与此应用程序对应的第一个JMX bean有关创建/销毁的会话,以便更新统计信息。从JMX服务注册或取消注册与会话相对应的JMX实例。

一旦设置好所有内容,就可以使用JMX客户端,例如jdk附带的jconsole和visualvm。从jmx客户端可以查看JMX bean的所有属性,也可以调用它们的任何方法。

以下屏幕截图来自使用jconsole的测试应用程序。

enter image description here

这些是与每个受监视应用程序对应的JMX bean实例的属性。

enter image description here

这些是可以在所选特定会话上执行的操作。

如果监视多个应用程序,则会出现更多具有自己结构的应用程序上下文,即每个jmx bean接口下的/ TestApplication,/ Application2等。

如何

最初需要创建两个JMX bean接口(simple tutorial),然后创建一个HttpSessionListener(大量在线教程)。

1.第一个JMX bean接口每个应用程序只有一个实例受监控,并将存储与从任何受监控的应用程序创建的会话相关的所有信息。它基本上用于持久性。我只将数据保存在内存中,这意味着如果服务器出现故障,数据将会丢失,但通常只要服务器启动就需要检查统计数据。如果要将数据持久保存到日志或数据库以便始终拥有此信息,您当然可以在接口的实现中执行此操作。

所以这可以如下,

public interface SessionsMXBean {

    /**
     * Get Indicates whether the data should be persisted in memory.
     */
    public boolean getPersistData();

    /**
     * Set Indicates whether the data should be persisted in memory.
     */
    public void setPersistData(boolean value);

    /**
     * Get All active sessions that have been persisted.
     */
    public String getActiveSessions();

    /**
     * Get All dates of each active session that has been persisted.
     */
    public String getDatesOfSessions();

    /**
     * Get The threshold for the number of session, after which persistence will
     * take place. If -1 all are persisted.
     */
    public int getSessionsThreshold();

    /**
     * Set The threshold for the number of session, after which persistence will
     * take place. If -1 all are persisted.
     */
    public void setSessionsThreshold(int value);

    /**
     * Set The limit of size to be persisted in KB. If -1 then no size limit.
     */
    public void setPersistenceSize(long value);

    /**
     * Clears all persisted data.
     */
    public void clearData();

    /**
     * Unregisters this instance
     */
    public void unregisterThis();
}

然后你必须创建一个最终会保存这种数据的接口实现。

    public class SessionsImpl implements SessionsMXBean {
    /*
    here you need to implement the interface and have all kind of objects you require
    */
      public synchronized void incrementSessions() {
        ....
      }

      public synchronized void decrementSessions() {
        .....
      }

2.第二个JMX bean接口将为每个受监控应用程序中创建的每个会话创建一个实例。此接口将存储会话对象,并且还将具有可从jmx客户端调用的方法,以使这些会话无效。 这可以如下,

public interface HttpSessionMXBean {

    /**
     * Get HTTP Session id
     */
    public String getSessionId();

    /**
     * Get the date created
     */
    public String getDateCreated();

    /**
     * Get the date created in milliseconds
     */
    public long getMillisCreated();

    /**
     * Get attributes from http session
     *
     * @param attrName Attribute Name
     * @return java.lang.String
     */
    public String getAttribute(String attrName);

    /**
     * Invalidate this session
     */
    public void invalidate();

    /**
     * Unregisters this instance
     */
    public void unregisterThis();
}

再次需要实施,

public class HttpSessionMXBeanImpl implements HttpSessionMXBean {
....

3.然后创建HttpSessionListener,它将创建/删除第二个bean接口的实例,并从服务器的JMX服务注册/取消注册它们。这将在创建会话并使其无效/过期时发生。因此,每个应用程序都有一个侦听器,它在web.xml中定义了它。

HttpSessionListener

        ....
        public class MyJMXHTTPSessionListener implements HttpSessionListener {
        ....
          private SessionsImpl sesssionsImpl;
          private Map<String, HttpSessionMXBeanImpl> httpSessionMXBeans

          @Override
          public void sessionCreated(HttpSessionEvent se) {
            //requires synchronized block here with this i.e.
            synchronized (this) {
            /*check if a jmx bean instance of the 1st interface exists otherwise create one*/
    if(sessionsImpl==null){
    sesssionsImpl= new SesssionsImpl();
/* take care here to create a nice and unique path per instance 
of the application in order to be nicely presented on the JMX tree of the JMX clients  */
                        String id = ("services.jmx.beans:type=Sessions,"+ "realm=" + se.getSession().getServletContext().getContextPath());
                        sessionManagerMXBean.setId(id);
                        ObjectName objectName = new ObjectName(id);
                        if (ManagementFactory.getPlatformMBeanServer().isRegistered(objectName)) {
                            ManagementFactory.getPlatformMBeanServer().
                                    unregisterMBean(objectName);
                        }
                        ManagementFactory.getPlatformMBeanServer().
                                registerMBean(sesssionsImpl,
                                objectName);
    }

    sesssionsImpl.inrementSessions();

    /*

               create a jmx bean instance of the 2nd interface

 and register it to the jmx service as already shown using the unique session id

 and a nice path indicating the 2nd interface jmx beans.
    */

          }

          @Override
          public void sessionDestroyed(HttpSessionEvent se) {
            //requires synchronized block here with this i.e.
            synchronized (this) {
            /*unregister the jmx bean instance of the 2nd interface, 

remove it from the list 

and call decrementSessions() on the jmx bean instance corresponding to this app*/
            }
          }
        }

如果您通过添加以下几行在web.xml文件中定义HttpSessionListener,则可以随时为任何Web应用程序轻松激活此功能,

<强>的web.xml

<listener>
  <listener-class>
    myservices.myhttpsessionlisteners.MyJMXHTTPSessionListener
  </listener-class>
</listener>

答案 1 :(得分:4)

您是否查看了psi-probe项目?

它是Apache Tomcat的高级管理器和监视器,源自Lambda Probe。

答案 2 :(得分:2)

@melc的答案提供了一个很好的通用解决方案。如果它只在Tomcat上运行,你也可以使用更简单的版本:

在其中一个servlet中实现org.apache.catalina.ContainerServlet接口(您可以在&lt; Tomcat安装路径&gt; \ lib \ catalina.jar中找到它。)

import org.apache.catalina.Context;
import org.apache.catalina.Session;
import org.apache.catalina.Wrapper;

public void setWrapper(Wrapper w) {
    this.wrapper = w;
    context = (Context) wrapper.getParent();
    // This'll give you all sessions:
    org.apache.catalina.Session[] sessions = context.getManager().findSessions();
    for (int i = 0; i < sessions.length; i++) {
        System.out.println(sessions[i]);
    }
    host = (Host) context.getParent();
    // contexts are the list of applications deployed on Tomcat
    Context[] contexts = (Context[]) host.findChildren();
    for (Context context:contexts) {
        //Or to access session list by application, 
        //call findSessions() on the target context
        org.apache.catalina.Session[] sessions = context.getManager().findSessions();
    }
}

顺便说一下,您需要在context.xml中将Context定义为特权:

<Context privileged="true">

答案 3 :(得分:0)

Tomcat AddOns

Lambda Probe releases (以前称为Tomcat Probe)-实时监视和管理Apache Tomcat实例的终极工具。 Lambda Probe将通过易于使用且友好的Web界面帮助您可视化有关Apache Tomcat实例的实时信息。

PSI Probe是Apache Tomcat的高级管理器和监视器,由Lambda Probe分叉到GitHub。

Installation of ApacheTomcat:下载War文件并放在webapp文件夹中,通过向任何用户添加manager-gui角色来更改配置文件

<role rolename="manager-gui"/>
<user username="tomcat" password="s3cret" roles="manager-gui"/>