Archive for Styczeń, 2011

Użycie dużych rozmiarów strony w JVM

W Javie istnieje możliwość zwiększania wydajności działania aplikacji poprzez zmianę sposobu użycia pamięci. Istnieje możliwość użycia Huge Memory Pages. Pozwalają one na użycie przez aplikację stron pamięci o większym rozmiarze niż standardowe 4kB (np. w przypadku Linuksa o rozmiarze 2048kB).

Użycie takich stron pozwala na zmniejszenie ilości mapowań dokonywanych przez TLB (Translation lookaside buffer). Niestety, przynajmniej w przypadku Linuksa przed użyciem takiej pamięci należy odpowiednio skonfigurować system operacyjny, czyli zarezerwować odpowiedni obszar pamięci, który zostanie użyty przez aplikacje. Trzeba pamiętać, że będzie on miał nastepujące właściwości:

  • obszar pamięci o dużych rozmiar stron będzie dostępny tylko dla aplikacji, które potrafią i chcą z niego korzystać (czyli jeżeli przeznaczymy za dużo pamięci na ten obszar, może zabraknąć RAMu dla innych aplikacji działających w ramach systemu operacyjnego)
  • pamięć ta nigdy nie zostanie zapisanie w pamięci tymczasowej (swap)
  • aplikacja musi mieścić się w całości w ramach tego obszaru, więc warto pamiętać że pamięć zajmowana przez JVM to jest suma dwóch wartości, definiowanych przez parametry -Xmx oraz -XX:MaxPermSize

Konfiguracja systemu operacyjnego Linuks


Konfigurację Huge Pages może zostać wykonana na działającym systemie, ale w przypadku za dużej fragmentacji pamięci może się nie powieść. W zawiązku z tym po zapisaniu zmian w pliku /etc/sysctl.conf przydatny może byc restart serwera.

Pierwszym krokiem będzie zdefiniowanie maksymalnego obszaru pamięci, jak ma zostać przeznaczony dla JVM. Najłatwiej zrobić to, umieszczając w pliku /etc/sysctl.conf następujący zapis:

73
kernel.shmmax = 1073741824

Wartość dla parametru należy podać w bajtach, ja zdefiniowałem ją na 1GB (1024 * 1024 * 1024). Parametr ten definiuje maksymalny obszar pamięci jaki za zostać przeznaczony dla aplikacji, ale wymagana jest jeszcze zdefiniowanie faktycznej ilości stron pamięci, jaka zostanie użyta. Robi się to przy użyciu parametru:

74
vm.nr_hugepages = 512

Rozmiar pojedynczej strony pamięci można sprawdzić przy użyciu plecenia:

grep Hugepagesize /proc/meminfo

Kolejnym krokiem będzie utworzenie specjalnej grupy w systemie operacyjnych, której członkowie będą mieli możliwość korzystania z tej specjalnej pamięci:

groupadd hugepgs

Teraz trzeba jeszcze poznań numer GID tej grupy:

grep hugepgs /etc/group

W moim przypadku będzie to numer 1005.

Teraz jeszcze należy poinformować system, że członkowie tej grupy będą mieli możliwość zapisywania do pamięci:

75
vm.hugetlb_shm_group = 1005

Dodajmy użytkownika jboss do zdefiniowanej grupy:

usermod -aG hugepgs jboss

Ostatnim krokiem będzie możliwości blokowania stron przez danego użytkownika. Robi się to w pliku /etc/security/limits.conf poprzez umieszczenie takiego wpisu:

61
62
jboss soft memlock unlimited
jboss hard memlock unlimited

Tym sposobem system operacyjny jest już skonfigurowany poprawnie, więc pozostaje uruchomić maszynę wirtualną tak, aby wykorzystała dostępną pamięć z dużymi rozmiarami strony. Robi się to przekazując parametr -XX:+UseLargePages w momencie uruchamiania JVM.

W przypadku serwera aplikacji JBoss najlepiej jest dodać parametr -XX:+UseLargePages w pliku konfiguracyjnym run.conf w miejscu definiowania zmiennej środowiskowej JAVA_OPTS. Po tym kroku można już uruchomić serwer.

Ilość zużytych bloków pamięci można sprawdzić przy użyciu komendy:

