Archive for Marzec, 2010

Czym jest JBoss Microcontainer?

JBoss Microcontainer jest to nowe jądro serwera aplikacyjnego JBoss AS 5. Powstało w wyniku prac nad poprzednim JXM Microkernel zmierzających do dodanie do niego wsparcia dla obiektów POJO. Nowe wydania jądra serwera aplikacyjnego może także być używane samodzielnie (jak zresztą większość pozostałych produktów JBossa). Oto jego najważniejsze cechy:

  • wsparcie dla wszystkich cech JMX Microcontainer
  • obsługa bezpośredniej instalacji komponentów POJO
  • obsługa wstrzykiwania zależności
  • poprawy w zarządzani cyklem życia
  • dodanie dodatkowych możliwości kontroli nad zależnościami
  • integracja z AOP
  • wprowadzenie Virtual File System (VFS)
  • ładowanie klas przy użyciu OSGI

Podstawowe moduły jądra

Moduły, jakie wchodzą w skład jądra JBossa oraz zależności między nimi:

Moduły JBoss Microcontainer

Moduły JBoss Microcontainer

  • Bootstrap – mechanizm pozwalający na aktywację jądra (jego załadowanie)
  • Controller – odpowiada za upewnienie się, że obiekty POJO zostaną załadowane, skonfigurowane oraz uruchomione w zależności od wybranego profilu, rozwiązywanie zależności i konfigurację oraz cykl życia rożnych systemów i usług
  • Registry – przechowywanie informacji o zainstalowanych obiektach POJO
  • Configurator – inicjalizuje i konfiguruje obiekty POJO
  • Deployer – proces instalacji obiektów
  • Bus
  • Repository – przechowywanie metadanych o zainstalowanych oraz dostępnych (lecz nie zainstalowanych) obiektach POJO
  • Profile – pozwala na zdefiniowanie które systemy, podsystemy, obiekty POJO zostają zainstalowane, które usługi wystartują automatycznie a które będzie można uruchomić ręcznie

Proces startu serwera

Sam proces startu serwera jest obsługiwany przez oddzielaną bibliotekę, pochodząca z projektu JBoss Bootstrap. Start serwera typowo wygląda tak:

  • utworzenie serwera
  • wskazanie serwerowi, gdzie znajduje się konfiguracja, w przypadku JBossa jest to plik bootstrap.xml
  • uruchomienie serwera
  • zamrożenie konfiguracji, uniemożliwienie jej zmian w czasie działania serwera
  • serwer zostaje uruchomiony, uruchamia po kolei swoje usługi, zdarzenia
  • serwer przechodzi w stan „STARTED”
  • można działać
  • zamykanie serwera, uruchamianie zdarzeń związanych ze zmianą stanu
  • ewentualny restart serwera

