WebLogic 集成

连接性 > 容器 > WebLogic 集成

ActiveMQ Classic WebLogic 集成

ActiveMQ Classic 客户端和代理可以在 WebLogic Server 或 WebLogic Express 中运行。这通常出于许可原因。

  • WebLogic Server 包含 JMS 客户端和服务器功能,但使用这些 JMS 功能将多个服务器连接在一起(而不是仅在单个服务器内部使用 JMS)可能需要额外付费。
  • WebLogic Express 通过许可证禁用 JMS 功能,因此虽然 JMS 类位于类路径上,但没有可用的 JMS 功能。
    可以在 WebLogic 中运行 ActiveMQ Classic 代理来提供 JMS 功能,同时避免这些问题。此外,可以在 WebLogic 中运行 ActiveMQ Classic 客户端以连接到在同一 WebLogic 实例中运行的 ActiveMQ Classic 代理,以及在远程 WebLogic 实例中运行的 ActiveMQ Classic 代理,或在网络上其他位置运行的独立 ActiveMQ Classic 代理。

WebLogic 中的 ActiveMQ Classic 客户端

ActiveMQ Classic 客户端可以在任何最近的 WebLogic 版本中运行。但是,具体细节取决于 WebLogic 版本支持的 JMS 版本。

包含 JMS 1.0.x 的 WebLogic Server/Express 版本

已知这包括 **WebLogic 8.1** 及所有以前版本。

**注意:**在此版本的 WebLogic 中,ActiveMQ Classic 无法向消息驱动 Bean 传递消息。您需要手动创建 JMS 客户端来发送和接收 JMS 消息。

要从这些 WebLogic 版本之一使用 ActiveMQ Classic,您不应该将任何 javax.jms 类包含到您的应用程序中,而应该使用与 WebLogic 一起分发的 JMS 1.0.x 类。这意味着您不应该使用完全聚合的 ActiveMQ Classic JAR,例如 activemq-4.0.1/incubator-activemq-4.0.1.jar,而是应该使用单独的 ActiveMQ Classic JAR,例如 activemq-4.0.1/lib/activeio-core-3.0-beta3.jaractivemq-4.0.1/lib/activemq-core-4.0.1.jar

此外,您的代码应该只使用 JMS 接口的 JMS 1.0.x 版本(例如 javax.jms.Session)。请注意,JMS 1.1 使用了许多相同的接口,但为它们添加了许多方法,如果您使用新方法,您的代码将无法在此版本的 WebLogic 中运行。尝试确保您正在针对来自正确 WebLogic 版本的 weblogic.jar 编译您的客户端代码,或者使用专门的 JMS 1.0.x JAR(例如,您可以从 Sun 下载的 JAR)。*不要针对像 activemq-4.0.1/incubator-activemq-4.0.1.jar 这样的 JAR 进行编译,因为该 JAR 包含 JMS 1.1!*

最后,您可以使用正常的 ActiveMQ Classic JNDI 设置(包括连接 URL)连接到 ActiveMQ Classic。不要尝试使用 WebLogic JNDI 连接到 ActiveMQ Classic,也不要在 ActiveMQ Classic 连接 URL 中使用 WebLogic 主机名或监听端口 - 即使 ActiveMQ Classic 代理在 WebLogic 中运行,它也将监听与 WebLogic 使用的端口不同的网络端口。

**待办事项:**添加示例 JMS 1.0.x 代码

包含 JMS 1.1 的 WebLogic Server 版本

**WebLogic 9.2** 及更高版本已知支持 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支持哪个 JMS 版本)

要在这些 WebLogic Server 版本之一中使用 ActiveMQ Classic,您可以使用 ActiveMQ Classic 附带的 J2EE 连接器(称为 ActiveMQ Classic-RA)。这将为 J2EE 应用程序提供完整的 ActiveMQ Classic 支持 - ActiveMQ Classic 可用于发送消息以及将传入消息传递给消息驱动 Bean。您的 J2EE 应用程序可以在 JNDI 中映射连接工厂和目标引用。

我没有使用来自 WebLogic 中 J2EE 1.4 应用程序的 J2EE 连接器的示例。如果有人可以贡献一个,那就太好了!

