piątek, 31 stycznia 2014

Tomcat - RequestFilterValve

Zabezpieczenie po IP

Czasem trzeba się zabezpieczyć przed dostępem do niektórych zasobów Tomcat-a. Wprawdzie ta metoda nie jest zbyt skuteczna, ale na początek można ją spróbować.

Przykładowa definicja:
<Context>
  ...
  <Valve className="org.apache.catalina.valves.RemoteHostValve"
         allow=".*\.mycompany\.com|www\.yourcompany\.com"/>
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         deny="192\.168\.1\.\d+"/>
  ...
</Context>
Można powiedzieć że jest w tym przykładzie zdefiniowany łańcuch 2 obiektów Value.
Jak tylko dojdzie do RemoteHostValve to na pewno go wykona jak, nie wywali w tym czasie błędu 403 to wykona również RemoteAddrValve. Wiec to oznacza że do RemoteAddrValve może nie wejść.

Podczas badania jak działa RequestFilterValve wyszły mi następujące wnioski:

Dane do sprawdzania
  • request.getRemoteAddr() - adres IP z requesta
  • request.getRemoteHost() - nazwa hosta


Kolejność sprawdzania
  • denies jak przejdzie idzie dalej
  • allows jak przejdzie idzie dalej
  • jak doszło do tego miejsca i jest ustawione denies i nie ustawione allows to idzie dalej
  • wywala 403

Scenariusz testów

Dodaje definicję w/w value do tomcat/conf/server.xml w sekcji Host tak jak access log
Moja maszyna ma IP 192.168.1.10
Mój Tomcat ma connector https na porcie 443.
Odpalam Tomcat-a 
Z przeglądarki pytam https://192.168.1.10/manager/html/ - powinno mnie wpuścić
Z przeglądarki pytam https://127.0.0.1/manager/html/ - powinno dać komunikat 403
Definicję value przenoszę do tomcat/conf/context.xml - spawdzam działanie
Definicję value przenoszę do tomcat/conf/Catalina/localhost/ap-xxxx.xml - spawdzam działanie

Wnioski:

  • przy ustawionych denies i allows - definicja denies powinna być bardziej szczegółowa niż allows, dlatego że inaczej nie wejdzie do sprawdzenia allow
  • prawdopodobnie lepiej jest zdefiniować kilka value z pojedynczymi definicjami denies albo allows
  • można dla definicji denies i allows podać dowolne wyrażenie regularne przyklady z ip oczywiście są sensowne, ale może to być cokolwiek. Warto zwrócić uwagę na znaki \ 
  • dla definicji denies i allows można podać kilka wartości oddzielonych znakiem "," Zostaną one zamienione na tablicę Pattern[]

Źródła:

http://tomcat.apache.org/tomcat-6.0-doc/config/context.html#Request_Filters
http://fossies.org/dox/apache-tomcat-6.0.37-src/RequestFilterValve_8java_source.html

Tomcat - zdalne debugowanie

Łatwo znaleźć - ale lepiej mieć pod ręką

Niektóre rzeczy łatwo znaleźć u wujka google, trzeba jednak wiedzieć jak go zapytać.

Wiadomo można odpalić Tomcat-a w środowisku IDE Eclipse i podłączyć źródła.
Ja to robię jeszcze prehistoryczną metodą przy pomocy pluginu http://www.eclipsetotale.com/tomcatPlugin.html ale jak, ktoś wie co i jak to znajdzie lepsze patenty.

Czasem jednak skórka nie warta wyprawki i lepiej się podłączyć do tego co już jest.

Akurat pracuję pod Windows więc cytuje zaklęcia:

  set JPDA_ADDRESS=8000
  set JPDA_TRANSPORT=dt_socket
  bin/catalina.bat jpda start

W IDE Eclipse wystarczy zdefiniować Run / Debug Configuration / Remote Java Application, ustawić port 8000, podłączyć źródła np Tomcat-a i można sobie oglądać na żywo.


