Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Concurrency, singletons и синхронизация в EJB 3.0


Автор: chief39 23.8.2012, 18:59
Ситуация такая:

Надо уметь считать всякие разные вызовы - вебсервисы, еджиби вызовы. Их много разных. Все в одном большом еаре(сейчас)
Все это прикручено аспектами, вопросов не возникает.
Вопрос в том чтоб быстро считать, аккумулировать и по шедулеру сливать статистику в базу(к примеру).

Счетчик будет выглядеть как ConcurrencyHashMap c AtomicInteger и обновляться по CAS'у

Возник вопрос где этот счетчик единообразно хранить. 

- Синглетон, конечно, хорош. 
И даже будет до определенного момента работать. Но как только класслоадеры расползутся - швах.
Шедулер стянет инфу счетчика из своего класслоадера и все. Остальные потеряются. 
Идей как пересчитать все класслоадеры, все счетчики в них и посчитывать данные - нету.
Вернее, выглядят они абсолютно безумными с т.з. ЕЕ (имхо)

- Есть отличная, шикарная вещь в 3.1 http://docs.oracle.com/javaee/6/tutorial/doc/gipvi.html
А именно bean management concurrency 
Но джибосс ее поддерживает начиная с 7-го :(
Мы мигрируем, но только на 6-й максимум :(

- Есть сугубо джибоссовская аннотация http://docs.jboss.org/ejb3/docs/tutorial/1.0.7/html/Service_POJOs.html для синглетона (интуитивно понятное название, не правда ли? smile )
В доке ничего о конкарренси не сказано. Инет пестрит индусскими выводами "раз он синглетон - значит конкарренси ручками, ручками"

Заимплементил с ней пример.
Сотня клиентов, каждый валит по тысяче вызовов, порядочный классец должен был бы сломаться после двух параллельных counter++;
И побежать к плюс бесконечности.
Хрена с два. Строгие нолики на выходе.
Эта тварюка все-таки thread safe.

Код

@Service
@Local(CounterServiceLocal.class)
@Stateless(name = "CounterService")
public class CounterServiceBean implements CounterServiceLocal{

    private int counter = 0;

    public void count(String invoker) {
        System.out.println("+1 " + invoker + " count=" + counter);
        
        counter++;
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(counter == 1 )counter--;
        System.out.println("-1 " + invoker + " count=" + counter);
    }

    public Integer getCount() {
        return counter;
    }



Итого :(
@Service мне вроде подходит. Но это будет преступлением практически все залочить на один классец с такой прямолинейной синхронизацией на одном мониторе.
Шаг влево-вправо - и вместо подсчета скорости мы получим обвал скорости и затык.

Рассматриваю варианты:

http://docs.jboss.org/ejb3/docs/reference/build/reference/en/html/jboss_extensions.html 
(поиском Test asynchTest = org.jboss.ejb3.asynchronous.Asynch.getAsynchronousProxy(test); )

Сунул асинхронный count - и забыл про него.


И второй вариант, стремный, но красивый:
Заюзать @Service и полагаться на то, что это никак не аукнется в ближайшее время (систему все равно никто еще не оптимизировал пока - страх и ужас начиная с отсутствия индексов).
Со временем, с выходом JBoss SOA 6  с JBoss AS 7 внутри - поднять вопрос о срочной миграции на него и засунуть @Singleton вместо @Service со своей синхронизацией.


Асинхронность вроде решает(не знаю что там с накладными расходами), но некрасиво - жуть.
@Service - тупо и в лоб. Чисто, красиво, по джибоссовским понятиям. Но синхронизировать сотни высоконагруженных(в будущем) методов и сервисов на единственном мониторе религия не позволяет.


ЗЫ: Самое паршивое что с еджиби работал года так 4 назад, ничего не помню, да и монструозность с очевидностью, особенно джибоссовская, вызывает приступы немотивированной агрессии  smile 



Может я уткнулся в мысленный тупик? Посоветуйте незамутненным разумом что-то, а? smile




Автор: Stolzen 23.8.2012, 23:19
Если совсем не получается, то может следует использовать UUID?

Автор: chief39 23.8.2012, 23:37
Цитата(Stolzen @  23.8.2012,  23:19 Найти цитируемый пост)
Если совсем не получается, то может следует использовать UUID? 

Эммм.. если бы я сказал что понял, я бы соврал smile

Как, что и куда прикручивать? smile


ЗЫ: Напутал с версиями, вроде бы будет 5 жбосс. Но гарантированно Ежибяки 3.0, не больше :(

Автор: Stolzen 24.8.2012, 10:03
Цитата(chief39 @  24.8.2012,  00:37 Найти цитируемый пост)
Как, что и куда прикручивать? smile

Я имею ввиду, в данном случае, когда использование централизованного генератора уникальных идентификаторов неоправданно, можно использовать распределенный генератор. http://ru.wikipedia.org/wiki/UUID - один из алгоритмов, позволяющих сделать это. 
В джаве это можно сделать так
Код

UUID.randomUUID().toString()

Автор: chief39 26.8.2012, 00:23
Так мне считать надо, а не случайные числа генерить smile


Вопрос решился бутылкой пива и мыслью "гляну-ка я еще разок":

Код

@Service
@Local(CounterServiceLocal.class)
@Stateless(name = "CounterService")

должно выглядеть вот так
Код

@Service(name = "CounterService")
@Local(CounterServiceLocal.class)


Я умудрился оставить стейтлесс и списать это на контейнерную конкарренси.

Теперь все отлично, кантер моментально сходит с ума при сотне клиентов smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)