Ответы пользователя по тегу Паттерны проектирования
  • Как работает блокировка у Singleton на кластере?

    @bobzer
    Java EE Developer
    Как решается проблема, когда нужно иметь Singleton на нескольких серверах?

    1. Блокировка записи в БД. Если бизнес логика вносит какие-то изменения в БД, то перед этим осуществляйте чтение записи с блокировкой, SELECT ... FOR UPDATE (для JPA LockMode/LockModeType и прочее, в зависимости от реализации и версии). При этом, получаем актуальное состояние записи одновременно запрещая её изменять другим потокам (и другим узлам кластера) до тех пор, пока не завершится транзакция обработки записи. Сразу после чтения с блокировкой проверяем, подлежит ли она обработке или нет, на случай, если пока получали блокировку другой поток уже обработал запись. Обычно, сама запись содержит поле, сообщающее о том, следует ли её обрабатывать, например - некий статус. Если статус говорит о том, что запись уже обработана, то обработку не выполняем, завершаем транзакцию, переходим к следующей записи. Если не обработана - соответственно обрабатываем. Пока идёт обработка текущим потоком, другие потоки (узлы) останавливаются на моменте чтения с блокировкой, это поведение обеспечивает СУБД. После завершения обработки, смены статуса записи и подтверждения транзакции, запись высвобождается, и если другой поток пытался её обработать, то СУБД разрешает ему считать запись с блокировкой. Поток проверяет статус, "видит" что она уже обработана и не обрабатывает её. Плюсы: универсальность, независимость от контейнера, практически "непробиваемый". Минус: вероятно возникновение излишней нагрузки, в самом неприятном варианте - всю работу делает один узел, остальные потребляя те же мощности не делают ничего полезного. Если записей менее 100 тысяч в сутки, а узлов менее 5-10, то скорее всего, это не будет большой проблемой.
    2. Для Wildfly начиная с версии 10 есть альтернативный вариант - Singleton deployments. Этот сервис существовал в JBoss 5/6, но был "выпилен" в JBoss 7 (6 EAP) в угоду соответствия стандартам Java EE. Раньше работало так: вы разворачиваете свои кластерные синглтоны в отдельное приложение, и "ложите" в отдельную папку развертывания. Отличие Wildfy в том, что вместо отдельной папки, требуется добавить в приложение специфический дескриптор развёртывания. JBoss/Wildfly гарантирует, что все такие приложения будут запускаться только в одном экземпляре на весь кластер. Плюс: нет лишней нагрузки. Минус: надёжность под сомнением, например, "сломался" протокол UDP, все узлы потеряли друг друга и решили стать главными и развернули ваш синглтон. Вообще, во всём что касается атомарности, лучше СУБД (ИМХО) ещё ничего не придумано.
    3. Реализуете вариант 1 и разворачиваете его как вариант 2. При таком раскладе избавляетесь от минусов обоих подходов, получая все их плюсы.


    PS Касательно варианта 1. Если работа синглтонов не связана с обработкой записей БД, их всё равно можно синхронизировать таким же образом. Создаёте в любой таблице (например, в таблице каких-нибудь системных настроек) запись и синхронизируете синглтоны на ней.
    Ответ написан
    Комментировать
  • Взаимодействие между двумя EJB-модулями внутри одного приложения?

    @bobzer
    Java EE Developer
    Вы не показали, как создается SomeBean. Я это к тому, что контейнер делает инъекцию в бины, которые сам создает. Если вы SomeBean создали через new, то никаких инъекций в него не будет.

    Также можно покопать в сторону загрузки классов, которая в свежем JBoss-е существенно переработана, в сравнении с предыдущими версиями. Попробуйте, например в jboss-deployment-structure.xml указать <ear-subdeployments-isolated>false</ear-subdeployments-isolated>. В конце-концов, объедините core.jar и app.jar в один jar (тупо средствами WinRar-а, если долго переделывать скрипты сборки) и посмотрите, будет ли инъекция. Если будет — то 99% что надо ковырять загрузку классов. Если нет, то это скорее всего ни при чем, и надо думать дальше.
    Ответ написан
    Комментировать