JBoss JDBC MBean предотвращает запуск, если сервер не найден

Во время запуска JBoss у меня есть диспетчер сохраняемости, который зависит от соединения JDBC (DefaultDS). Соединение JDBC запускается нормально независимо от того, действительно ли оно может подключиться к базе данных, поэтому при запуске диспетчера сохранения состояния он думает, что у него есть соединение. Затем он взрывается, потому что не может подключиться к базе данных и никогда не запускается. Это предотвращает запуск моего DestinationManager и вызывает всевозможные головные боли.

Есть ли способ сделать так, чтобы MBeans, зависящие от соединения JDBC, не запускались, если соединение JDBC не может фактически подключиться к базе данных? В качестве альтернативы, есть ли способ сделать соединение JDBC зависимым от MBean, который активен только тогда, когда база данных может быть подключена?

tl; dr; Все, что мне нужно, это чтобы мои MBeans / DestinationManager дождались, пока база данных (DefaultDS) не станет доступной перед загрузкой.

Прокомментируйте, если вам нужна дополнительная информация об окружении.

  • JBoss версии 4.2.3

  • База данных: MsSql


person Bob Fincheimer    schedule 20.07.2011    source источник


Ответы (2)


Если я правильно понимаю проблему, у вас проблема, потому что даже если источник данных DefaultDS сообщает, что он запущен, поскольку он не получил никаких подключений, вы не обязательно знаете, что могут быть установлены соединения.

К сожалению, даже при включенной опции prefill служба источника данных будет запускаться нормально, даже если она не может связь.

Лучше всего реализовать 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 не запускается, и, надеюсь, это будет лучше, чем головная боль, которую вы испытываете сейчас.

person Nicholas    schedule 20.07.2011
comment
это то, что я в конечном итоге сделал, но есть ли способ заставить bean ждать / останавливаться, пока он не сможет установить соединение. Прямо сейчас он крутится, проверяя наличие соединения, пока не получит его. Но это не позволяет серверу запуститься. - person Bob Fincheimer; 21.07.2011
comment
Конечно. В методе startService ConnChecker выполните цикл проверки соединения и просто спите x секунд каждый раз, когда вам не удается установить соединение в течение всего y раз, а затем генерируйте исключение. - person Nicholas; 21.07.2011
comment
Итак, нет никакого способа, чтобы куча bean'ов просто ждала и все же позволяла Jboss загружаться полностью? - person Bob Fincheimer; 22.07.2011

Значит, нет никакого способа, чтобы куча бинов просто «ждала» и при этом позволяла Jboss загружаться полностью?

Не стандартным способом. Цикл загрузки JBoss либо длится до завершения, либо сообщает об ошибке зависимости. Процесс является последовательным и однопоточным (до JBoss 7).

Что вы могли бы сделать (и я лишь вкратце это проверил):

  • Повторно реализуйте ConnChecker, чтобы запустить проверку соединения в отдельном потоке. Он будет считаться запущенным, как только этот поток будет запущен.
  • Вытащите все файлы конфигурации XML для служб, которые вы хотите использовать, ConnChecker (я предполагаю, что это будут все XML развертывания JMS) в другой каталог за пределами 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>
person Nicholas    schedule 22.07.2011