Plik XML zawierający konfigurację procesu startu zawiera odnośniki do plików, które odpowiadają za konfigurcację poszczególnych usług serwera. W przypadku JBossa 5.1 wygląda on następująco (znajduje się on w pliku $JBOSS_HOME/server/default/conf/bootstrap.xml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< ?xml version="1.0" encoding="UTF-8"?>
<!--
  The list of URLs for mc beans to load during bootstrap.
  $Id: bootstrap.xml 88109 2009-05-01 20:10:48Z bstansberry@jboss.com $
-->
<bootstrap xmlns="urn:jboss:bootstrap:1.0">

   <url>bootstrap/logging.xml</url>
   <url>bootstrap/vfs.xml</url>
   <url>bootstrap/classloader.xml</url>
   <url>bootstrap/aop.xml</url>
   <url>bootstrap/jmx.xml</url>
   <url>bootstrap/deployers.xml</url>
   <url>bootstrap/profile.xml</url>

</bootstrap>

Poszczególne pliki odpowiadają za konfigurację i inicjalizację odpowiedniego zestawu usług:

  • logging.xml
  • vfs.xml – inicjalizacja Virtual File System
  • classloader.xml – główny system ładowania klas oraz konfiguracja ścieżki dostępu do klas
  • aop.xml – inicjalizacja ziarna JBoss AOP AspectManager, wczytanie potrzebnych bibliotek
  • jmx.xml – inicjalizacja JMXKernel
  • deployers.xml – inicjalizacja szeregu ziaren odpowiedzialnych za aplikację rożnych usług lub aplikacji
  • profile.xml

Źródła

Tags: , , ,

Jak wyczyścić pamieć podręczną DNS w Linuksie

Problem jest prosty: ulega zmianie adres serwera a nasz komputer ciągle łączy się ze starym adresem. Jest to spowodowane tym, że odpowiedzi od serwera DNS są przechowywane w pamięci podręcznej (żeby nie zasypywać biednego serwera DNS ciągle pytaniami). Ponieważ każda odpowiedź z serwera DNS ma pewien czas życia, możemy poczekać aż on upłynie i ponownie zostanie wysłane pytanie, lub też spróbować coś z tym zrobić.

W zależności od konfiguracji, może zadziałać jeden ze sposobów:

  • Restart interfejsów sieciowych – jeżeli jest możliwe, może się okazać najprostszą metodą, ale nie zawsze skuteczną.
  • Używamy demona dnsmasq – demon do przechowywania w pamięci podręcznej adresów DNS. Aby wyczyścić pamięć podręcznę, należy wysłać do niego sygnał SIGHUP
    # kill -SIGHUP $(pgrep dnsmasq)
  • Używamy demona bin – można użyć aplikacji służącej do zarządzaniem tym serwerem rndc
    # rndc flush
  • Używamy demona nscd:
    # /etc/init.d/nscd restart

Tags: , , , , ,

Logowanie przychodzących połączeń HTTP w serwerze JBoss AS i Apache Tomcat

Standardowo (przynajmniej w przypadku JBossa) nie są śledzone przychodzące połączenia HTTP. Może to wprowadzać pewną konsternację :), na szczęście łatwo to zmienić.

Odpowiednie modyfikacje należy wprowadzić w pliku server.xml, który w przypadku JBossa (5.0) znajduje się w katalogu deploy/jbossweb.sar odpowiedniej konfiguracji, z którą serwer jest uruchamiany.

Logowanie odbywa się przez klasę AccessLogValve uruchomianą jako valve (hmm, kranik z angielska, ale nie mam pojęcia jak to będzie po polsku). Należy więc odszukać definicję z tą klasą i ją po prostu odkomentować. Wygląda ona następująco:

80
81
82
83
<Valve className="org.apache.catalina.valves.AccessLogValve"
    prefix="localhost_access_log." suffix=".log"
    pattern="common" directory="${jboss.server.log.dir}"
    resolveHosts="false" />

Konstrukcję tę można umieścić w dowolnym kontenerze (Context, Host, Engine) i będą wtedy zapisywane wszystkie połączenia przechodzące przez dany komponent.

