JBoss EAP应用获取运行模式、相关路径及节点信息

一、背景

某应用系统在JBoss EAP 7.0的standalone模式(单实例模式)下运行正常,但在切换到domain模式(域模式)后陆续发现一些问题。为解决这些问题产生了这样的需求:如何判断JBoss运行在哪种模式?随之又产生了其它需求:如何获取相关路径的信息?如何获取集群(Cluster)中的所有节点信息?

二、解决思路

对于第2个需求,是容易解决的,因为JBoss EAP预置的各种属性(property)中就包含了相关路径的定义,如:jboss.home.dir(JBoss EAP安装目录,即${JBOSS_HOME})、jboss.server.base.dir(JBoss EAP的当前Server的主目录)、jboss.domain.base.dir(JBoss EAP在域模式下的主目录)等等,详见https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.1/html-single/configuration_guide/的Table3.3。

以此为基础,则第1个需求也找到一个很简单的解决方法:根据jboss.domain.base.dir的值来判断,在域模式下它的值通常是:${JBOSS_HOME}/domain,而在单实例模式下,其值为null。经测试,在7.x及6.x版都运行正常。

但第3个需求的解决就困难的多,在查阅大量资料及反复进行试验后,终于发现可以通过wildfly-clustering-api-yyy.jar及wildfly-clustering-server-xxx.jar(其中xxx、yyy为各自的版本号)提供的接口来实现。由于wildfly-clustering-server-xxx.jar只在JBoss EAP 7.x内置加载,本解决方案只在7.x版得以验证,限于时间因素未能得出在6.x中实现的具体方法。

三、接口类、实现类、显示页面

重点有三个组成部分:接口类DispInfoRemote,实现类DispInfo,以及用于显示的index.jsp。

接口类示例代码:

package test;

import java.util.List;

import javax.ejb.Remote;

@Remote
public interface DispInfoRemote {
    public void setID(String sessionID);
    public void setTime(String createTime);
    public String getID();
    public String getTime();
public List<String> getNodesInfo();
}

实现类示例代码:

package test;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import org.wildfly.clustering.group.Group;
import org.wildfly.clustering.group.Node;

/**
 * Session Bean implementation class DispInfo
 */
@Stateless
@Remote
public class DispInfo implements DispInfoRemote {
    
    @Resource(lookup = "java:jboss/clustering/group/web")  
    private Group group;

    //sessionID和createTime用于验证域模式下是否实现session复制
    private String sessionID;
    private String createTime;
    
    /**
     * Default constructor. 
     */
    public DispInfo() {
    }

    public void setID(String sessionID) {
        this.sessionID = sessionID;
    }
    public void setTime(String createTime) {
        this.createTime = createTime;
    }
    public String getID() {
        return sessionID;
    }
    public String getTime() {
        return createTime;
    }
//获取集群中所有节点的信息
    public List<String> getNodesInfo() {
         
        List<Node> nodes = group.getNodes();
        List<String> lists = new ArrayList<String>();
 
        for (Node node: nodes)
        {
            String str = node.getName() + ", " + node.getSocketAddress();
            lists.add(str);
        }
        return lists;
    }
    
}

需要指出的时,集群(cluster)并非只能在域模式下模式,在单实例模式下,多个节点也可通过standalone-ha.xml或standalone-full-ha.xml组成一个集群。限于篇幅,不在本文讨论。

index.jsp的示例代码:

<%@ page language="java" import="java.util.*"%>
<%@ page import="javax.naming.*, java.util.Properties" %>
<%@ page import="test.DispInfoRemote" %>
<%
    Hashtable<String, String> jndiProperties = new Hashtable<String, String>();
    jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
%>
<%!    DispInfoRemote diw = null;
%>
<%    try {
        Context ctx = new InitialContext(jndiProperties);
        final String appName = "";
        final String moduleName = "TestEjb";
        final String distinctName = "";
        final String beanName = "DispInfo";
        final String className = DispInfoRemote.class.getName();
    
        Object obj = ctx.lookup("ejb:" + appName + "/" + moduleName + 
                "/" + distinctName + "/" + beanName + "!" + className);
    
        diw = (DispInfoRemote)obj;
        diw.setID(session.getId());
        out.print(session.getId());
        diw.setTime(Long.toString(session.getCreationTime()));
    } catch (NamingException e) {
        e.printStackTrace();
    }
%>
<html>
  <head><title>JBossEap</title></head>
  <body>
    <h1><font color="red">JBossEap</font></h1>
    <table align="centre" border="1">
      <tr>
        <td>Session ID</td>
        <td><%= this.diw.getID() %></td>
      </tr>
      <tr>
        <td>Created on</td>
        <td><%= this.diw.getTime() %></td>
      </tr>
      <tr>
        <td>"{jboss.home.dir}"</td>
        <td><%= System.getProperty("jboss.home.dir") %></td>
      </tr>
      <tr>
        <td>"{jboss.server.base.dir}"</td>
        <td><%= System.getProperty("jboss.server.base.dir") %></td>
      </tr>
      <tr>
        <td>"{jboss.domain.base.dir}"</td>
        <td><%= System.getProperty("jboss.domain.base.dir") %></td>
      </tr>
      <tr>
        <td>"{jboss.node.name}"</td>
        <td><%= System.getProperty("jboss.node.name") %></td>
      </tr>
      <tr>
        <td>"{jboss.server.name}"</td>
        <td><%= System.getProperty("jboss.server.name") %></td>
      </tr>
      <% List<String> nodesInfo = this.diw.getNodesInfo();
      %>
      <tr>
        <td>Cluster Node Count</td>
        <td><%= nodesInfo.size() %> </td>
      </tr>
      <%
         for (int i=0; i<nodesInfo.size(); i++)
         {
      %>
      <tr>
        <td>  Node <%= i+1%> </td>
        <td><%= nodesInfo.get(i) %> </td>
      </tr>
      <% }%>
    </table>
  </body>
</html>

四、测试结果

此处仅仅是为测试,为图省事将上述三项放入一个工程,并打包成一个cluster.war,分别部署到JBoss EAP的单实例模式和域模式下进行测试。

在standalone模式下的页面截图如下:

可以看到,此时的jboss.domain.base.name的值为null,而jboss.node.name和jboss.server.name为节点的hostname,且Cluster只有一个节点,节点名等同于jboss.server.name,有时会获取不到SocketAddress。

在domain模式下的页面截图为:

可以看到,此时jboss.domain.base.name的值已是${JBOSS_HOME}/domain,而jboss.node.name和jboss.server.name的值也发生改变,与在domain.xml里的配置一致;Cluster所有节点的信息也全部列出,SocketAddress也始终能获取到。

五、总结

通过上述方法,3个需求均得到解决,应用系统也得以修改后在域模式和集群环境下正确运行。

网上能获得的JBoss EAP有效资料比较少,很多还是6.x版的陈旧资料,尤其是在不能google的情况下。

猜你喜欢

转载自www.cnblogs.com/wggj/p/9493649.html