czwartek, 30 stycznia 2014

SSH - putty autoryzacja kluczem

Uciążliwe hasło

Jednych z częściej wykonywanych operacji przez administratora jest autoryzacja. Oczywiście można być połączony cały czas, ale w środowisku korporacyjnym gdzie funkcjonuje limitowanie tego typu "przywilejów" będziesz musiał ciągle zmieniać i podawać hasła. 
Znajdą się oczywiście "specjaliści", którzy na siłę będą Ci wciskać domenową autoryzację Window lub LDAP i może jeszcze inne cukiereczki.

Ja osobiście korzystam z czegoś prostszego.

Klient windows putty, pagent, puttygen

Jako że korzystam z Windows (nie z przyjemności), trzeba mieć pod ręką jakiego klienta ssh. Nie wiem nawet czy jest jakaś alternatywa do putty, w każdym razie używam.
W ramach paczek, które oferuje można sobie wygenerować klucze RSA i na podstawie tego się autoryzować.

putty

W przypadku klienta putty dla Windows robię to tak:
  • wygenerować klucz puttygen
  • zapisać klucze do plików (najlepiej z hasłem)
  • skopiować zawartość klucza publicznego (wyciąć entery
  • na maszynie na której chcemy się logować kluczem utworzyć plik $HOME/.ssh/authorized_keys skopiować do niego zawartość (dodać na końcu) w formacie
  • ssh-rsa 12312312313212312sdfsdfsdfd.............s23423432424234== user@ip
Uwaga!!! na entery puttygen generuje klucz z enterami (powycinać)
ustawić w putty do autoryzacji klucz prywatny

pageant

Wykorzystać pageant do ładowania kluczy do autoryzacji.
Dodać do autostat-u odpalenie pageant z ładowaniem kluczy
"C:\Program Files\ssh\pageant.exe" "c:\Users\user\Documents\ssh\local\keys.prv.ppk"
Klucze lepiej przechowywać w katalogu domowym
Jeżeli klucz zostanie wygenerowany bez hasła (teoretycznie niezalecane) w praktyce w wewnętrznej sieci bardzo wygodne), będziemy mieli dostęp tylko po wpisaniu ip do clienta ssh

Od tego momentu wszystkie operacji ssh (putty, winscp) gdy uda się automatyzować w/w kluczem będą wykonywane automatycznie w oparciu o klucze

Klient linux

ssh-keygen -t rsa -C "xxx@host"
Wygenerowane zostaną pliki w katalogu domowym ~/.ssh/ (id_rsa, id_rsa.pub)
Zawartość id_rsa.pub trzeba skopiować do authorized_keys na maszynie docelowej. Katalog ~/.ssh/, jeżeli nie ma trzeba utworzyć, należy zwrócić uwagę na uprawnia.

Konfiguracja dla konta linux

Dla konta linux na którym chcę się logować przy pomocy klucza stosuję następującą procedurę:

  cd ~
  mkdir .ssh
  chmod 700 .ssh/

Kopiowanie kluczy z innej maszyny (to uproszczona wersja). Można dodać poszczególne klucze ręcznie.
  scp user@ip:/home/kczerw/.ssh/authorized_keys .ssh/ 

  chmod 400 .ssh/authorized_keys

Uprawnienia do plików są bardzo ważne!!!


środa, 29 stycznia 2014

Zabbix - screen javascript search

Dużo screenów

Jednym z lepszych sposobów na organizowanie wykresów jest grupowanie ich w screen-y, które pozwalają na jednym ekranie pokazać kilka wykresów. W zabbix 2.0 mamy 2 typy screenów: ogólne oraz host screeny. Mnie na razie interesują te pierwsze w których można łączyć wykresy z różnych hostów. 
W dużym systemie może ich się pojawić dużo. Autorzy do wybierania screena wykorzystali pole combo (select), które przy dużej ilości wpisów jest wyjątkowo niewygodne.