Dopuszczalne parametry konfiguracyjne:

  • className
    Nazwa klasy, która ma odpowiadać za obsługę logowania. Do wyboru są dwie wartości:

    • org.apache.catalina.valves.AccessLogValve – bardziej ogólna, umożliwia zdefiniowanie zakresu logowanych informacji
    • org.apache.catalina.valves.FastCommonAccessLogValve – klasa przeznaczona do wykorzystania na systemach produkcyjnych, umożliwia jedynie na logowanie informacji w formacie common lub combined
  • prefix
    Ciąg znaków dodawany na początku nazwy pliku z logiem. Domyślną wartością jest access_log.
  • suffix
    Ciąg znaków dodawany na końcu nazwy pliku z logami.
  • pattern
    Ciąg znaków zawierający informacje o tym, co powinno zostać zapisane w pliku z logami. Może to być definicja używający specjalnych znaczników lub też słowa common lub combined oznaczające jeden ze standardów logowanych informacji. Dokładną specyfikację można znaleźć w dokumentacji Tomcata.
  • directory
    Ścieżka dostępu do katalogu w którym powinny być zapisywane pliki z logami.
  • resolveHosts
    Jeżeli zostanie ustawiona na true to adresy IP zostaną zamienione na nazwy domenowe (będzie to negatywnie wpływało na wydajność, ponieważ będą potrzebne dodatkowe zapytania do serwera DNS). Jeżeli parametr przyjmie wartość false, zostaną użyte adresy IP.
  • rotatable
    Parametr określa, czy plik z logami ma być rotowany. Domyślnie przyjmuje wartość true. Jeżeli zostanie ustawiony na false, plik z logiem nigdy nie będzie rotowany oraz zawartość pola fileDateFormat zostanie zignorowana.
  • condition
    Włączenie logowania warunkowego. Jeżeli parametr zostanie ustawiony na jakąś wartość, to informacja o połączeniu zostanie zalogowań tylko wtedy, gdy ServletRequest.getAttribute() będzie równe null. Jeżeli wartością parametru będzie loguj, to połączenie zostanie zalogowane tylko wtedy, gdy będzie spełniony ten warunek: ServletRequest.getAttribute("loguj") == null.
  • fileDateFormat
    Pozwala na określenie formatu daty w nazwie pliku z logiem. Jednocześnie decyduje o tym, jak często plik ten będzie rotowany. Aby włączyć rotowanie co godzinę, można ustawić wartość parametru tak: yyyy-MM-dd.HH.

Źródła

Tags: , , , , ,

Zarządzanie transakcjami przez serwer aplikacji

W środowiskach zarządzanych (czyli np w serwerze aplikacyjnym JBoss AS) to te systemu mogą zarządzać transakcjami, czyli rozpoczynać, kończyć je w odpowiednim momencie, zwalniając z tego obowiązku programistę. W aplikacji można zdefiniować, jak dany fragment kodu ma wpływać na transakcje. Jeżeli sposób zachowanie nie zostanie zdefiniowany przez metodę, to kontener rozpoczyna transakcję zanim rozpocznie się wykonywanie metody, i kończy ją tuż przed końcem jej wykonywania. Nie są dozwolone zagnieżdżone transakcje, każda metoda może zostać skojarzona z jedną transakcją.

Definicja rodzaju transakcji

Rodzaje transakcji można zdefiniować przy użyciu adnotacji TransactionAttribute oraz TransactionAttributeType.

Adnotacja TransactionAttribute może występować zarówno na poziomie deklaracji klasy jak i deklaracji metody. Jeżeli zostanie podana przy deklaracji klasy, oznacza to że dany poziom transakcji ma zostać użyty we wszystkich metodach danej klasy, w przypadku deklaracji na poziomie metody odnosi się tylko do niej. W przypadku gdy występuje w jednym jak i drugim miejscu, pod uwagę brana jest wartość występująca przy deklaracji metody.

Poniżej przykład deklarowania rodzajów transakcji, na poziomie klasy i metod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class UserManager {
   
    @TransactionAttribute(TransactionAttributeType.SUPPORTS)
    public String getUserName() {
        return null;
    }
   
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void setUserName(String name) {
       
    }
}

Typy transakcji