cat /proc/meminfo | grep -i pages

Źródła

Tags: ,

Kompilacja serwera aplikacji JBoss AS 5.1 ze źródeł (aktualnych)

Wersja społecznościowa (community) serwera aplikacji JBoss jest wydawana co jakiś czas w wersji stabilnej i na tym kończy się wsparcie ze strony Red Hata. Można to łatwo zauważyć na przykładzie wersji 5.1 serwera. Została ona wydana 23.05.2009 (czyli ponad półtora roku temu) i następną wersja stabilna, która się pojawiła do wersja 6.0 wydana pod koniec grudnia. W międzyczasie nie została opublikowana żadna wersja pośrednia.

Oczywiście, nie oznacza to że serwer nie posiada żadnych błędów. Jest to raczej związane z polityką firmy Red Hat, która poprawki do poszczególnych wersji wydaje tylko w ramach subskrypcji. Pozostają więc takie możliwości:

  1. Wykupić wsparcie w Red Hacie i mieć dostęp do wszelkich aktualizacji (generalnie najlepsza opcja).
  2. Pobrać aktualne źródła serwera aplikacji JBoss i samodzielnie je skompilować.

Przy pierwszym wariancie dużo do roboty nie ma, i w razie problemów zawsze można zawracać głowę firmie Red Hat. Zapewni to dostęp do przetestowanej aplikacji i da gwarancje, że wszystkie elementy działają poprawnie.

Jeżeli nie zdecydujemy się wykupienie wsparcia, pozostaje samodzielna kompilacja aplikacji. Pojawia się tutaj pytanie: po co w ogóle kompilować serwer aplikacji? Czy nie wystarczy po prostu używać opublikowanej aplikacji?

Poniższe polecenia będzie można wykonać samodzielnie po pobraniu źródeł serwera aplikacji.

Lista wszystkich zmian w repozytorium od momentu wydania wersji stabilnej JBossa 5.1:

svn log -r {2009-05-24}:BASE

Możemy sprawdzić, ile było poszczególnych zmian w kodzie źródłowym:

svn log -r {2009-05-24}:BASE | grep  ^r[[:digit:]] | wc -l

W moim przypadku wyszło 866 zmian w kodzie źródłowym.

Można także sprawdzić, ile usunięto zgłoszeń w systemie śledzenia błędów:

svn log -r {2009-05-24}:BASE | grep JBPAPP- | wc -l

W moim przypadku wyszło 502 zgłoszenia.

Jak widać, prace nad wersją JBossa 5.1 cały czas trwają.

Konfiguracja systemu

W moim przypadku cały proces kompilacji odbywa się na maszynie z systemem Ubuntu 10.10. Na szczęście system nie ma podczas tego procesu dużego znaczenia (poza detalami związanymi z instalacją pakietów).

Wymagania początkowe:

  • dostępność JDKw wersji co najmniej 1.5 (ja testowałem na JDK 1.6.22)
  • instalacja klienta Subversion
    sudo aptitude install subversion
  • instalacja aplikacji patch:
    sudo aptitude install patch

Kolejnym krokiem jest utworzenie odpowiedniego katalogu przeznaczonego na źródła serwera JBoss a następnie pobranie źródeł przy użyciu klienta Subversion:

mkdir JBoss-5.1
svn co http://anonsvn.jboss.org/repos/jbossas/branches/JBPAPP_5_1/ JBoss-5.1

Teraz pozostaje odczekać, aż źródła zostaną pobrane.

Jeżeli w przyszłości będziemy chcieli zaktualizować źródła, wystarczy wejść do katalogu z nimi (w moim przypadku do katalogu JBoss-5.1) i wydać polecenie:

svn update

Kompilacja źródeł

Pozostaje teraz skompilować serwer aplikacji. Jest to czynność stosunkowo łatwa, sprowadza się do uruchomienia jednego skryptu:

cd build
./build.sh

Podczas pierwszego uruchomienia zostaną pobrane wszystkie niezbędne do kompilacji i działania serwera biblioteki (przy użyciu aplikacji Maven). Proces ten może trwać dość długo. Po zakończeniu pobierania bibliotek źródła zostaną skompilowane i pliki binarne można będzie znaleźć w katalogu build/output.