Planowane ułatwienia

Zastanawiałem się nad zrobieniem pola autocomplete, które by zastąpiło pole combo. Ze względu na fakt że API w zabbix nie jest zbyt fajne i dodatkowo w PHP (jakoś przyzwyczaiłem się do Java) postanowiłem szukać innego rozwiązania.
Może to co przyszło mi do głowy, nie jest najszczęśliwsze, ale proste do zrobienia. Dodałem do pola combo filtr w postaci pola tekstowego, który zawęża wartości w polu combo do tych które zawierają wprowadzony tekst. Aktualizacja zawartości pola combo jest na onblur pola tekstowego.


Wartości pola tekstowego nie są zapamiętywane na stałe w serwerze... ale można się o to pokusić.
Myślę że nie warto, zamiast tego lepiej będzie popracować nad polem autocomplete.
Tymczasem proponowane rozwiązanie.

Zmiany

Modyfikacji poddałem include/views/js/general.script.confirm.js.php 
Obsługa dotyczy pola select#elementid, zrobiłem to korzystając z jQuery


<script type="text/javascript">

...
        function selectScreenRebuild(){
         var i=jQuery('input#screen_filter_value');
         var fv=i.val();
         fv=fv.trim();
         var selScreen=jQuery('select#elementid');
         //console.log('key', fv);
         var re=new RegExp(fv,"i");
         //clearall
         jQuery('select#elementid option').remove();
         jQuery('<option value="">-- wybierz --</option>').appendTo(selScreen);
         jQuery(selectScreenCopy).each(function(i,o){
          var ov=o.v;
          var ot=o.t;
          var o_visible=re.test(ot);
          if(o_visible) {
           //console.log("keydown", fv, ot);
           jQuery('<option value="'+ov+'">'+ot+'</option>').appendTo(selScreen);
          }
         });
        }

        var selectScreenCopy=[];
        jQuery(function(){
          jQuery('select#elementid option').each(function(i,o){
                //console.log(i,o);
                var f=jQuery(o);
                var v=f.val();
                var t=f.text();
                selectScreenCopy[i]={v:v,t:t};
          });

          var filter_value=jQuery('input#screen_filter_value');

          filter_value.keyup(function(e){
                selectScreenRebuild();
          });
          filter_value.change(function(e){
                selectScreenRebuild();
                //setTimeout(function(){ jQuery('select#elementid').closest('form').submit() },500)
          });
        });

Wyszukiwarka wydaje się prymitywna jednak przyspiesza niesamowicie szukanie po combo.


Zabbix - optymalizacja pod kątem wydajności

Wydajność IO daje się we znaki

Na razie wszystkie instalacje które wykorzystuje pracują na bazie MySQL.
Możliwe że w przypadku zastosowania innej bazy takie problemy nie występują.

W większych instalacjach zdarzyły mi się problemy dotyczące housekeeper-a który zaczął wykonywać za dużo operacji IO na dysku. Do pewnego momentu próbowałem modyfikować parametry mysql-a jednak nie dawało to sensownych rezultatów.

Podjąłem dlatego próbę zmniejszania częstości pytania itemów.
Do pewnego momentu robiłem to z poziomu interface, jednak poddałem się i zacząłem modyfikować dane z poziomu sql-a.

Przyjąłem założenie aby nie definiować itemów które maja duże history. Domyślnie zabbix zakłada itemy które maja history = 90 dni. Sprawdzona optymalna wartość to 7 dni.

Może to nie jest jedyny sposób optymalizacji, możliwe że trzeba zabrać się za partycjonowanie tabel jak w jednym z linków. Poniższy przykład może być jednak pomocny do diagnostyki skali problemu.

Przydatne SQL

Poniżej zebrałem parę zapytań, które się bardzo przydają:

Sprawdzenie items pod kątem częstości odświeżania
  select delay,type from items group by delay,type;

Wielkość tabeli z historia
  show table status like 'history';