如果您在应用程序中使用 Spring 或其他非 J2EE 架构,您可能选择跳过 J2EE 连接器,而直接使用下一节中描述的技术连接到 ActiveMQ Classic。

包含 JMS 1.1 的 WebLogic Express 版本

**WebLogic 9.2** 及更高版本已知支持 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支持哪个 JMS 版本)

J2EE 连接器在 WebLogic Express 中不受支持,因此该方法不可用。相反,任何想要连接到 ActiveMQ Classic 的组件都需要手动创建连接(或使用 Spring 消息驱动 POJO 等技术来管理它)。但是,这应该是比较容易的,因为 ActiveMQ Classic 和 WebLogic 支持相同的 JMS 版本。

**待办事项:**WebLogic 的 JMS 1.1 客户端和 Spring 消息驱动 POJO 客户端示例

WebLogic 中的 ActiveMQ Classic 代理

表面上看,为什么您可能希望在 WebLogic 中运行 ActiveMQ Classic 代理而不是独立运行,这并不明显,但需要考虑的因素包括

  • 当 ActiveMQ Classic 在 WebLogic 中运行时,它可以像其他应用程序一样部署、启动、停止和重新部署,使用 WebLogic 控制台或其他工具,同时 JVM 和 WebLogic 仍在运行
  • ActiveMQ Classic 可以连接到 WebLogic JMX 管理系统(以及例如 JRockit)以提供对应用程序服务器、应用程序、ActiveMQ Classic 甚至 JVM 的单一管理接口。
  • ActiveMQ Classic 可以利用 WebLogic 安全域进行身份验证和授权 - 不仅 WebLogic 可用更多的安全域类型,而且它们也更容易通过 WebLogic 控制台进行配置

如果您决定独立运行 ActiveMQ Classic,那就没问题,您可以跳过此部分。否则,请继续阅读。

具体集成技术取决于您使用的是 WebLogic Server 还是 WebLogic Express,以及您的版本是否支持 JMS 1.0.x 或 JMS 1.1。

包含 JMS 1.0.x 的 WebLogic Server/Express 版本

在仅支持 JMS 1.0.x 的 WebLogic Server 或 WebLogic Express 版本中部署 ActiveMQ Classic 代理尚未经过测试。已知这包括 **WebLogic 8.1** 及所有以前版本。它可能会因 ActiveMQ Classic 和 WebLogic 使用的 JMS 版本冲突而遇到问题。

如果您尝试这样做,请报告您的结果

包含 JMS 1.1 的 WebLogic Server 版本

**WebLogic 9.2** 及更高版本已知支持 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支持哪个 JMS 版本)

可以在 WebLogic Server 中以两种方式之一部署 ActiveMQ Classic

  • **使用 ActiveMQ Classic-RA J2EE 连接器** - ActiveMQ Classic 提供了一个 J2EE 连接器,该连接器通常由客户端用来连接到单独的 ActiveMQ Classic 代理。但是,J2EE 连接器接受参数以运行嵌入式代理并提供嵌入式代理的 XML 配置文件的位置。这可能是将 ActiveMQ Classic 代理部署到 WebLogic Server 的最佳方式,因为 ActiveMQ Classic 然后可以访问 WebLogic 线程池和其他资源。
  • **将 ActiveMQ Classic 代理部署为 WebLogic 应用程序** - 这是下面针对 WebLogic Express 描述的技术。它在 WebLogic Server 中同样适用。

J2EE 连接器方法尚未经过专门测试,但应该可以正常工作。它需要一些额外的类来支持下一节中描述的安全性和管理集成,因此需要将这些类添加到 JAR 中,然后将其添加到 J2EE 连接器 RAR 文件中。*如果您尝试这样做,请报告您的结果*

包含 JMS 1.1 的 WebLogic Express 版本

**WebLogic 9.2** 及更高版本已知支持 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支持哪个 JMS 版本)

由于 WebLogic Express 不支持 J2EE 连接器,因此有必要将 ActiveMQ Classic 包装在部署到 WebLogic 的应用程序中。请注意,ActiveMQ Classic 在 XBean 容器中运行,因此 XBean 必须指向适当的配置文件才能启动,然后它将配置并启动所有 ActiveMQ Classic 组件。因此,第一个挑战就是构建一个应用程序,该应用程序在部署时找到正确的配置文件并启动 ActiveMQ Classic 代理。