W moim przypadku znalazł się tam katalogu jboss-5.1.1.Branch, co jak widać jest wersją nowszą niż ostatnia wersja społecznościowa serwera aplikacji JBoss 5.1.

Kompilacja ta jest także bardzo podobna do wersji komercyjnej serwera:

  • znajdziemy w niej profil production
  • w profilach jest także wyłączony dostęp do konsol zarządczych, użytkownik admin jest wyłączony w plikach konfiguracyjnych

Jeżeli z jakiś powodów wolimy wersję podobną do wersji społecznościowej, należy uruchomić na binarnym serwerze odpowiednie pliki przy użyciu polecenia patch. Dokładne instrukcje można znaleźć w pliku build/REDME.

Na zakończenie mały skrypt, który wywoła kompilację serwera JBoss, ale zapisze ją w katalogu zawierającym numer wersji repozytorium. Pozwoli to w łatwy sposób oznaczyć wersje źródeł, co może przydać się podczas testowania, czy aktualna wersja działa poprawnie i może zostać użyta na serwerach produkcyjnych.

Skrypt nazwa się build_jboss.sh i należy wywołać go z nazwą katalogu w którym znajdują źródła serwera JBoss:

./build_jboss.sh JBoss-5.1

Skrypt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash

if [ ! -n "$1" -o ! -d "$1" ]; then
        cat <<EOF
Prosze podac katalog ze zrodlami serwera JBoss:

$0 jboss-svn
EOF

        exit 1
fi

JBOSS_DIR="$1"
BUILD_DIR="build"

echo -n "Numer wersji repozytorium: "

cd $JBOSS_DIR
REVISION=$(svn info | grep Revision | cut -c 11-)
echo $REVISION

cd $BUILD_DIR

echo "Kompilacja"
./build.sh -Dversion.tag=$REVISION

echo Kompilacja zakonczona, sprawdz katalog $JBOSS_DIR/build/output
echo

exit 0

Źródła

Tags: ,

Instalacja Oracle 11g na RedHacie 5