Badanie wilkości tabelek o nazwie jak maska '%history%'
  SELECT table_rows, table_name AS "Table",  
  round(((data_length + index_length) / 1024 / 1024), 2) "Size in MB"  
  FROM information_schema.TABLES  WHERE table_schema = "zabbix" and

  table_name like '%history%';

Sprawdzenie które itemy maja największą ilość wpisów historii
  select itemid, count(itemid) from history group by itemid order by count(itemid);

Usuwanie starej historii itemów od daty (dane podać w formacie timestamp unix)
  delete from history where itemid in(xxx,xxx,xxx) and clock<1380585600;

Usuwanie historri po kawałku
  delete FROM history  where clock < UNIX_TIMESTAMP(date_sub(current_timestamp, 
  interval 7 day)) limit 1000000;

  delete from history_uint where clock<UNIX_TIMESTAMP(date_sub(current_timestamp, 
  interval 4 day)) limit 1000000;

Sprawdzenie które itemy mają historię dłuższą niż 7 dni (w definicji)
  select itemid, name, key_ from items where history > 7;

Liczba itemow w tysiacach
  select count(cnt), cnt from (select round(count(itemid)/1000) cnt 
  from history_uint group by itemid) a group by cnt;


Operacje na datach w tabelkach z historią

Data w formacie unix
  FROM_UNIXTIME()

  select FROM_UNIXTIME(clock) from history order by itemid desc limit 10;

Godzina (data) o 7 dni wcześniej
  date_sub(current_timestamp, interval 7 day) 

Konwersja na date w formacie unix timestamp
  UNIX_TIMESTAMP()

  select UNIX_TIMESTAMP(date_sub(current_timestamp, interval 7 day));

Sprawdzenie ile jest rekordów historii starszej niż 3 dni
  select count(*) from history where
  clock<UNIX_TIMESTAMP(date_sub(current_timestamp, interval 3 day));

  select count(*) from history_uint where
  clock<UNIX_TIMESTAMP(date_sub(current_timestamp, interval 3 day));

Indexy

Sprawdzenie indexow dla tabelki
  SHOW INDEX FROM history_uint;

Opis tabel

Niektóre rzeczy dobrze mieć pod ręką.
Database tables for history/trends and theirs item type:

  • history – numeric (float)
  • history_uint – numeric (unsigned integers)
  • history_str – character (up to 255 bytes)
  • history_log – log
  • history_text – text
  • trends – numeric (float)
  • trends_uint – numeric (unsigned integers)

Notatnik

Parsowanie zapytania
  QueryHandler .handleQuery
  JMXHelper

Linki

http://zabbixzone.com/zabbix/history-and-trends/http://zabbixzone.com/zabbix/partitioning-tables/

sobota, 25 stycznia 2014

Zabbix - daje radę

Trudne początki

Zaczęło się pozornie kiepsko. Może nie było by specjalnie o czym pisać. Ale tego co monitoruję nazbierało się sporo, dlatego myślę że warto to pokazać. Z oczywistych przyczyn musiałem poddać dane anonimizacji. Większość z tych rzeczy udało się spreparować podczas rozwijania aplikacji Kamsoft.

To było dość dawno... Oczywiście sobie nie przypomnę kiedy, ale sporo czasu już minęło.
Pogadanka u szefa jak to zwykle. Podobno ktoś tam używa Zabbix. I podobno monitoruje system. W czasach gdy ja miałem opanowane robienie wykresów RRD z poziomu Cacti, gdzie wcale nie trzeba było bazy i jedyną zajętość jaką generowało Cacti to były pliki RRD. Zadawałem sobie pytanie po co to w ogóle taka kobyła. Dodam że zacząłem się cieszyć moją nowinką skryptową perl-a i RRD. Udało mi się zrobić właśnie nowy wykres do Cacti który potrafił na wykresie zobrazować różne rodzaje requestów do naszego systemu w skali czasu. Ilość requestów znaczyłem kolorami. Oś X to czas. Oś Y to typy Requestów (ze względu na rodzaj operacji) było tego z 1000. Oj było na co popatrzeć. Widać było coś na kształt (tylko przykład) nie mam oryginalnego wykresu. Był wielki i życie zweryfikowało jego użyteczność - poszedł do kosza. Mało co z tego dało się niestety wywnioskować. Widmo dość losowe. A trzeba było znaleźć przyczynę i źródło wycieku pamięci. Oj niestety w Javie też tak się da.