ActiveMQ Classic 作为 WebLogic 应用程序

最容易配置的 WebLogic 应用程序类型是使用所有必要的 ActiveMQ Classic 库和配置,以及少量其他内容的 Web 应用程序。JAR 放入 WEB-INF/lib/,配置文件通常放入 WEB-INF/。Web 应用程序本身唯一需要的配置是安装一个侦听器,该侦听器将在 Web 应用程序启动和停止时启动和停止 ActiveMQ Classic。还可以使用几个可选类来将 ActiveMQ Classic 与 WebLogic 的安全系统集成。此外,在此示例中,WAR 中包含的一个简单网页将在 ActiveMQ Classic 运行时可用,因此一个简单的 HTTP 请求可以确定 ActiveMQ Classic 模块是否已启动。

管理选项

ActiveMQ Classic 通过 JMX 公开许多管理和监控功能。有三种方法可以公开这些 JMX 对象

  1. 让 ActiveMQ Classic 启动自己的 JMX MBeanServer 和网络连接器(通常在端口 1099 上)
  2. 让 ActiveMQ Classic 使用 JVM 的 MBeanServer(对于 Java 5 及更高版本,无论是 Sun VM 还是 JRockit VM)
  3. 让 ActiveMQ Classic 使用运行时环境(例如 WebLogic)提供的 MBeanServer

每种方法都有其优缺点。需要注意的一些事项

  • 确保同一台机器上的每个 ActiveMQ Classic 实例都使用单独的网络端口来处理 JMX 请求。这在使用 ActiveMQ Classic MBeanServer 时是在配置文件中设置的,在使用 JVM 的 MBeanServer 时是在系统属性(命令行参数)中设置的,它使用标准的 WebLogic 监听端口来进行 WebLogic JMX
  • JRockit 似乎需要运行时许可才能使用嵌入式 MBeanServer,而 Sun JVM 则免费提供它

下面的示例包含一个可选的配置块,它允许 ActiveMQ Classic 连接到 WebLogic 运行时 MBeanServer。这意味着 ActiveMQ Classic MBean 将与 WebLogic MBean(以及 JVM MBean,如果已启用)一起显示。使用这种方法,管理客户端将通过正常的 WebLogic 监听端口(例如 7001)访问 ActiveMQ Classic MBean,而不是使用专用的 JMX 端口,尽管 IIOP 必须启用才能正常工作。但是,请注意,这是可选的,您可以跳过该配置块并使用其他方法之一(JVM 或嵌入式 MBeanServer)来公开 ActiveMQ Classic MBean。

安全选项

ActiveMQ Classic 具有可选的身份验证和授权插件,它们基于 JAAS。幸运的是,WebLogic 提供了一个 JAAS LoginModule,它针对默认的 WebLogic 安全域执行身份验证,并返回用于授权的适当主体。不幸的是,默认情况下,ActiveMQ Classic 无法根据 WebLogic 主体对安全域中的特定用户进行授权访问,这意味着要么没有安全,要么需要登录,但任何具有有效登录的用户都可以完全访问 ActiveMQ Classic。但是,使用下面显示的自定义安全类,ActiveMQ Classic 可以使用 WebLogic 安全域来处理登录,然后您可以配置应该被允许对每个代理或每个目标执行读/写/创建/删除操作的 WebLogic 主体(用户和/或组)。

您可以选择只使用身份验证,在这种情况下,任何具有有效 WebLogic 登录的用户都可以访问 ActiveMQ Classic,并且不需要自定义代码。您也可以使用一些自定义代码为其添加授权,以对特定用户或目标应用特定的安全约束。为了本例的目的,我们只实现了一种授权方法,它允许单个特定 WebLogic 组中的任何成员访问 ActiveMQ Classic 中的所有资源。在本文提供的授权插件和 ActiveMQ Classic 提供的默认插件之间,您应该具备基础来增强此插件,如果需要更丰富的授权功能。

持久性选项