Krótki opis instalacji Oracle 11g w systemie RHEL 5. Punkt po punkcie tak jak to wyglądało w mojej sytuacji.

  1. Wyłączenie SELinuksa.

    SELinux jakoś do końca nie chciał mi działać z Oraclem. Uparcie nie pozwalał na otwarcie niektórych plików i na uruchomienie bazy danych. Ponieważ moja maszyna nie jest narażona za bardzo na kontakt ze światem zewnętrznym, to po prostu go wyłączyłem na stałe. Najłatwiej to zrobić poprzez edycję pliku /etc/sysconfig/selinux i zmianę wartości parametru SELINUX:

    6
    SELINUX=disabled

    Teraz pozostaje restart maszyny i i SELinux powinien już być wyłączony.

  2. Dodanie nazwy serwera do /etc/hosts.

    Należy się upewnić, że można prawidłowo rozwiązać nazwę serwera, najprościej poprzez umieszczenie odpowiedniego wpisu w pliku /etc/hosts. W moim przypadku wyglądała ona tak:

    4
    192.168.122.50  oracle
  3. Konfiguracja parametrów jądra (wg dokumentacji)

    Można także skonfigurować odpowiednie parametry jądra systemu. Ja pominąłem tek krok, ale dokumentacja go zaleca, więc można do pliku /etc/sysctl.conf dodać takie linie:

    kernel.shmall = 2097152
    kernel.shmmax = 2147483648
    kernel.shmmni = 4096
    # semaphores: semmsl, semmns, semopm, semmni
    kernel.sem = 250 32000 100 128
    net.ipv4.ip_local_port_range = 1024 65000
    net.core.rmem_default = 4194304
    net.core.rmem_max = 4194304
    net.core.wmem_default = 262144
    net.core.wmem_max = 262144

    Należy pamiętać o tym, aby parametr kernel.shmmax nie był większy niż połowa dostępnej ilości pamięci RAM.

  4. Instalacja dodatkowych bibliotek.

    W przypadku Oracla należy doinstalować kilka dodatkowych pakietów:

    yum install binutils elfutils-libelf glibc glibc-common libgcc \
        libstdc++ make elfutils-libelf-devel glibc-devel gcc gcc-c++ \
        libstdc++-devel unixODBC libaio libaio-devel unixODBC-devel \
        'sysstat*' 'compat-libstdc++*'
  5. Konfiguracja użytkownika dla Oracla.

    Dobrze jest uruchomić serwer na koncie oddzielnego użytkownika, którego należy utworzyć i odpowiednio skonfigurować.

    Dodanie nowego konta wraz z odpowiednimi grupami:

    groupadd oinstall
    groupadd dba
    groupadd oper
    groupadd asmadmin

    useradd -g oinstall -G dba,oper,asmadmin oracle
    passwd oracle

    Ustawienie odpowiednich ograniczeń dla użytkownika oracle, w pliku /etc/security/limits.conf należy umieścić takie linie:

    50
    51
    52
    53
    oracle    soft    nproc   2047
    oracle    hard    nproc   16384
    oracle    soft    nofile  1024
    oracle    hard    nofile  65536

    Należy się jeszcze upewnić, że w pliku /etc/pam.d/system-auth znajduje się taka linia:

    18
    session     required      pam_limits.so

    Ostatnim krokiem będzie zdefiniowanie odpowiednich zmiennych środowiskowych dla użytkownika oracle w pliku /home/oracle/.bash_profile:

    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    export ORACLE_HOSTNAME=oracle
    export ORACLE_BASE=/opt/oracle/oracle
    export ORACLE_HOME=$ORACLE_BASE/product/11.1.0/db_1
    export ORACLE_SID=baza
    export ORACLE_TERM=xterm
    export PATH=/usr/sbin:$PATH
    export PATH=$ORACLE_HOME/bin:$PATH
    export ORA_OWNR="oracle"

    export JAVA_HOME="/etc/alternatives/java_sdk"

    export PATH=.:${JAVA_HOME}/bin:${PATH}:$HOME/bin:$ORACLE_HOME/bin
    export PATH=${PATH}:/usr/bin:/bin:/usr/bin/X11:/usr/local/bin

    export LD_LIBRARY_PATH=$ORACLE_HOME/lib
    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$ORACLE_HOME/oracm/lib
    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/lib:/usr/lib:/usr/local/lib

    export CLASSPATH=$ORACLE_HOME/JRE
    export CLASSPATH=${CLASSPATH}:$ORACLE_HOME/jlib
    export CLASSPATH=${CLASSPATH}:$ORACLE_HOME/rdbms/jlib
    export CLASSPATH=${CLASSPATH}:$ORACLE_HOME/network/jlib

    export THREADS_FLAG=native

    Należy zwrócić w szczególności uwagę na miejsce, gdzie ma zostać umieszczona baza danych Oracle, nazwę serwera czy też użytkownika i odpowiednio je dostosować do własnych potrzeb.

  6. Utworzenie katalogu do instalacja.

    Teraz jeszcze należy utworzyć odpowiedni katalog, w którym zostanie zainstalowana baza danych:

    mkdir -p /opt/oracle
    chown -R oracle:oinstall /opt/oracle
    chmod -R 770 /opt/oracle
  7. Instalacja bazy danych Oracle

    Instalację bazy danych należy wykonać, będąc użytkownikiem oracle. Należy pamiętać, że w czasie instalacji będzie potrzebny dostęp do serwera X Window (jeżeli nie zadziała to przy użyciu komendy su lub sudo zawsze można zalogować się na serwer przy użyciu polecenia ssh -X oracle@localhost).

    Jako użytkownik oracle należy uruchomić skrypt runInstaller. Sprawdzi on środowisko i następnie uruchomi właściwy instalator graficzny. Podczas niego należy odpowiedzieć na szereg pytań, poniżej zrzuty ekranu z mojej instalacji:

    Jednym z ostatnich kroków instalacji jest konieczność uruchomienia dwóch skryptów: orainstRoot.sh oraz root.sh.

    Należy pamiętać, że skrypty te należy uruchomić na uprawnieniach użytkownika root:

    # /opt/oracle/oraInventory/orainstRoot.sh
    Changing permissions of /opt/oracle/oraInventory to 770.
    Changing groupname of /opt/oracle/oraInventory to oinstall.
    The execution of the script is complete
    # /opt/oracle/oracle/product/11.1.0/db_1/root.sh
    Running Oracle 11g root.sh script...

    The following environment variables are set as:
        ORACLE_OWNER= oracle
        ORACLE_HOME=  /opt/oracle/oracle/product/11.1.0/db_1

    Enter the full pathname of the local bin directory: [/usr/local/bin]:
       Copying dbhome to /usr/local/bin ...
       Copying oraenv to /usr/local/bin ...
       Copying coraenv to /usr/local/bin ...


    Creating /etc/oratab file...
    Entries will be added to the /etc/oratab file as needed by
    Database Configuration Assistant when a database is created
    Finished running generic part of root.sh script.
    Now product-specific root actions will be performed.
    Finished product-specific root actions.
  8. Automatyczny start instancji bazy danych

    W pliku /etc/oratab należy zdefiniować, jakie instancje bazy danych będą automatycznie uruchamiane podczas startu bazy danych. W ostatniej kolumnie należy zmienić N na Y:

    1
    baza:/opt/oracle/oracle/product/11.1.0/db_1:Y

    Teraz czas na utworzenie odpowiednich plików startowych:

    • /etc/sysconfig/oracle – definicja zmiennych środowiskowych, używanych w skryptach startowych
      1
      2
      3
      ORACLE_BASE=/opt/oracle/oracle
      ORACLE_HOME=$ORACLE_BASE/product/11.1.0/db_1
      ORACLE_OWER="oracle"
    • /etc/init.d/oracle – skrypt, który umożliwia uruchomienie i zatrzymanie bazy danych
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      #!/bin/bash
      #
      #       /etc/rc.d/init.d/oracle
      #
      # chkconfig: 345 98 02
      # description: Uruchomienie bazy danych Oracle

      # Source function library.
      . /etc/init.d/functions


      if [ -f /etc/sysconfig/oracle ] ; then
              . /etc/sysconfig/oracle
      fi

      start() {
              echo "Starting Listener: "
              su - $ORACLE_OWER -c "$ORACLE_HOME/bin/lsnrctl start"

              echo "Starting Oracle Database: "
              su - $ORACLE_OWER -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME"

              return 0
      }

      stop() {
              echo "Shutting down Oracle Database: "
              su - $ORACLE_OWER -c "$ORACLE_HOME/bin/dbshut $ORACLE_HOME"

              echo "Starting Listener: "
              su - $ORACLE_OWER -c "$ORACLE_HOME/bin/lsnrctl stop"

              return 0
      }

      case "$1" in
          start)
              start
              ;;
          stop)
              stop
              ;;
          restart)
              stop
              start
              ;;
          *)
              echo "Usage: oracle {start|stop|restart}"
              exit 1
              ;;
      esac
      exit $?
    • /etc/init.d/em – skrypt, który pozwala na uruchomienie Enterprise Managera
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      #!/bin/bash
      #
      #       /etc/rc.d/init.d/em
      #
      # chkconfig: 345 99 01
      # description: Uruchomienie Enterprise Managera

      # Source function library.
      . /etc/init.d/functions

      if [ -f /etc/sysconfig/oracle ] ; then
              . /etc/sysconfig/oracle
      fi

      start() {
              echo "Starting Enterprise Manager: "
              su - $ORACLE_OWER -c "$ORACLE_HOME/bin/emctl start dbconsole"

              return 0
      }

      stop() {


              echo "Shutting down Enterprise Manager: "
              su - $ORACLE_OWER -c "$ORACLE_HOME/bin/emctl stop dbconsole"

              return 0
      }


      case "$1" in
          start)
              start
              ;;
          stop)
              stop
              ;;
          restart)
              stop
              start
              ;;
          *)
              echo "Usage: oracle {start|stop|restart}"
              exit 1
              ;;
      esac
      exit $?

    Teraz trzeba skonfigurować system, aby uruchamiał skrypty podczas startu:

    chmod +x /etc/init.d/oracle /etc/init.d/em
    chkconfig --add oracle
    chkconfig --add em

    Po tych krokach baza danych oraz EM będą uruchamiane podczas startu serwera. Oczywiście można także uruchomić te aplikacje od razu:

    1
    service oracle start; service em start

Źródła

Tags: ,