Jakoś zawsze miałem sentyment do skryptów, których nie trzeba kompilować i na potrzeby uruchomienia jednego zadania wszystko działa od razu bez całej tej kompilacji (ech ta Java) nawet przy dużych projektach. Wiadomo że nie wszystko złoto co się świeci - teraz to wiem.

Szukanie przyczyny to był jakiś katalizator do poszukiwań jakiegoś narzędzia do diagnostyki takich problemów. Wtedy nasz system był znacznie mniejszy. Raptem 2 workery Tomcat-a. Ale mimo to przychodziły takie momenty, że to klękało. Wtedy zaczynało się szukanie i nerwówka.

Zabbix-a zainstalowałem ale mnie nie przekonał.
Jedyne czego zazdrościłem wtedy to scrollowania czasu. Teraz uważam że to chyba najgorsze co ma Zabbix. Na ten czas nie byłem tego w stanie ogarnąć. Wyglądało jakby to samo potrafiło znajdować to co ma diagnozować. Znalazło Linux-y i tyle. Wtedy w Cacti potrafiłem znacznie więcej.

Odstawiłem to na półkę i zostałem przy Cacti.

Szef wie co chce i dąży do celu, jak się na coś zaweźmie. Tak jak to bywa w większej firmie - temat dostał ktoś inny. Oj wcale się nie zdziwiłem. Marketing-owo podobno poszedł krok dalej. Ale jak popatrzyłem to, stanął tam gdzie ja. 

Prostsze będzie lepsze

Było by dobrze z Cacti - ale tylko u mnie. Na innych instalacjach już nie było tak kolorowo. Monitorowałem swój system (testowy) a produkcja była już poza moim zasięgiem. Jeden miał tak inny inaczej. Nasz system zaczął się rozrastać i nawet na testowym systemie zaczęło się robić ciasno i wolno. Przed oczami przewinął mi się wtedy wykres diagnostyki dysku z Linux-a (iostat). Niby tylko tak prosty xml do importu do zabbix. Jak sobie pomyślałem, że trzeba by to od zera dziargać w perl-u coś dla Cacti trochę mnie lenistwo ogarnęło. To był jakiś przełom w Zabbix. Wykresy się pojawiły w Zabbix. To była dobra wróżba. To się da sprzedać dla innych administratorów. I tak właśnie zostały pogrzebane moje argumenty lekkości. Nadal ciągle próbuję znaleźć równowagę pomiędzy kodowaniem w jakimś sensownym języku a definiowaniem w xml-u. Kto robił grubsze skrypty w ant wie co to znaczy.

Jeden z pierwszych wykresów Zabbix iostat który mnie przekonał o tym że to się da używać.

Hosty

To jest właśnie ciekawe, że skomplikowanie powoduje uproszczenie. Takie wrażenie na mnie wywarła wizja hostów. Takim hostem może być np Tomcat, ESB, Agent. I to jest właśnie pomylenie. Naturalnie bym tak nie pomyślał. Wielu którzy się zetknęli z Zabbix tak pomyśli. Pewnie da się to przerobić tak aby host który obrazuje System (np Linux) posiadał dodatkowe itemy odpowiedzialne za monitorowanie poszczególnych usług. Tomcat przecież można uważać jako usługę. Pewnie podpinając go przez JMX tak by było. Lepiej tego nie robić tak. Moje doświadczenia z JMX są negatywne jeżeli chodzi o komunikację po sieci. JMX potrzebuje dużego zakresów portów, a to czasem nie jest proste do osiągnięcia.