Za pomocą adnotacji TransactionAttributeType można zdefiniować rodzaj transakcji, jaka ma obowiązywać w metodach. Występują następujące typy transakcji:

  • MANDATORY
    Konieczność wykonania metody w ramach istniejącej już transakcji. Jeżeli dla danego klienta istnieje już działająca transakcji, dana metoda zostanie w jej ramach wykonana. Jeżeli natomiast taka transakcji nie istnieje, to zostanie wyrzucony wyjątek TransactionRequiredException. Należy użyć tego atrybutu używać wtedy, gdy dana metoda musi zostać wykonana w ramach transakcji klienta.
  • REQUIRED
    Jeżeli klient działa w ramach transakcji i zostanie wywołana metoda oznaczona tym typem, to zostanie ona wykonana w ramach tej transakcji. Jeżeli natomiast klient nie działa w ramach transakcji, to zostanie rozpoczęta nowa, zanim metoda zostanie uruchomiona. Jest to także domyślne zachowanie, jeżeli nie zostanie ustawiony typ transakcji.
  • REQUIRES_NEW
    Jeżeli klient nie działa w ramach transakcji, to po prostu jest rozpoczynana nowa przed uruchomieniem metody. Natomiast jeżeli jest istnieje już działająca transakcja, to podejmowane są następujące kroki:

    1. Zawieszenie aktualnie działającej transakcji.
    2. Rozpoczęcie nowej transakcji do wykonania wybranej metody.
    3. Wywołanie i wykonanie metody.
    4. Po zakończeniu działania metody ponowne uruchomienie wcześniej zawieszonej transakcji.

    Typu tego należy używać w sytuacji, gdy istnieje potrzeba wykonywania danej metody zawsze w nowej transakcji.

  • SUPPORTS
    Jeżeli klient działa w ramach transakcji i wywoła daną metodę, to zostanie ona wykonana w ramach tej transakcji. Jeżeli natomiast transakcja nie istnieje, to nie zostanie ona także rozpoczęta przed wykonaniem wybranej metody.
  • NOT_SUPPORTED
    Jeżeli klient działa w ramach transakcji, to zostanie ona zatrzymana na czas wywołania wybranej metody, a po jej wykonaniu ponownie przywrócona. Jeżeli nie ma takiej transakcji, metoda zostanie po prostu wykonana, bez rozpoczynania nowej.

    Należy używać tego typu wtedy, gdy wybrana metoda nie potrzebuje transakcji do działania, a zależy nam na większej wydajności jej wykonywania (transakcje mają negatywny wpływ na szybkość wykonywania metod).

  • NEVER
    Jeżeli klient działa w ramach transakcji i wywoła metodą oznaczoną tym typem, zostanie wyrzucony wyjątek RemoteException. Natomiast jeżeli transakcja nie istnieje, to metoda zostanie wykonana bez rozpoczynania nowej transakcji.

Mała tabela, która podsumowuje powyższe:

Zachowanie kontenera w zależności od typu i stanu transakcji
Nazwa atrybutu Transakcja istnieje Brak transakcji
MANDATORY używa istniejącej wyrzuca wyjątek
REQUIRED używa istniejącej rozpoczyna nową
REQUIRES_NEW zawiesza istniejącą, rozpoczyna nową rozpoczyna nową
SUPPORTS używa istniejącej działa bez
NOT_SUPPORTED zawiesza istniejącą działa bez
NEVER wyrzuca wyjątek działa bez

Źródła

Tags: , , , , ,

Monitorowanie aktywności sieciowej procesu lub użytkownika

Oto prosta komenda, która pozwoli na monitorowanie, z jakimi adresami sieciowymi łączy się dana aplikacja lub też dany użytkownik:

  • monitorowanie aktywności procesu:
    lsof -r 2 -p PID -i -a
  • monitorowanie aktywności użytkownika
    lsof -r 2 -u USER -i -a

Poszczególne parametry oznaczają:

  • -p PID – numer procesu, który ma być monitorowany
  • -u USER – nazwa użytkownika, którego połączenia sieciowe mają być monitorowane, parametr może być użyte więcej niż jeden raz, może to pozwolić to wtedy na monitorowanie aktywności kilku użytkowników
  • -r 2 – tryb ciągłego odczytu, w tym przypadku co dwie sekundy zostaną wyświetlone aktualne dane
  • -i – wyświetlenie połączeń IP (pominięcie wyświetli także np. otwarte pliki), pozwala także na ograniczanie zakresu wyświetlanych opcji (np. IPv4 lub IPv6 czy jakaś pojedyncza domena)
  • -a – powoduje, że pomiędzy warunkami definiującymi co ma być wyświetlone jest stosowany spójnik logiczny AND (w przeciwnym wypadku będzie stosowany spójnik OR, czyli wyświetlenie np. informacji o podanym procesie lub wszystkie połączenie TCP)

Źródła

Tags: , , ,