ActiveMQ Classic 默认情况下使用本地日志(文件系统上的文件)和后端数据库的组合。在标准配置中,使用嵌入式 Derby 数据库。这在 WebLogic 中运行良好,但也可以让 ActiveMQ Classic 使用在 WebLogic 中定义的数据库连接池,而不是使用单独的 Derby 数据库。后面显示的配置文件中包含注释掉的关于 WebLogic 数据库连接池的部分 - 如果你想使用它们,只需要设置数据库连接池使用的正确 JNDI 名称。

注意,ActiveMQ Classic 会在第一次连接到数据库时创建所需的表,因此数据库不需要任何特别的准备。

ActiveMQ Classic 集成架构

ActiveMQ Classic 在 WebLogic 中的组合看起来像这样

总结这张图

  • ActiveMQ Classic 作为 Web 应用程序运行,该应用程序在 WebLogic Express 中的 Web 容器中运行
  • ActiveMQ Classic 从 WebLogic 类路径上的目录中读取两个配置文件 - 一个用于配置 ActiveMQ Classic 本身,另一个用于配置其日志输出
  • ActiveMQ Classic 使用 WebLogic Express 中的两个主要资源 - JMX 管理服务器 (MBeanServer) 和 WebLogic 安全域 (以 JAAS 登录模块的形式)。
  • 为了在 Web 应用程序部署时启动 ActiveMQ Classic,web.xml 包含 Spring 的上下文监听器,Spring applicationContext.xml 文件加载 ActiveMQ Classic 代理并将其指向 ActiveMQ Classic 配置文件(如上所述,存储在类路径上的目录中)。
  • 在 ActiveMQ Classic 中
    • ActiveMQ Classic 配置文件中的一个配置块会导致 ActiveMQ Classic 将其所有 JMX MBean 注册到 WebLogic JMX MBeanServer
    • 安全插件会导致所有客户端都对 WebLogic 安全域进行身份验证
    • 安全插件还会从 ActiveMQ Classic 配置文件中读取 WebLogic 组的名称,并要求任何客户端必须是该组的成员(当 WebLogic 处理登录时,它必须为该组的用户创建了一个主体)。
    • ActiveMQ Classic 配置文件还标识了 ActiveMQ Classic 将监听用于 JMS 客户端的网络监听端口。任何客户端都必须在其连接 URL 中包含服务器的主机名和此监听端口。
    • ActiveMQ Classic 日志系统 (Log4J) 以日志配置文件中指定的格式将日志消息输出到日志配置文件中指定的目的地
    • 持久性消息存储在 ActiveMQ Classic 数据目录中的日志中,并定期转储到远程数据库(图中未显示数据库)
  • 注意,ActiveMQ Classic 使用自己的线程;由于 WebLogic Express 不支持 J2EE 连接器,因此 ActiveMQ Classic 无法在没有更广泛的自定义的情况下访问 WebLogic 线程池

构建 ActiveMQ Classic 到 WebLogic 集成 WAR

本节讨论构建将部署到 WebLogic Express 中的 ActiveMQ Classic Web 应用程序所需的代码、库和配置文件。

启动和停止 ActiveMQ Classic

ActiveMQ Classic 需要在 Web 应用程序部署或启动时启动,并在 Web 应用程序停止或取消部署时停止。最简单的方法是使用常用的 Spring 监听器,它们启动 Spring 上下文,该上下文可以将 ActiveMQ Classic 指向 XBean 配置文件,该文件启动 ActiveMQ Classic。有点绕,但实际上效果很好,而且配置很少。

J2EE WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app\_2\_4.xsd" >
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Spring WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="brokerService" class="org.apache.activemq.xbean.BrokerFactoryBean">
        <property name="config" value="classpath:activemq-config.xml"/>
    </bean>
</beans>

同样,web.xml 监听器启动 Spring 并读取 Spring META-INF/applicationContext.xml 文件(ContextLoaderListener 使用的默认位置),applicationContext.xml 指示应从类路径中读取 ActiveMQ Classic 配置文件,名称为 activemq-config.xml。该文件可以放在 WEB-INF/classes 中,也可以放在添加到 WebLogic 类路径的文件系统上的目录中(便于编辑)。

使用这种方法,正常的 WebLogic 部署工具、管理控制台等可用于部署、启动、停止和重新启动 ActiveMQ Classic(打包成 Web 应用程序 WAR)。