Duży system i wirtualizacja

Tu się pojawił dopiero skok. Łatwo było kogoś przekonać: wiesz tu jest wirtualka. Sciągasz i masz. Ale zanim się to zaczęło sam u siebie tak zrobiłem. Przeniosłem się z docelowej maszyny na wirtualki. Ciekawe zdarzenie miałem miejsce śledzić. Coś na wirtualkach zaczeło zjadać procki na operacjach IO. Rzut oka na główna maszynę, która hostuje VMware i co okazuje się, że na głównej też coś zjada tak proca.
Okazało się że kolega kopiował obraz - niestety na wirtualkach to się odbija jak cień na całym systemie.
Można się nieźle pomylić jak się nie ma obrazu całości a tylko fragment. A już chciałem badać moje aplikacje...

Co by tu jeszcze zmonitorować?

Lepiej nie przesadzać z monitorowaniem to jakoś zawsze wiedziałem. 
Potrafię jednak wpiąć się w różne ciekawe miejsca. 
W najbliższym czasie spróbuje pokazać inne obrazki.
Obrazki to nie jest jedyna dobra rzecz tego systemu. Dobrze zestrojony może alertować o tym że coś się złego święci. Nie należy jednak tego traktować jako złoty środek. Zwykle już jest ciepło jak Zabbix się odzywa. 

Na dziś można rysować ze wszystkiego co daje dostęp przez JMX, SNMP korzystając z normalnego agent-a. Przez traper dowolne skrypty wsadowe.

Źródła

Kod i skrypty można pobrać z https://code.google.com/p/zabbix-extension/.

Linux

Monitorowanie systemu linux w podstawowym zakresie działa całkiem dobrze. Zabbix Agent dla systemu linux exportuje podstawowe intem-y i działają one całkiem dobrze. 
Tego tematu nie zamierzam tu poruszać. Skupię się więc na tych rzeczach, które są nietypowe. 
Większość statystyk które chcemy możemy znaleźć jako opis na stronie zabbix-a, ale akturat takiej nie znalazłem. 
Dużo danych można dodać do systemu przez dodanie dodatkowych UserParams do zabbix agenta.
Zazwyczaj sprowadza się to do podania skryptu który należy uruchomić aby zwrócił określone dane na ż żądanie dostarczenia przez agenta jakiegoś item-a. 
Takie rozwiązanie jest dobre, ale tylko wtedy gdy pobranie gdy skrypt wykonuje się szybko, lub itemy pytane są wyjątkowo rzadko.
Przy odpytywaniu np 1 na minutę kilku, lub kilkunastu itemów zaczniemy mieć problemy.
Dlatego większość optymalizacji które się pojawią sprowadzają się do cachowania pewnych danych, a potem zwracania ich z tego cache na żądanie. 

Netstat

Jednym z takich przykładów jest napisany dla wprawki w perlu netstat.
Statystyka okazała się całkiem przydatna do sprawdzenia i tuningu konfiguracji Apache httpd.

Przykład statystyki netstat dla serwera z uruchomionym Apache httpd. Widać różnicę po zmianie.
Przy poprzedniej konfiguracji nie wyrabiały routery.
Rozszerzenie składa się z:

  • skryptu w pythonie które pobierają dane z netstat-a i cachują w pliku
  • skryptu w pythonie który pobiera item-a z cache (plik)
  • wpisu do cron-a który uruchamia co minute aktualizację cache
  • aktualizacji UserParams dla zabbix agent-a
  • definicji itemów wykresów dla zabbix



Tomcat

