Java监视活动Web会话

Dar*_*ght 8 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
Run Code Online (Sandbox Code Playgroud)

此外,我有一个要求即时杀死会话.可能吗?请指教.

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

mel*_*elc 9

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

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

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

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

在此输入图像描述

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

在此输入图像描述

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

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

如何

最初需要创建两个JMX bean接口(简单教程),然后创建一个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();
}
Run Code Online (Sandbox Code Playgroud)

然后,您必须创建此接口的实现,最终将保存此类数据.

    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() {
        .....
      }
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

并且还需要实施,

public class HttpSessionMXBeanImpl implements HttpSessionMXBean {
....
Run Code Online (Sandbox Code Playgroud)

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*/
            }
          }
        }
Run Code Online (Sandbox Code Playgroud)

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

web.xml中

<listener>
  <listener-class>
    myservices.myhttpsessionlisteners.MyJMXHTTPSessionListener
  </listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)