2014-06-16 38 views
8

Obserwuję niezwykłe zachowanie i chciałbym zrozumieć, co się dzieje.Metoda EJB wymaga więcej czasu, aby powrócić po każdym wywołaniu

Wyobraź sobie prostą konfigurację.

Najpierw Mam bezstanowej fasoli, które po prostu zwraca coś:

@Stateless 
public class SimpleService{ 
    private Map<String, String> map; 

    @PostConstruct 
    public init(){ 
     map = new HashMap<>(); 
    } 

    public Map<String,String> getMap(){ 
     return map; 
    } 
} 

Następnie mam innego bezstanowej fasoli, który wykonuje pewne przetwarzanie

@Stateless 
public class ProcessService{ 

    private static final Logger log = LoggerFactory.getLogger(ProcessService.class); 
    private static final int MAX = 2000; 

    @Inject 
    private SimpleService simpleService; 

    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public void process(){ 
     final long start = System.currentTimeMillis(); 
     for(int i=0; i<MAX; i++){ 
      simpleService.getMap(); 
     } 
     final long end = System.currentTimeMillis(); 
     log.info(MessageFormat.format("Process took {0} ms", end - start)); 
    } 
} 

Następnie Mam proste CDI fasoli zadzwonić do metoda procesowa.

Wynik:

Kiedy wzywam process metoda kilka razy z rzędu, czas proces wciąż rośnie:

Process took 900 ms 
Process took 1,100 ms 
Process took 1,200 ms 
Process took 1,400 ms 

I ciągle dzieje się za każdym razem, gdy wywoływana jest metoda.

Jak to wyjaśnić?

Używam Java JDK 1.7.0_25 i JBOSS EAP 6.1.

EDIT

Nawiasem mówiąc, jedynym sposobem na „reset” czas przetwarzania dla metoda jest ponowne uruchomienie serwera.

+1

Czy przetestowałeś to z więcej niż 4 iteracjami z rzędu i czy czasy zawsze rosły lub są o tym samym poziomie? po pewnym punkcie? – Thomas

+0

Tak, zrobiłem więcej niż 4, to po prostu idzie dalej. W tym przykładzie wziąłem go do 5s dla tej samej metody (około 25 wywołań). Właściwie to może być interesujące zauważyć, że często trochę maleje, a następnie powraca: 350ms, 340ms, 460ms, 450ms, 700ms, 680ms, 900ms itd. W końcu to zawsze kończy się zwiększeniem – phoenix7360

+0

Nie mogę Podejmij ten przykład bardzo poważnie, gdy już łamiesz wszystkie reguły, mając stan bezstanowy. Jest to jednak interesujący problem, ponieważ można oczekiwać, że czas upłynie pod pewnymi optymalizacjami środowiska wykonawczego. Niestety, nie da się zobaczyć, gdzie przebiega czas przetwarzania kodu, który prawie nic nie robi. W tym momencie byłoby interesujące złożyć to jako błąd dla JBoss i zobaczyć, co się z nim stanie. – Gimby

Odpowiedz

4

Zrobiłem badania z JBoss Application Server 8.1.0.Final i uzyskać następujące:

Process took 900 ms 
Process took 600 ms 
Process took 400 ms 
Process took 300 ms 
Process took 130ms 
Process took 100ms 

A potem stabilizuje około 90 ms.

Sądzę, że możemy bezpiecznie założyć, że pierwotny problem był błędem w JBoss AS 7, który został naprawiony w WildFly 8.1. Więcej niż poprawiono wprowadzili nawet optymalizację!

EDYCJA!

Przepraszam wszystkich, zrobiłem złą diagnostykę. Ten błąd nie ma nic wspólnego z wersją JBoss, ale należał do JRebel.

Po pobraniu Wildfly, nie uruchomiłem go w trybie debugowania z załączonym agentem JRebel (co robiłem ciągle z EAP 6.1). Jeśli uruchomię JBoss EAP 6.1 bez JRebel, problem nie nastąpi.

Tak się przyzwyczaiłem do JRebela, że ​​zapomniałem, że go włączyłem!

Podniosę problem z zespołem JRebel.

EDIT 2

zespół JRebel zbadane i byli w stanie odtworzyć błędu. Zostało to naprawione w nocnej kompilacji i zostanie naprawione w następnej wersji (z powodu sierpnia/września 2014 r.).

+0

Jest to dość niespodzianka - czy należy zgłosić to zespołowi AS 7? – bjedrzejewski

+0

Tak, zrobiłem to już – phoenix7360

+0

To jest całkiem interesujące znalezisko! Czy masz link do raportu o błędzie, więc mogę śledzić jego postęp? – Gimby

0

Możesz spróbować tego samego testu, ale utwórz interfejs SimpleService, a obecna SimpleService będzie podobna do SimpleServiceImpl, która zaimplementuje SimpleService.
Założę się, że cdi robi trochę magii, aby owinąć EJB. Hmm .. lub inna rzecz mogłaby być spróbuje użyć zastrzyk @EJB zamiast @Inject