Główne obrazki którymi się ludzie cieszą to pamięć i requesty. Wiadomo to się przydaje. To oczywiście też mam w swoim repertuarze.
Trochę nietypowe połączenie. Korelacja czasu przetwarzania i liczba requestów to ważny wskaźnik
w systemie o w miarę stałej wartości czasu odpowiedzi. 
Osobiście nie badam zbyt często. To obciąża system. Wartości które dobrałem to kompromis. Tu są liczniki do badania, więc nic nie ginie, może zostać tylko scałkowane (efekt filtra dolnoprzepustowego). Nie chcę w tym wypadku bawić się w wyciąganie wniosków z tego co jest namalowane. Okazuje się, że aby coś sensownego zobaczyć trzeba przejrzeć kilka punktów.

Liczba sesji jest ważna ponieważ to alokuje pamięć serwera.
Gdy nie zdążysz zareagować na wyciek pamięci wszystkie statystyki idą do piachu. Wiesz tylko że to się zaczęło mniej więcej o godzinie X.

Alokacja pamięci powyżej zadeklarowanej kończy się ogólna klęską. Wykresy też przestają wtedy działać.
Gdy brakowało informacji z bazy danych, jedną z możliwości sprawdzania liczby połączeń do bazy była analiza póli połączeń. Tu też mogą się pojawić problemy jak coś się nie pozamyka (szczególnie z winy developera).
Jedna z pól połączeń do bazy

Apache httpd

Pierwszy punkt styku klienta i aplikacji webowej to serwer WWW. Oczywiście można sobie wyobrazić różne rozwiązania z balancingiem niemniej jednak, to choć stare to jest nadal dość powszechne.

Kody odpowiedzi na minutę. Dość ważne z punktu widzenia detekcji
błędów raportowanych do klientów (szczególnie 503)
Typy requestów na minutę
Balancing przekazuje sterowanie do workerów, można to traktować jak kolejkę.
Na tym wykresie ładnie będzie widać jak coś zwolni przetwarzanie.

WSO2 - ESB

Przez magistralę przelatuje mnóstwo danych. Czasem dzieją się tam dziwne rzeczy. Niektóre można zaobserwować na liczbie połączeń, oraz na wyłączaniu serwisów. Wiadomo jak tu coś klęknie to klapa na max-a.

Jeden z parametrów ESB
Liczba połączeń do ESB (przychodzące i wychodzące)

iSeries DB2

Po uruchomieniu interface SNMP wydawało się że to jest właśnie dobre miejsce do badania parametrów DB2. Baza informacji SNMP była wystarczająca, CPU, Pamięć, trochę zamotane netstat którego nie wiedziałem jak ugryźć. Moje poszukiwania po interface SNMP nie przyniosły oczekiwanego rezultatu.

CPU niby nic szczególnego ale bez tego jak bez ręki
Liczba procesów jest ważna ponieważ jest to związane z liczbą połączeń do bazy.
Niestety połączenia to nie jedyne procesy i trochę trudno na podstawie tego powiedzieć co.
Z analizy puli pamięci ciężko coś wnioskować. Może kiedyś z tego zrobię jakiś doktorat, ale na dziś jest ta informacja jest nieużyta.
Po dłuższej zabawie w pythonie wyłuskałem z SNMP te wiadomości nestat które są dla mnie coś warte i pokazują liczbę połączeń z określonych maszyn.

Połączenia do iSeries DB2 z 4 maszyn klastra. Gdy wszystko jest ok to obciążenie się rozkłada równo.
Warto widzieć ile połączeń jest ogólnie. Jak wiadomo różne sterowniki pracują na różnych portach. Dobrze by mieć jeszcze jakiś rozdział na określone porty.

Tak jak powiedziałem - chciałem coś więcej. Jedno z miejsc gdzie takie statystyki znalazłem jako pudełkowe to był Mysql. Właśnie ta statystyka mnie zainspirowała do tego, aby do bazy iSeries DB2 spróbować poszukać podobnego rozwiązania. Na razie nie znalazłem tego jako gotowy kawałek, jednak znalazłem narzędzia w iSeries, które pomogły coś takiego uzyskać. Znaczenie więcej dostaje się z tabelek systemowych. Oto przykłady:
Otwarcie i zamknięcie obiektów
Statystyka operacji zmiany ze względu na rodzaj
Rodzaje operacji odczytu