必需的库

ActiveMQ Classic 需要许多 JAR 文件,这些 JAR 文件应该包含在 Web 应用程序 WEB-INF/lib 目录中。

此列表是为 ActiveMQ Classic 4.0.1 生成的

  • activemq-core(基本的 ActiveMQ Classic 代码)
  • activemq-jaas(ActiveMQ Classic 安全代码)
  • activeio-core(ActiveMQ Classic 网络层)
  • derby(用于持久性消息的嵌入式 DB)
  • commons-logging(日志抽象库)
  • log4j(实际使用的日志包)
  • backport-util-concurrent(并发实用程序库)
  • spring(用于配置和启动 ActiveMQ Classic)
  • xbean-spring(用于配置 ActiveMQ Classic)

此外,为了构建自定义安全插件,目前在编译时需要 WebLogic server/lib/weblogic.jar

其中,如果 ActiveMQ Classic 配置为不使用数据库进行持久性,或者使用单独的数据库(例如 WebLogic 数据库池)进行持久性,则可以省略 Derby。WebLogic JAR 仅在构建时需要(它在运行时由服务器提供)。如果使用不同的策略来启动和停止 Web 应用程序启动或停止时的 ActiveMQ Classic(一些自定义代码可以替换此依赖项),则可以省略 Spring。其余的可能无法避免,除非 ActiveMQ Classic 在未来的版本中更改了其依赖项。

WebLogic 集成代码

此示例中使用了两个自定义类。我们将在一分钟内展示如何配置 ActiveMQ Classic 以使用这些类。请注意,这些是可选的 - 如果你不想利用 WebLogic 的安全域,可以跳过这些。

第一个类使 ActiveMQ Classic 使用 WebLogic 安全域进行身份验证,并允许你指定单个 WebLogic 组用于授权(只有该组的成员才能访问 ActiveMQ Classic,尽管组成员对 ActiveMQ Classic 拥有完全访问权限)。

ActiveMQToWebLogicSecurity.java

此类是一个 ActiveMQ Classic“插件”,它安装两个过滤器(授权和身份验证),这些过滤器将在每个请求上被调用。这类似于 ActiveMQ Classic 的 JaasAuthenticationPluginAuthorizationPlugin 提供的默认行为。

/**
 * An ActiveMQ Classic security plugin that installs two security filters
 * (authentication and authorization) that use WebLogic security realms to
 * handle the login and provide user and group principals.
 */
public class ActiveMQToWebLogicSecurity implements BrokerPlugin {
    private String authorizedGroup;

    public Broker installPlugin(Broker broker) {
        // Install the first filter for authentication
        Broker first = new ActiveMQWebLogicAuthenticationFilter(broker);
        // Configure and install the second filter for authorization
        AuthorizationEntry entry = new AuthorizationEntry();
        Set acls = new HashSet();
        acls.add(new WLSGroupImpl(authorizedGroup));
        entry.setAdminACLs(acls);
        entry.setReadACLs(acls);
        entry.setWriteACLs(acls);
        DefaultAuthorizationMap map = new DefaultAuthorizationMap();
        map.setDefaultEntry(entry);
        //todo: if finer-grained access is required, add more entries to the authorization map
        Broker second = new AuthorizationBroker(first, map);
        return second;
    }

    public String getAuthorizedGroup() {
        return authorizedGroup;
    }

    /**
     * Called by XBean at configuration time to set the authorized group from a
     * property in the main ActiveMQ Classic configuration file.
     */
    public void setAuthorizedGroup(String authorizedGroup) {
        this.authorizedGroup = authorizedGroup;
    }
}

第二个类是上面类中用于对所有登录进行身份验证的认证过滤器,针对 WebLogic 默认安全域进行身份验证。

ActiveMQWebLogicAuthenticationFilter.java

/**
 * A broker filter that authenticates callers against WebLogic security.
 * This is similar to the ActiveMQ Classic JaasAuthenticationBroker except for two
 * things:
 * <ul>
 *   <li>Instead of reading a JAAS configuration file, it hardcodes the JAAS
 *     configuration to require authentication against WebLogic</li>
 *
 *   <li>The SecurityContext implementation overrides the method used to
 *     compare actual and eligible principals in order to handle the fact
 *     that WebLogic principals (WLSGroupImpl in particular) do not seem
 *     to match according to equals and hashCode even if the principal class
 *     and principal name are the same (perhaps having to do with the
 *     signature data on the WLSAbstractPrincipal).</li>
 * </ul>
 */
