1

在 JBoss 启动期间,我有一个依赖于 JDBC 连接(DefaultDS)的持久性管理器。JDBC 连接启动良好,无论它是否可以实际连接到数据库,因此当 Persistence Manager 启动时,它认为它有一个连接。然后它爆炸了,因为它无法连接到数据库并且永​​远不会启动。这会阻止我的 DestinationManager 启动并导致各种头痛。

有没有办法让依赖 JDBC 连接的 MBean 不启动,除非 JDBC 连接可以真正连接到数据库?作为替代方案,是否有办法使 JDBC 连接依赖于仅在数据库可以连接时才处于活动状态的 MBean?

tl;博士; 我所需要的只是让我的 MBeans/DestinationManager 等到数据库 (DefaultDS) 可用后再启动。

如果您需要有关环境的更多信息,请发表评论。

  • JBoss 版本 4.2.3

  • 数据库:MsSql

4

2 回答 2

2

如果我正确理解了这个问题,那么您就会遇到问题,因为即使DefaultDS数据源报告它已经启动,但由于它没有获得任何连接,您不一定知道可以建立连接

不幸的是,即使启用了预填充选项,即使无法建立连接,数据源服务仍将正常启动。

最好的办法是实现一个ServiceMBean,它在报告启动之前检查来自数据源的实际连接。对于此示例,我们将其命名为org.bob.ConnChecker并将使用 ObjectName org.bob:service=ConnChecker进行部署。

您的部署描述符应如下所示:

  <mbean code="org.bob.ConnChecker" name="jboss.mq:service=DestinationManager">
    <depends optional-attribute-name="DataSource">jboss.jca:name=DefaultDS,service=ManagedConnectionPool</depends>
  </mbean>

因此,在数据源启动之前,您的服务不会启动。除非它可以建立连接,否则您的服务将不会启动。现在您只需添加org.bob:service=ConnChecker作为 DestinationManager 的依赖项:

jboss.mq:service=MessageCache jboss.mq:service=PersistenceManager jboss.mq:service=StateManager jboss.mq:service=ThreadPool jboss:service=命名org.bob:service=ConnChecker

ConnChecker的代码如下所示:

....
import org.jboss.system.ServiceMBeanSupport;
....
public class ConnChecker extends ServiceMBeanSupport implements ConnCheckerMBean {
    /** The ObjectName of the data source */
    protected ObjectName dataSourceObjectName = null;
    /** The Datasource reference */
    protected DataSource dataSource = null;
    /**
     * Called by JBoss when the dataSource has started
     * @throws Exception This will happen if the dataSource cannot provide a connection
     * @see org.jboss.system.ServiceMBeanSupport#startService()
     */
    public void startService() throws Exception {
        Connection conn = null;
        try {
            // Get the JNDI name from the DataSource Pool MBean
            String jndiName = (String)server.getAttribute(dataSourceObjectName, "PoolJndiName");
            // Get a ref to the DataSource from JNDI
            lookupDataSource(jndiName);
            // Try getting a connection
            conn = dataSource.getConnection();
            // If we get here, we successfully got a connection and this service will report being Started
        } finally {
            if(conn!=null) try { conn.close(); } catch (Exception e) {}
        }
    }
    /**
     * Configures the service's DataSource ObjectName
     * @param dataSourceObjectName The ObjectName of the connection pool
     */
    public void setDataSource(ObjectName dataSourceObjectName) {
        this.dataSourceObjectName = dataSourceObjectName;
    }
    /**
     * Acquires a reference to the data source from JNDI
     * @param jndiName The JNDI binding name of the data source
     * @throws NamingException
     */
    protected void lookupDataSource(String jndiName) throws NamingException {
        dataSource = (DataSource)new InitialContext().lookup(jndiName);
    }
}

ConnCheckerMBean的代码如下所示:

....
import org.jboss.system.ServiceMBeanSupport;
....
public interface ConnCheckerMBean extends ServiceMBean {
    public void setDataSource(ObjectName dataSourceObjectName);
}

因此,如果无法与数据库建立连接,您仍然会遇到错误,但 DestinationManager 不会启动,希望这会比您现在遇到的头痛问题要好。

于 2011-07-20T19:40:54.297 回答
2

所以有没有办法让一堆豆子只是“等待”并且仍然允许Jboss一路启动?

不是以任何标准方式。JBoss 引导周期要么一直运行到完成,要么报告依赖关系失败。该过程是顺序的和单线程的(直到 JBoss 7)。

你能做的(我只是简单地测试了一下)是:

  • 重新实现ConnChecker以在单独的线程中运行其连接测试。一旦产生该线程,它将被视为已启动。
  • 将您想要依赖ConnChecker的服务的所有 XML 配置文件(我猜这将是所有 JMS 部署 XML)文件拉出到deploy之外的另一个目录中,例如 /jboss/server/bob/late-deploy
  • 由于后期服务文件现在不在URLDeploymentScanner的路径列表中,因此它们不会作为默认部署过程的一部分进行部署。

部署后期服务文件的技巧是,您的新ConnChecker会愉快地旋转,等待获得连接(并且可能会超时并停在那里),但是当它成功获得连接时,它将执行看起来像这样:

import javax.management.*;
.....
// The JBoss URL Deployment Scanner MBean ObjectName
ObjectName on = new ObjectName("jboss.deployment:flavor=URL,type=DeploymentScanner");
// server is the JBossMBean server. ServiceMBeans automatically have this reference.
server.invoke(on, "addURL", new Object[]{new URL("file:/jboss/server/bob/late-deploy")}, new String[]{String.class.getName});

所以它的作用是告诉部署扫描器“也开始查看这个目录”,几秒钟后,你的后期服务将部署,希望没有错误。此外,由于您在运行时添加了后期服务(因此是非持久性的),当服务器重新启动时,部署扫描程序将恢复为其原始配置,等待ConnChecker向其添加新 URL。

只需确保部署程序将ScanEnabled设置为 true 并且ScanPeriod足够低,以便在建立 JDBC 连接后获得部署后期服务所需的响应时间。该 MBean 配置位于

<jboss-home>/server/<server-name>/conf/jboss-service.xml

寻找这个:

   <mbean code="org.jboss.deployment.scanner.URLDeploymentScanner"
      name="jboss.deployment:type=DeploymentScanner,flavor=URL">
....
      <!-- Frequency in milliseconds to rescan the URLs for changes -->
      <attribute name="ScanPeriod">5000</attribute>
      <!-- A flag to disable the scans -->
      <attribute name="ScanEnabled">true</attribute>
....
   </mbean>
于 2011-07-22T14:05:23.910 回答