Każdy z tych wykresów był kluczowy podczas analizy optymalności pracy aplikacji, szczególnie pod dużym obciążeniem. Patrząc na system jako czarna skrzynka, te parametry to kluczowe wyznaczniki złożoności operacji. Można to skorelować z operacjami logicznymi systemu. Z odczytów możemy odczytać czy zapytania są wykonane optymalnie. Zbyt duże wartości odczytów w najbardziej trywialnym przypadku może oznaczać brak index-ów. Można być też przyczyną nieoptymalnej implementacji procedur na bazie.
Trochę więcej można się dowiedzieć analizując w krótkich okresach czasu wybrane obiekty.
Na temat samych procesów można też się co nieco dowiedzieć.
Typy job-ów z iSeries
Wielkość kolejki komunikatów dla zadań określonego typu.

Openfire

Po dłuższym okresie użytkowania aplikacji Openfire, okazało się że serwer na którym jest uruchomiona miewa mocne zadyszki i na maszynie wirtualnej powoduje zamięszanie. To był więc opiszę więc moją przygodę z openfire .jeden z motywów aby podłączyć tę aplikację do monitorowania wydajności. Okazało się że sam monitor jmx java niewiele mówi, a mechanizmy, które są dostępne nie pokazują tego co chciałem. Na tyle dużo się tego zrobiło że postanowiłem z tego zrobić oddzielny rozdział pod tytułem Zabbix - Openfire monitoring

Raporty z aplikacji

Po jakimś czasie znalazłem nietypowe zastosowanie dla Zabbix. Czasem dobrze widzieć w tym samym miejscu rzeczy z systemu oraz z aplikacji. Ja wybrałem raporty przez JMX dlatego że dla mnie stworzenie interface komunikacji z Java było wyjątkowo proste. Na pierwszy ogień poszedł system autoryzacji.

Tokeny związane z autoryzacja w ciągu dnia.

Statusy operacji autentykacji (Operacji na minutę. Odpowiednio Z - zalogowanie, W - wylogowanie, T - blokada tymczasowa, P - hasło wygasło, O - błędne konto/hasło, E - blokada konta) 
Co ciekawe przy zasilaniu takimi danymi nawet na Zabbix da się wykryć próby łamania haseł. Mając te dane historycznie można łatwo to wyśledzić w postaci obrazków. Użyteczne a niewielkim kosztem.

Java - Sprawdzenie ID procesu na linux

Czasem może się zdarzyć że trzeba sprawdzić identyfikator procesu.
Poniżej znalazłem taki kawałek w WSO Carbon

        byte[] bo = new byte[100];
        String[] cmd = {"bash", "-c", "echo $PPID"};
        Process p;
        try {
            p = Runtime.getRuntime().exec(cmd);
        } catch (IOException e) {
            //ignored. We might be invoking this on a Window platform. Therefore if an error occurs
            //we simply ignore the error.
            return;
        }

        try {
            int bytes = p.getInputStream().read(bo);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

        String pid = new String(bo);


Java - Generacja zmiennej losowej

Oczywiście można skorzystać z narzędzie Common Lang w stylu RandomUtils, jednak zaciekawiło mnie wykorzystanie bazowego mechanizmu Java.

import java.util.UUID;
....
String uuId = UUID.randomUUID().toString();

Java - Detekcja lokalnego adresu IP

Warto skorzystać z java.net.InetAddress
Przykład wykorzystania znalazłem analizując kod WSO Carbon. Jest on wykorzystany do wygenerowania identyfikatora serwera.

InetAddress addr;
String ipAddr;
String hostName;
try {
addr = InetAddress.getLocalHost();
ipAddr = addr.getHostAddress();
hostName = addr.getHostName();
} catch (UnknownHostException e) {
ipAddr = "localhost";
hostName = "127.0.0.1";
}