public class ActiveMQWebLogicAuthenticationFilter extends BrokerFilter {
    private final static Configuration WEBLOGIC\_JAAS\_CONFIGURATION = new Configuration() {
        public AppConfigurationEntry\[\] getAppConfigurationEntry(String name) {
            return new AppConfigurationEntry\[\]{
                    new AppConfigurationEntry("weblogic.security.auth.login.UsernamePasswordLoginModule",
                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, Collections.EMPTY_MAP)
            };
        }

        public void refresh() {
        }
    };
    private final CopyOnWriteArrayList securityContexts = new CopyOnWriteArrayList();

    public ActiveMQWebLogicAuthenticationFilter(Broker next) {
        super(next);
    }

    static class JaasSecurityContext extends SecurityContext {

        private final Subject subject;

        public JaasSecurityContext(String userName, Subject subject) {
            super(userName);
            this.subject = subject;
        }

        public Set getPrincipals() {
            return subject.getPrincipals();
        }

        /**
         * This is necessary because WebLogic uses extra logic when comparing principals,
         * probably to check whether they are cryptographically signed (which WebLogic
         * supports).  We skip that test because ActiveMQ Classic does not sign the principals
         * it deals with.
         */
        public boolean isInOneOf(Set eligiblePrincipals) {
            for (Iterator it = getPrincipals().iterator(); it.hasNext();) {
                Principal test = (Principal) it.next();
                for (Iterator el = eligiblePrincipals.iterator(); el.hasNext();) {
                    Principal eligible = (Principal) el.next();
                    if(test.getName().equals(eligible.getName()) &&
                            test.getClass().getName().equals(eligible.getClass().getName())) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
        if( context.getSecurityContext()==null ) {
            // Do the login.
            try {
                LoginContext lc = new LoginContext("ActiveMQ", new Subject(),
                        new URLCallbackHandler(info.getUserName(), info.getPassword()),
                        WEBLOGIC\_JAAS\_CONFIGURATION);
                lc.login();
                Subject subject = lc.getSubject();

                SecurityContext s = new JaasSecurityContext(info.getUserName(), subject);
                context.setSecurityContext(s);
                securityContexts.add(s);
            } catch (Exception e) {
                throw (SecurityException)new SecurityException("User name or password is invalid.").initCause(e);
            }
        }
        super.addConnection(context, info);
    }

    public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception {
        super.removeConnection(context, info, error);
        if( securityContexts.remove(context.getSecurityContext()) ) {
            context.setSecurityContext(null);
        }
    }

    /**
     * Previously logged in users may no longer have the same access anymore.  Refresh
     * all the logged into users.
     */
    public void refresh() {
        for (Iterator iter = securityContexts.iterator(); iter.hasNext();) {
            SecurityContext sc = (SecurityContext) iter.next();
            sc.getAuthorizedReadDests().clear();
            sc.getAuthorizedWriteDests().clear();
        }
    }
}
ActiveMQ Classic 配置文件示例

本节显示了三个 ActiveMQ Classic 配置文件示例 - 一个用于单个代理,具有上面列出的安全和管理插件,另一个用于具有上面列出的安全和管理插件的两个代理的网络。如果你想跳过安全和管理插件,可以从主 <broker> 元素中删除这些属性,并删除下面它们对应的 <bean> 定义。

它还显示了一个 Log4J 配置文件,该文件控制 ActiveMQ Classic 日志输出。

单个代理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="MyBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="MyBrokerTCP" uri="tcp://0.0.0.0:61616" />
    </transportConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="ActiveMQUsers" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

代理网络(代理 1/2)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="FirstBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b1-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b1-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="FirstBrokerTCP" uri="tcp://0.0.0.0:60010" />
    </transportConnectors>
    
    <networkConnectors>
        <networkConnector name="Broker1ToBroker2"
                          uri="static://(tcp://127.0.0.1:60011)" failover="true"
                          userName="fixme" password="fixme"/>
    </networkConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="ActiveMQUsers" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

代理网络(代理 2/2)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="SecondBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b2-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b2-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="SecondBrokerTCP" uri="tcp://0.0.0.0:60011" />
    </transportConnectors>
    
    <networkConnectors>
        <networkConnector name="Broker2ToBroker1"
                          uri="static://(tcp://127.0.0.1:60010)" failover="true"
                          userName="fixme" password="fixme" />
    </networkConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="activemq" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Log4J 配置文件 (log4j.properties)

# Can change this to "INFO, out" or "INFO, out, stdout"
# to enable logging to the file defined down below
log4j.rootLogger=INFO, stdout
log4j.logger.org.apache.activemq.spring=WARN
log4j.logger.org.springframework=WARN
log4j.logger.org.apache.xbean.spring=WARN

# Configuration to log to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %-30.30c{1} - %m%n
log4j.appender.stdout.threshold=INFO

# Configuration for a log file (in addition to or instead of stdout)
log4j.appender.out=org.apache.log4j.RollingFileAppender
log4j.appender.out.file=/server/bea/weblogic920/domains/test/activemq.log
log4j.appender.out.maxFileSize=1024KB
log4j.appender.out.maxBackupIndex=5
log4j.appender.out.append=true
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d \[%-15.15t\] %-5p %-30.30c{1} - %m%n

安装步骤

此步骤假设以下内容

  • ActiveMQ Classic 配置文件和 Log4J 配置文件将存储在 WebLogic 域目录的子目录中,以便于编辑。它们可以打包到 WAR 中的 WEB-INF/classes 中,以便于分发。
  • ActiveMQ Classic JMX 管理功能将通过 WebLogic 运行时 JMX MBeanServer 公开。这不是必需的,但它应该允许现有的 WebLogic 管理脚本看到 ActiveMQ Classic MBean。注意:如果使用 Sun JVM JMX 服务器或 JRockit 管理服务器,或者如果使用嵌入式 ActiveMQ Classic JMX 服务器,并且在同一服务器上运行多个 ActiveMQ Classic 实例,则需要额外的配置。
  • ActiveMQ Classic 将安装在单个 WebLogic 实例上,或在代理网络配置中的两个 WebLogic 实例上。
    • 在(代理网络)集群中,两个 ActiveMQ Classic 实例将使用特定的 URL 来定位彼此,而不是尝试运行时发现网络上可能存在的任意代理。
  • ActiveMQ Classic 安全要么被禁用,要么 ActiveMQ Classic 登录将针对 WebLogic 默认安全域进行验证,并且需要登录,并且指定 WebLogic 组的任何成员都可以访问 ActiveMQ Classic。

先决条件

  • 已安装 WebLogic Express 9.2
  • 已创建简单的 WebLogic 域
  • 如果在 Linux 上使用 JRockit VM,则运行 WebLogic 的用户的文件句柄限制可能很重要(使用 ulimit -n 测试)。推荐的值至少应该是预期最大 JMS 客户端数量的两倍。
  • ActiveMQ Classic Web 应用程序 WAR (activemq-4.0.1-web.war)
  • ActiveMQ Classic 配置文件 (activemq-config.xml)
  • Log4J 配置文件 (log4j.properties)

安装步骤

  1. 创建 WebLogic 域目录的子目录来保存 ActiveMQ Classic 配置文件(例如 domain-dir/activemq/config
  2. 创建 WebLogic 域目录的子目录来保存 ActiveMQ Classic 运行时数据 - 持久性消息等(例如 domain-dir/activemq/data
  3. 编辑 activemq-config.xml 以指向在步骤 2 中创建的正确运行时数据目录(查找文件中读取 dataDirectory="..." 的部分)
  4. activemq-config.xml 中,查看 <transportConnector .../> 行中定义的当前 ActiveMQ Classic 服务器的端口,如果使用 ActiveMQ Classic 集群,请查看 <networkConnector .../> 行中定义的集群中其他 ActiveMQ Classic 服务器的主机名和端口。
  5. 如果同时启用了 ActiveMQ Classic 集群和安全,请在 activemq-config.xml 中找到(或添加)<networkConnector .../> 上的 userNamepassword 设置,并将它们更改为有效的值。(当启用安全时,集群中的 ActiveMQ Classic 代理需要有效的登录才能连接到彼此以形成集群。)
  6. 如果启用了安全,请在 activemq-config.xml 中找到 WebLogicSecurity bean 上的 authorizedGroup 设置,并将其设置为应能够访问 ActiveMQ Classic 的 WebLogic 组的名称。请注意,上一步中网络连接器使用的帐户必须是此组的成员。(配置文件中的此条目在上一节中进行了描述。)
  7. (可选) 更新 log4j.properties 文件,将 ActiveMQ Classic 日志保存到文件,而不是只输出到 WebLogic 服务器的标准输出(例如,将第一行更改为 log4j.rootLogger=INFO, out, stdout,并在 log4j.appender.out.file=... 行中更改目标文件)。
  8. activemq-config.xmllog4j.properties 文件保存到步骤 1 中创建的 ActiveMQ Classic 配置目录。
  9. 编辑域目录中的 startWebLogic.sh 文件,并在顶部添加以下行(紧接在 DOMAIN_HOME=... 行之后),调整该行以使用步骤 1 中创建的目录。
    export EXT_POST_CLASSPATH=${DOMAIN_HOME}/activemq/config
    
  10. 启动 WebLogic。
  11. 部署 activemq-4.0.1-web.war 文件,方法是将其复制到 domain-dir/autodeploy 目录或使用 WebLogic 控制台中的部署工具。
  12. 验证 WebLogic 服务器标准输出(或步骤 5 中配置的 ActiveMQ Classic 日志文件)是否显示 ActiveMQ Classic 已启动,输出类似于以下内容。
    INFO  BrokerService                  - ActiveMQ 4.0.1 JMS Message Broker (localhost) is starting
    INFO  BrokerService                  - For help or more information please see:
                                           http://incubator.apache.org/activemq/
    INFO  JDBCPersistenceAdapter         - Database driver recognized: \[apache\_derby\_embedded\_jdbc\_driver\]
    INFO  JournalPersistenceAdapter      - Journal Recovery Started from: Active Journal: using 5 x 20.0 Megs at:
                                           /data/server/bea/weblogic920/domains/test/activemq-data/journal
    INFO  JournalPersistenceAdapter      - Journal Recovered: 0 message(s) in transactions recovered.
    INFO  TransportServerThreadSupport   - Listening for connections at: tcp://0.0.0.0:60010
    INFO  TransportConnector             - Connector default Started
    INFO  BrokerService                  - ActiveMQ JMS Message Broker
                                           (localhost, ID:remus-28763-1156532531109-1:0) started
    
  13. 通过运行 Java 5 附带的 jconsole 工具测试管理连接,使用高级连接,输入 URL service:jmx:rmi:///jndi/iiop://127.0.0.1:7001/weblogic.management.mbeanservers.runtime(调整 localhost:7001 以匹配 WebLogic 服务器主机名和端口),以及 WebLogic 管理员用户名和密码。连接后,在 MBeans 选项卡上,应该在 org/activemq 下有条目。
  14. 如果需要,通过运行 ActiveMQ Classic 4.0.1 发行版中的示例生产者和消费者来测试安全性。请注意,连接 URL 位于 examples/build.xml 中,而连接用户名和密码需要添加到 examples/src/ConsumerTool.javaexamples/src/ProducerTool.java 中,才能成功连接到安全实例。
  15. 如果要使用 ActiveMQ Classic 集群,请对集群中的其他 WebLogic/ActiveMQ Classic 实例重复此过程。这将设置两个 ActiveMQ Classic 服务器相互连接。通过查看两个代理都运行后出现的以下类似输出,确认这一点。
    INFO  DemandForwardingBridge         - Network connection between vm://FirstBroker#0 and
                                           tcp://127.0.0.1:63222(SecondBroker) has been established.
    

Apache, ActiveMQ, Apache ActiveMQ,Apache 羽毛标志和 Apache ActiveMQ 项目标志是 Apache 软件基金会的商标。版权所有 © 2024,Apache 软件基金会。根据 Apache 许可证 2.0 授权。