Optimalizace aplikací Java/EE

Podobné dokumenty
Semináˇr Java X J2EE Semináˇr Java X p.1/23

Úvod. Petr Aubrecht (CA) Martin Ptáček (Wincor Nixdorf) Je 10 typů lidí: ti, kteří znají binární kód, a ti, kteří ne.

Tvorba podnikových aplikací v jazyce JAVA. Josef Pavlíček KII PEF CZU

Architektury informačních systémů

Architektury informačních systémů

PA165: Úvod do Java EE. Petr Adámek

Vzdálená správa v cloudu až pro 250 počítačů

Tvorba informačních systémů

(Enterprise) JavaBeans. Lekce 7

Tvorba informačních systémů

Vývoj moderních technologií při vyhledávání. Patrik Plachý SEFIRA spol. s.r.o.

Platformy / technologie. Jaroslav Žáček

vlastnosti Výsledkem sledování je: a) Využití aplikací b) Používání internetu c) Vytížení počítačů d) Operační systém e) Sledování tisků

Testování Java EE aplikací Petr Adámek

PLATFORMY / TECHNOLOGIE JAROSLAV ŽÁČEK

Aplikace je program určený pro uživatele. Aplikaci je možné rozdělit na části:

Uživatelský manuál. Aplikace GraphViewer. Vytvořil: Viktor Dlouhý

Sísyfos Systém evidence činností

Analýza výkonu HELIOS Green

Platforma J2EE. Lukáš Zapletal liberix.cz. Platforma Java 2 Enterprise Edition

Optimalizaci aplikací. Ing. Martin Pavlica

Úvod do problematiky vývoje Vývoj informačních systémů

MATLABLINK - VZDÁLENÉ OVLÁDÁNÍ A MONITOROVÁNÍ TECHNOLOGICKÝCH PROCESŮ

1. Webové služby. K čemu slouží? 2. RPC Web Service. 3. SOA Web Service. 4. RESTful Web services

GTL GENERATOR NÁSTROJ PRO GENEROVÁNÍ OBJEKTŮ OBJEKTY PRO INFORMATICA POWERCENTER. váš partner na cestě od dat k informacím

Tvorba informačních systémů

Zátěžové testy aplikací

Tvorba informačních systémů

Databázové a informační systémy

Michal Krátký, Miroslav Beneš

Porovnání rychlosti mapového serveru GeoServer při přístupu k různým datovým skladům

Vývoj řízený testy Test Driven Development

Replikace je proces kopírování a udržování databázových objektů, které tvoří distribuovaný databázový systém. Změny aplikované na jednu část jsou

Návrh softwarových systémů - architektura softwarových systémů

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

C# - Databáze úvod, ADO.NET. Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí

TÉMATICKÝ OKRUH Softwarové inženýrství

Vlákno (anglicky: thread) v informatice označuje vlákno výpočtu neboli samostatný výpočetní tok, tedy posloupnost po sobě jdoucích operací.

Architektura rodiny operačních systémů Windows NT Mgr. Josef Horálek

Aplikace. vliv na to, jakou mají strukturu i na to, jak pracné je je vyvinout. Bylo vypozorováno, že aplikace je možné rozdělit do skupin

Komponentový návrh SW

Úvod. Klíčové vlastnosti. Jednoduchá obsluha

Tovek Server. Tovek Server nabízí následující základní a servisní funkce: Bezpečnost Statistiky Locale

Specifikace. Odevzdání do

Technology Entry form Entry up-to-date? Internal links Faulty internal Possible internal links

Požadavky pro výběrová řízení TerraBus ESB/G2x

TÉMATICKÝ OKRUH Softwarové inženýrství

Microsoft SharePoint Portal Server Zvýšená týmová produktivita a úspora času při správě dokumentů ve společnosti Makro Cash & Carry ČR

O Apache Derby detailněji. Hynek Mlnařík

Platformy / technologie. Jaroslav Žáček jaroslav.zacek@osu.cz

INSTALACE PRODUKTU ONTOPIA KNOWLEDGE SUITE

VYSOKÁ ŠKOLA BÁŇSKÁ TECHNICKÁ UNIVERZITA OSTRAVA FAKULTA STROJNÍ DATABÁZOVÉ SYSTÉMY ARCHITEKTURA DATABÁZOVÝCH SYSTÉMŮ. Ing. Lukáš OTTE, Ph.D.

1. Distribuce Javy. 2. Vlastnosti J2EE aplikace. 3. Fyzická architektura J2EE aplikace. Distribuce Javy se liší podle jejího zamýšleného použití:

Matematika v programovacích

Současný svět Projekt č. CZ.2.17/3.1.00/32038, podpořený Evropským sociálním fondem v rámci Operačního programu Praha adaptabilita

Business Intelligence

Formy komunikace s knihovnami

ČESKÉ VYSOKÉ UČENÍ TECHNIKÉ Fakulta elektrotechnická. Microsoft Sharepoint 2007 Workflows Průmyslové informační systémy

PRODUKTY Tovek Server 6

Nástroje a frameworky pro automatizovaný vývoj. Jaroslav Žáček jaroslav.zacek@osu.cz

Relační DB struktury sloužící k optimalizaci dotazů - indexy, clustery, indexem organizované tabulky

Technologie Java. Jaroslav Žáček

Přidělování CPU Mgr. Josef Horálek

Tvorba informačních systémů na platformě J2EE Petr Hetmánek Masarykova Univerzita, Fakulta Informatiky, Botanická 68a, Brno

Vize. Thang Do. Adam Papoušek.

INFORMAČNÍ SYSTÉM VIDIUM A VYUŽITÍ MODERNÍCH TECHNOLOGIÍ

Technologie Java Enterprise Edition. Přemek Brada, KIV ZČU

PRODUKTY. Tovek Tools

SOAP & REST služby. Rozdíly, architektury, použití

Vývoj informačních systémů. Přehled témat a úkolů

MBI - technologická realizace modelu

Implementace dávkových operací

CA AppLogic platforma typu cloud pro podnikové aplikace

Studie webů automobilek

Softwarové komponenty a Internet

Vzdělávací obsah vyučovacího předmětu

ZÁKLADY PROGRAMOVÁNÍ. Mgr. Vladislav BEDNÁŘ /14

VZDĚLÁVACÍ OBLAST INFORMAČNÍ A KOMUNIKAČNÍ TECHNOLOGIE VYUČOVACÍ PŘEDMĚT: INFORMAČNÍ A KOMUNIKAČNÍ TECHNOLOGIE. Charakteristika vyučovacího předmětu:

1 Uživatelská dokumentace

Obsah. Zpracoval:

Common Object Request Broker Architecture

SQL Server Data Tools (SSDT) RNDr. David Gešvindr MVP: Azure MCSE: Data Platform MCSD: Windows Store

Systém elektronického rádce v životních situacích portálu

Servlety a JSP. Petr Adámek, petr.adamek@ibacz.eu

1 Webový server, instalace PHP a MySQL 13

7. Enterprise Search Pokročilé funkce vyhledávání v rámci firemních datových zdrojů

Dijkstrův algoritmus

Programování II. Třídy a objekty (objektová orientovanost) 2018/19

1. Webový server, instalace PHP a MySQL 13

Elektronická podpora výuky předmětu Komprese dat

CYCLOPE PRINT MANAGEMENT SOFTWARE- UŽIVATELSKÁ PŘÍRUČKA

INOVACE PŘEDMĚTŮ ICT. MODUL 11: PROGRAMOVÁNÍ WEBOVÝCH APLIKLACÍ Metodika

Internet Information Services (IIS) 6.0

Metodika analýzy. Příloha č. 1

Load Balancer. RNDr. Václav Petříček. Lukáš Hlůže Václav Nidrle Přemysl Volf Stanislav Živný

X33EJA Web Services. Martin Ptáček, KOMIX s.r.o.

Prezentace CRMplus. Téma: CRMplus jako nástroj pro kontrolu a vyhodnocení rozpracovanosti dílů na zakázkách

Systémová administrace portálu Liferay

Obsah přednášky. Představení webu ASP.NET frameworky Relační databáze Objektově-relační mapování Entity framework

Transkript:

MASARYKOVA UNIVERZITA FAKULTA INFORMATIKY Optimalizace aplikací Java/EE Diplomová práce Bc. Martin Vala Brno, 2014

Prohlášení Prohlašuji, že tato práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj. Bc. Martin Vala Vedoucí práce: Ing. Mgr. et Mgr. Zdeněk Říha, Ph.D.

Poděkování Děkuji svému vedoucímu práce Ing. Mgr. et Mgr. Zdeňku Říhovi, Ph.D. za rady a připomínky, které mi pomohly při tvorbě práce. Děkuji také společnosti SeaComp s.r.o. za možnost zpracovat dané téma a za cenné konzultace. V neposlední řadě děkuji své rodině a blízkým za podporu při studiu a psaní práce.

Shrnutí Cílem této diplomové práce je zmapovat možnosti hledání a optimalizace problémových častí aplikace na platformě Java EE. Tyto poznatky poté aplikovat na systémy používané v reálném prostředí. V praktické části práce byly vytvořeny dvě aplikace. První aplikace je modelem reálné logistické aplikace, která byla použita pro zhodnocení migrace na novější aplikační servery. Druhá aplikace analyzuje vazby mezi entitami.

Klíčová slova optimalizace, Java EE, profilování, aplikační server, testování výkonu

Obsah 1 Úvod... 1 2 Aplikace na platformě Java EE... 3 2.1 Aplikační model... 3 2.1.1 Klientská vrstva... 5 2.1.2 Webová vrstva... 6 2.1.3 Aplikační vrstva... 7 2.1.4 Integrační vrstva... 7 2.2 Aplikační servery... 7 2.2.1 JBoss AS (WildFly)... 8 2.2.2 Glassfish... 9 3 Výkon Java EE aplikací... 10 3.1 Definice výkonu aplikací... 11 3.1.1 Odezva pro koncového uživatele... 11 3.1.2 Propustnost požadavků... 11 3.1.3 Využití zdrojů... 12 3.1.4 Dostupnost aplikace... 14 3.1.5 SLA... 14 3.2 Aplikační výkonnostní management... 14 3.2.1 APM ve fázi návrhu... 15 3.2.2 APM ve fázi vývoje... 16 3.2.3 APM ve fázi kontroly kvality... 16 3.2.4 APM v předprodukci... 17 3.2.5 APM v produkci... 17 3.3 Základní důvody problémů s výkonem aplikací... 18 3.3.1 Rozdělení aplikace do vrstev... 18 3.3.2 Špatné plánování kapacity systému... 19 3.3.3 Aplikační rámce a pomocné aplikace... 19 3.3.4 Flexibilita Javy... 19

3.4 Měření výkonu... 20 3.4.1 Získávání aplikačních metrik... 21 3.4.2 Získávání metrik aplikačního serveru... 22 3.4.3 Získávání metrik JVM... 22 3.4.4 Interpretace dat... 24 3.4.5 Agregace dat... 25 3.5 Profilování... 25 3.5.1 Profilování paměti... 26 3.5.2 Profilování kódu... 26 3.5.3 Profilování pokrytí... 27 3.5.4 VisualVM... 27 3.5.5 JProfiler... 30 4 Využití optimalizačních technik v praxi... 34 4.1 Porovnání aplikačních serverů na logistické aplikaci... 34 4.1.1 Popis modelu skladové aplikace... 35 4.1.2 Porovnání aplikačních serverů pomocí skladové aplikace... 36 4.1.3 Zhodnocení aplikačních serverů... 40 4.2 Aplikace pro analýzu vazeb mezi entitami v JPA... 40 4.2.1 Java Persistance API a vazby mezi entitami... 40 4.2.2 Implementace aplikace a výstup... 42 4.2.3 Zhodnocení aplikace na analýzu vazeb... 44 5 Závěr... 45 6 Použitá literatura... 47 7 Přílohy... 49

1 Úvod Mnoho aplikací se v poslední době potýká s problémy s výkonem, což je dáno hlavně rostoucí složitostí moderních systémů. Požadavky na výkon jsou stále stejné, ale složitost dnešních aplikací se se staršími nedá vůbec srovnat. Některé vývojářské firmy nedostatečně testují výkon svých systémů před vydáním a zátěžové testy dost často vynechávají úplně. Tyto aplikace v reálném prostředí pravidelně selhávají a nesplňují očekávání a požadavky zákazníka. Oprava takového problému u systému, který je už v produkci, je nesrovnatelně náročnější, než při odhalení stejného problému v dřívějších fázích vývoje. Proto je důležité se při vývoji složitých aplikací soustředit také na výkon při velké zátěži. Problémy s výkonem se nevyhýbají ani vývoji na platformě Java Enterprise Edition. Specifické pro aplikace na této platformě je, že jsou rozděleny do vrstev a každá vrstva může běžet na jiném stroji. Pokud se objeví problém s výkonem, je potřeba zanalyzovat všechny vrstvy a nejdříve najít, ve které se problém nachází. U větších aplikací poté musí nastoupit specialista na danou vrstvu a pokusit se problém vyřešit. Tento postup je velice časově náročný, a proto je vhodná prevence a dostatečné výkonnostní testování. I problémy v hotových aplikacích se ale dají řešit. Existuje slušné množství profilovacích nástrojů, které v těchto případech mohou pomoci odhalit spoustu problémů, jak u aplikací ve vývoji, tak u těch v produkci. Při optimalizaci platí pravidlo, že dvacet procent úsilí dokáže vyřešit osmdesát procent problémů, takže použití profilovacího nástroje na odhalení chyb a následná optimalizace může každé aplikaci pomoci. Cílem této diplomové práce je zmapovat možnosti hledání a optimalizace problémových částí aplikací na platformě Java EE. Tyto poznatky poté aplikovat na reálné problémy systémů používaných ve firmě SeaComp s.r.o., která diplomovou práci zaštiťuje. V kapitole 2 Aplikace na platformě Java EE popisuji fungování a technologie používané při vývoji aplikací na této platformě. Jsou zde popsány všechny jejich vrstvy, fungování a používané technologie. Poslední část kapitoly je věnována aplikačním serverům. V kapitole 3 Výkon Java EE aplikací se zabývám teorií problémů s výkonem a jejich možným řešením. Jsou zde popsána nejčastější problémová místa aplikací, u kterých je 1

potřebná zvýšená pozornost při vývoji. Na konci se práce zabývá měřením výkonu a jsou zde i ukázky použití profilovacích nástrojů. V kapitole 4 Využití optimalizačních technik v praxi využiji načerpané poznatky k vytvoření dvou aplikací, které by měly pomoci řešit reálné problémy firemních systémů. V první části je vytvořena jednoduchá skladová aplikace, na které je zhodnocena možnost migrace na novější servery. Ve druhé části je vytvořena aplikace, která analyzuje vazby mezi entitami a ceny jejich načítání. 2

2 Aplikace na platformě Java EE Java 2 Enteprise Edition (J2EE) je platforma, která byla navrhnuta, aby zjednodušila vývoj velkých distribuovaných aplikací. Programátor se může více soustředit na části, které jsou specifické pro jeho projekt, jelikož J2EE dodává dostatečnou množinu API 1, které zkracují čas vývoje, snižují komplexitu systému a zlepšují výkon. Vývojář se tedy nemusí zabývat obecnými problémy, které je potřeba řešit v každé aplikaci [1]. Java EE aplikace jsou vyvíjeny jako množina spolupracujících komponent, které by měly být na sobě co nejméně závislé a znovupoužitelné. Pokud máme takovéto komponenty, je snadné je měnit a přizpůsobovat jejich chovaní [2]. Od verze Java EE 6 se zjednodušuje programovací model, jelikož komponenty už není potřeba konfigurovat pomocí XML 2, ale stačí jednoduše přidat anotaci přímo do zdrojového kódu vedle elementu, který anotace ovlivňuje. Java EE server poté nakonfiguruje komponenty při nasazení a běhu programu [3]. Dalším zjednodušením je Dependency Injection, které umožňuje automatické vkládání referencí na ostatní potřebné komponenty nebo zdroje pomocí anotací. Dependency Injection se dá aplikovat na všechny zdroje, které komponenta potřebuje a úspěšně skrývá vytváření a vyhledávaní těchto komponent z kódu aplikace. 2.1 Aplikační model Základem Java EE aplikačního modelu je programovací jazyk Java a Java Virtual Machine 3, kteří společně poskytují portabilitu, bezpečnost a jednoduchou programovatelnost. Java EE je navržena pro podporu aplikací, které implementují podnikové služby pro zákazníky, zaměstnance, dodavatele, partnery a ostatní, kteří spolupracují s podnikem. Takové aplikace jsou komplexní, přistupují k datům z více zdrojů a distribuují funkcionalitu různým klientům [1]. Proto Java EE platforma používá pro podnikové aplikace vícevrstvý aplikační model. Aplikační logika je rozdělena do komponent podle funkcí a tyto aplikační komponenty jsou instalovány na různých strojích podle vrstvy, do které komponenta patří. Java EE 1 Application Programming Interface specifikuje, jak spolu mají komunikovat jednotlivé softwarové komponenty. 2 Extensible Markup Language 3 JVM virtuální stroj, který dokáže spouštět Java bytecode tzv. mezikód. 3

aplikace se skládají ze tří, nebo čtyř vrstev, podle toho jaké použijeme dělení (Obrázek 1). Dělení podle komponent: Integrační vrstva (Enterprise Information System Tier) Aplikační vrstva (Business Tier) Webová vrstva (Web Tier) Klientská vrstva (Client Tier) Dělení podle stroje, na kterém komponenta běží: Databázový server Aplikační server Počítač klienta Dělení podle vrstvy: Perzistence dat Aplikační logika Prezentační vrstva Obrázek 1. Java EE vícevrstvá aplikace [2]. 4

Při dělení podle komponent může mít aplikace tři nebo čtyři vrstvy, jelikož prezentační vrstva může mít buď obě komponenty, tedy klientskou i webovou vrstvu, nebo jen jednu z nich. 2.1.1 Klientská vrstva Klientská vrstva je spouštěna na počítači klienta a komunikuje přímo s ostatními vrstvami běžícími na aplikačním serveru. Pro lepší pochopení klientské vrstvy a komunikace mezi vrstvami je vhodný obrázek 2. 2.1.1.1 Webový klient Webový klient je takzvaným tenkým klientem, který je spouštěn na počítači uživatele. Tenký klient nezadává dotazy do databáze ani nevykonává složité aplikační pravidla. Při použití tenkého klienta jsou tyto složité a náročné operace delegovány do aplikační vrstvy, která běží na serveru. Webový klient se skládá ze dvou částí. Z webových stránek, které obsahují různé druhy značkovacích jazyků jako HTML 4 nebo XML. A z webového prohlížeče, který zobrazuje webové stránky, které obdržel ze serveru. Webové stránky mohou také obsahovat applety. Applet je malá klientská aplikace, napsaná v programovacím jazyce Java, která se spouští v JVM nainstalovaném ve webovém prohlížeči. 2.1.1.2 Aplikační klient Aplikační klient je také spouštěn na počítači uživatele a poskytuje mu bohatší možnosti, než mohou nabídnout značkovací jazyky. Aplikační klient obvykle poskytuje grafické uživatelské prostředí (GUI), vytvořené například pomocí API Swing. Existují také klienti bez grafického uživatelského prostředí, kteří jsou ovládáni pomocí příkazové řádky. Aplikační klient má přímý přístup k aplikační logice, která běží na aplikačním serveru. Tito klienti nemusí být napsáni jen v programovacím jazyce Java, ale i aplikace napsané v jiných jazycích mohou s aplikačním serverem komunikovat [1]. 4 HyperText Markup Language 5

Obrázek 2. Komunikace mezi vrstvami v Java EE aplikaci [1]. 2.1.2 Webová vrstva Webové komponenty jsou buď servlety, nebo webové stránky vytvořené pomocí technologií Java Server Faces, nebo Java Server Pages. Servlety jsou třídy napsané v jazyku Java, které dynamicky zpracovávají požadavky a vytvářejí odpovědi. JSP stránky jsou textové dokumenty, které se spouštějí jako servlety, ale dovolují přirozenější přístup k vytváření statického obsahu. JSF technologie je postavena na servletech a JSP, a poskytuje uživatelské prostředí pro webové aplikace. Statické HTML stránky a applety jsou spojeny s webovými komponentami při nasazování aplikace, ale nejsou považovány za komponenty webové vrstvy z pohledu Java EE specifikace. 6

2.1.3 Aplikační vrstva V aplikační vrstvě se nachází business logika aplikace, která řeší požadavky dané podnikové domény, jako například bankovnictví, prodej, nebo finance. Požadavky jsou zpracovávány v komponentách zvaných Enterprise Bean, které běží na serveru v aplikační vrstvě. Možné jsou tyto komponenty i ve vrstvě webové. Enterprise Bean je, zjednodušeně, třída napsaná v jazyce Java, která běží na aplikačním serveru a řeší určitou část business logiky. Aplikační vrstva přijímá data z klientské a webové vrstvy, zpracuje je a posílá do integrační vrstvy, kde se data ukládají. Také data z integrační vrstvy získává, zpracovává a posílá zpátky do klientské, nebo webové vrstvy [1]. 2.1.4 Integrační vrstva V integrační vrstvě se nacházejí databázové systémy, kde se ukládají veškerá data, které aplikace potřebuje. Mohou se zde nacházet také takzvané legacy systems, což může být například předchozí systém, na kterém je nová aplikace postavena a je stále potřebný, nebo jakýkoliv jiný systém, který je potřebný k běhu. K integrační vrstvě přistupuje jen vrstva aplikační, která zde ukládá data, nebo si odtud data bere. O tento přístup se stará JDBC. Java Database Connectivity je API v Javě, která zajišťuje přístup do různých databází. JDBC je orientován na relační databáze, a proto je pro vývoj jednodušší použít nějaký Object-relational mapping (Objektově relační mapování, ORM) nástroj, který implementuje rozhraní Java Persistence API (například Hibernate, TopLink, EclipseLink), který se stará o mapování objektů do relační databáze [2]. Samozřejmě využití ORM nástroje způsobuje jistou režii, a proto je důležité se správně rozhodnout, jestli využít ORM, nebo jestli použít jen JDBC. 2.2 Aplikační servery Aplikační server je prostředí, kde mohou běžet Java EE aplikace. Server se skládá z různých kontejnerů, kde každý poskytuje jiné služby. Můžeme například mít servletový kontejner, který zajišťuje uživatelské prostředí, Enterprise JavaBean kontejner, 7

který zajišťuje business logiku, nebo JNDI 5 kontejner, který zajišťuje vyhledávání jednotlivých služeb [4]. Aplikační servery můžeme dělit následovně [2]: Plnohodnotné open source o JBoss (WildFly) o Glassfish Open source pouze se servlet kontejnerem o Tomcat o Jetty Placené o WebSphere (IBM) o WebLogic (Oracle, dříve BEA) Nejvíce se tato práce zaměřuje na systémy na aplikačním serveru JBoss, který je ještě s dalším populárním open source serverem Glassfish představen v další části. Ostatní servery jsou zde uvedeny jen pro přehled. 2.2.1 JBoss AS (WildFly) Od verze 5 je aplikační server JBoss vyvíjen pod společností Red Hat, která JBoss koupila v roce 2006. Jedná se o plnohodnotný aplikační server, který je stavebním kamenem balíčku technologíí společnosti Red Hat, jenž se nazývá JBoss Enterprise Middleware Suite (JEMS). Všechny ostatní JEMS produkty fungují s aplikačním serverem JBoss a mnoho z nich může fungovat i bez něj v Java SE aplikacích. Součástí tohoto balíčku je například již zmiňovaný ORM nástroj Hibernate. JBoss zůstává i nadále open source, což ale vůbec nesnižuje jeho hodnotu a je schopný konkurovat i komerčním řešením. Jelikož je ale JBoss dostupný zdarma, jeho popularita se nedá změřit stejně jako u komerčního softwaru, tedy počtem prodaných licencí. Dotazníkové studie jako například ta od BZ Research 6 z roku 2005 ale ukazují, že JBoss se v této době dělil s WebSphere od IBM o prvenství v popularitě a server WebLogic je až za nimi. 5 Java Naming and Directory Interface pomáhá vyhledávat zdroje pomocí jména. 6 http://www.bzmedia.com/bzresearch/ 8

Takže fakt, že JBoss zůstává nadále open source, má spíše výhody. Každý programátor, který se rozhodne, že by chtěl JBoss zkusit, ho může stáhnout, nainstalovat, spustit a nasadit na něj aplikaci za méně než deset minut. Vše bez toho, aby si musel dělat starosti s licencí. Vývojový proces serveru je navíc naprosto transparentní a každý ho může vidět. Pokud někdo chce a má dostatečné schopnosti, tak může dokonce i vypomoct například nahlašováním bugů, opravováním chyb, nebo i vývojem. Další výhodou je, že kolem populárních open source produktů se srocují velké komunity a tedy většina bugů je nalezena a opravena mnohem dříve, než u ostatních produktů [5]. Nedávno byl aplikační server JBoss přejmenován na WildFly, který začíná své číslování od osmé verze, jelikož JBoss skončil na verzi sedmé. S aplikačním serverem WildFly 8.0.0 se lépe seznámíme v praktické části této práce. 2.2.2 Glassfish Projekt Glassfish začal v roce 2005, pod firmou Sun, která v té době vyvíjela také programovací jazyk Java. První verze vyšla rok poté a podporovala Java EE verze 5 a přispěla k její popularitě. Jedná se o populární open source aplikační server, který je teď podporován firmou Oracle a je už ve čtvrté verzi, která podporuje Java EE verze 7. Jeho popularita pramení také z toho, že nová verze je vždy vydána záhy po vydání nové verze Javy, takže nedočkaví programátoři si vždy mohou s tímto serverem zkusit nové funkce [6]. Rozdílem oproti serveru JBoss je například využití nástroje TopLink, jako standardního ORM poskytovatele, ale samozřejmě není problém na server nainstalovat jiný ORM nástroj. Se serverem GlassFish 4.0 se lépe seznámíme v praktické části této práce. 9

3 Výkon Java EE aplikací Mnoho firem má problémy s výkonem u svých Java aplikací i v dnešní době, kdy se na výkon hledí mnohem více, než dříve. Steven Haines, velice zkušený programátor zabývající se výkonem Javových aplikací, ve své publikaci [7] udává, že v roce 2005 mělo více než 80 % firem významné výkonnostní problémy se svými systémy v jazyce Java. Požadavky na výkon aplikace jsou definované v tzv. service level agreement (SLA). SLA udávají přesné údaje o tom, jak dlouho by mělo trvat zpracovat nějakou jednotku práce a velké množství aplikací těchto hodnot nedosahuje. Špatný výkon má dopad na produktivitu, zákazníkovu důvěru a příjem. Když má aplikace špatnou dobu odezvy, zákazník platí své zaměstnance za čekání na odpověď programu a tím ztrácí produktivitu zaměstnanců. Tento problém musí být také opraven vývojářem, jenž ztrácí čas, který by mohl věnovat něčemu jinému, například vývoji nových funkcí [8]. Je naprosto přirozené, že zákazník ztrácí důvěru ve firmu, která nedokáže splnit své sliby ohledně výkonu aplikace, což může vést k tomu, že na další důležitý projekt si raději vybere někoho jiného. Toto negativně ovlivňuje příjem firmy a může vést až k existenčním problémům. Symptomy výkonnostních problémů mohou být: Pomalu běžící aplikace Úniky paměti, které zpomalují výkon aplikace Velké úniky paměti, které způsobují pády aplikace Zamrzávající aplikace Aplikace, které mají problémy při velké zátěži Problémy, které se objevují na systému v produkci, ale nemohou být reprodukovány v testovacím prostředí Aplikace, které postupně zpomalují 10

3.1 Definice výkonu aplikací Z pohledu Java EE aplikací a aplikačních serverů jsou nejpoužívanější výkonnostní metriky odezva pro koncového uživatele, propustnost požadavků, využití zdrojů a dostupnost. Všechny tyto metriky jsou důležité pro definici výkonu jako takového. 3.1.1 Odezva pro koncového uživatele Tato metrika definuje, jak dlouho uživatel musí čekat na jeho požadavek, tedy poukazuje na uživatelův celkový dojem z aplikace, a proto je ze všech ostatních nejvíce na očích. Pomalá odezva má za následek celkovou nespokojenost zákazníka. Malé množství dlouhých odezev je horší, než více kratších. Nejvíce výrazné jsou odezvy, které jsou delší než 90 % všech ostatních. Odezva se dá měřit dvěma způsoby, aktivně a pasivně. Aktivně pomocí syntetických transakcí, které posílají požadavky na naše aplikační prostředí v daném čase a měří se odezva těchto požadavků. Výhodou aktivního měření je, že se dá použít i předtím, než špatná odezva ovlivní našeho uživatele, tedy předtím, než je produkt nasazen. Pasivní monitoring na druhou stranu sleduje požadavky, které se objevují na produktu nasazeném v reálném prostředí, a proto takto dostáváme přesnější data o uživatelově chování. Bohužel problémy s výkonem v tomto případě řešíme až po nasazení aplikace, což může mít negativní dopad na zákazníka. 3.1.2 Propustnost požadavků Propustnost ukazuje, kolik věcí stihne aplikace zpracovat v nějakém časovém úseku. V oblasti Java EE definujeme propustnost požadavků jako počet požadavků, které je aplikace schopna zvládnout za jednu sekundu. Vysoký počet zpracovaných požadavků poukazuje na to, že rychle a efektivně zpracováváme požadavky, což se kladně odráží na odezvě. 11

3.1.3 Využití zdrojů Zdroje podporují, nebo ulehčují práci aplikace a jejich využití je další důležitou metrikou výkonu. Mezi zdroje patří: Halda Zásobníky vláken Zásobníky JDBC připojení Vyrovnávací paměti Zásobníky bezstavových komponent (Stateless Bean) JMS servery Zásobníky JCA 7 připojení Zdroj, který je vhodné analyzovat jako první je halda. Zajímá nás využívání haldy a chování garbage collectoru. Jelikož celá aplikace běží v haldě, její špatná konfigurace může mít za následek špatný výkon bez ohledu na to, jak dobře je aplikace napsána a jak dobře je nakonfigurován aplikační server. Automatická správa paměti je jedna z funkcí, která láká programátory do vývoje aplikací v Javě. Správa paměti je zjednodušena tak zvaným garbage collectorem, který sám hledá dereferencované objekty a maže je z paměti. Tato funkce je v jednom momentě zároveň požehnáním i prokletím. Na jednu stranu eliminuje úniky paměti známé například z jazyka C++. Na druhou stranu není možné použít manuální správu paměti, protože garbage collector je jediný mechanismus na její správu. Proto je vhodné věnovat dostatek času jeho konfiguraci. Když aplikační server obdrží požadavek od uživatele, vloží ho do fronty požadavků. Tato fronta je udržována zásobníkem vláken, který odebere požadavek z fronty a zpracuje ho. Využití a výkon zásobníku může mít velký vliv na celkový výkon aplikace. Pokud je využití zásobníku malé, tak zbytečně využíváme prostředky serveru, které by mohly být použity jinde. Na druhou stranu pokud je využití 7 Java EE Connector Architecture 12

zásobníku nad 85 %, docházejí nám volná vlákna pro zpracování požadavků a tyto požadavky musejí čekat ve frontě, což snižuje propustnost celé aplikace. Většina aplikací potřebuje ke své práci databázi. Všechny interakce s databází jsou řízeny přes zásobník spojení. Každý požadavek musí nejdříve obdržet spojení s databází ze zásobníku, aby mohl provést svůj dotaz do databáze. Pokud zásobník nemá žádná volná spojení, musí požadavek čekat, což snižuje celkovou dobu odezvy uživatelského požadavku. Vyrovnávací paměť slouží ke snížení počtu volání do databáze. Načtení dat z vyrovnávací paměti je mnohem rychlejší, než volání do databáze, ale vyrovnávací paměť má omezenou velikost, a proto špatná konfigurace může způsobit pády aplikace. V Java EE jsou objekty odebírány z vyrovnávací paměti a vkládány do databáze v procesu zvaném pasivace. Nové požadavky jsou ukládány do mezipaměti v procesu zvaném aktivace. Využití mezipaměti a poměry aktivace a pasivace mohou ovlivnit výkon. Bezstavové komponenty jsou udržovány v zásobnících. Pokud proces potřebuje zdroj, vyžádá si ho ze zásobníku, použije a vrátí zpátky. Tyto zásobníky způsobují problémy s výkonem hlavně, když jsou příliš malé. Důležité je využít na správu zásobníku co nejméně paměti a přitom udržovat dostatečné množství zdrojů k obsloužení všech požadavků. Pokud není v zásobníku dostatek zdrojů, má to za následek rapidní snížení výkonu. Aplikace, které potřebují komunikovat s legacy systémem, nebo používat asynchronní zpracování, tak činí pomocí JMS (Java Message Service) serverů. V JMS serveru je fronta, přes kterou jsou zprávy zpracovávány a velikost této fronty se dá nakonfigurovat. Pokud je JMS server plný, tak do fronty nejdou přidat žádné další zprávy, což má za následek buď ztrátu celého požadavku, nebo zpomalení, protože program zkouší zprávu posílat tak dlouho, dokud neuspěje. Zásobníky JCA spojení jsou podobné JDBC zásobníkům s rozdílem, že pomocí JCA nekomunikujeme s databází, ale s jakýmkoliv systémem, který podporuje JCA. Často se používá na komunikaci s legacy systémy. Pro aplikace, které JCA používá, je správná konfigurace velice důležitá [7]. 13

3.1.4 Dostupnost aplikace Dostupnost se měří podle toho, jestli je aplikace dostupná vždy, když je to nutné, což by mělo být definováno ve SLA v podobě procentuální hodnoty dostupnosti. Pokud aplikace není dostupná a porušuje hodnoty dané ve SLA, zákazník může většinou vymáhat nějaké dohodnuté finanční sankce. 3.1.5 SLA Jak bylo řečeno výše, požadavky na výkon aplikace by měly být obsaženy v service level agreement. Tyto požadavky by měly být dobře zváženy všemi klíčovými osobnostmi projektu a je nutná důsledná analýza. Hlavní osobnosti, které se na SLA musejí podílet, jsou aplikační obchodní specialista a technický specialista. Pokud bychom vynechali obchodního specialistu, tak by uživatelovy požadavky nemusely být splněny a pokud bychom vynechali technického specialistu, mohli bychom dostat požadavky, které není možné technicky splnit. Dobře napsané SLA musejí být specifické, flexibilní a realistické. Specifické musejí být proto, abychom mohli při testování zjistit, jestli aplikace tyto hodnoty splňuje. Například není vhodné uvádět, že musí zvládnutí požadavku trvat okolo pěti vteřin, protože tato hodnota není přesná. Flexibilita znamená, že daný požadavek musí obsahovat procentuální hodnotu, kdy může aplikace porušit dané hodnoty ve SLA, protože vždy mohou nastat nějaké neočekávané situace. Například nemusí být považováno za problém, pokud jsou SLA pro daný požadavek porušeny jednou z třiceti případů. Realističnost daných SLA je důležitá a je důvodem, proč u sepisování dohody o SLA musejí být obchodní i technický specialista. Pokud vývojáři dostanou neproveditelné požadavky na výkon aplikace, tak je prostě ignorují a jsme ve stejné situaci, jako bychom žádné neměli [7]. 3.2 Aplikační výkonnostní management Aplikační výkonnostní management (Application Performance Management, dále jen APM) je metoda, která zajišťuje výkon aplikace ve všech fázích a cyklech vývoje a nasazení. APM začíná při návrhu, je aplikován při vývoji, je odzkoušen při testování a zůstává, i když je aplikace již v produkci. 14

Důvodem proč se s APM musí začínat již ve fázi návrhu je, že opravení chyby v rámci počáteční fáze vývoje je nepopsatelně levnější, než v pokročilejších fázích, kdy cena opravy roste exponenciálně (Obrázek 3). Například pokud objevíme chybné rozhodnutí ve fázi návrhu, dokumentace může být změněna za několik hodin. Pokud stejnou chybu objevíme ve fázi vývoje, musíme ještě navíc udělat změny v kódu. Pokud se ale chyba najde až ve fázi testování, musí být řešení znovu navrhnuto, naimplementováno a otestováno. Nejhorší je samozřejmě, když se chyba najde až v produkci, protože to může navíc špatně ovlivnit náš vztah se zákazníkem. Obrázek 3. Závislost mezi cenou opravení problému a fází vývoje [7]. 3.2.1 APM ve fázi návrhu Jelikož je důležité objevit problémy s výkonem co nejdříve, měl by návrh systému určitě zohledňovat výkon aplikace, ne-li na něm být založen. Často se stává, že softwarový architekti opomínají výkon ve svých návrzích, i když by bylo vhodné, kdyby všechny návrhy případů užití obsahovaly předem domluvené SLA, což ale vyžaduje další námahu architekta. Diskuze o SLA nemůže být provedena pouze se zákazníkem, ale také s technickým poradcem, kterému zákazník důvěřuje, protože jinak by mohl mít nereálné výkonnostní požadavky na některé prvky aplikace. Takovým nereálným požadavkem může například být, že doba odezvy některého prvku musí být pod jednu vteřinu, i když technický specialista ví, že pod dvě vteřiny není možné něco podobného provést. 15

3.2.2 APM ve fázi vývoje Při vývoji větších aplikací je každá komponenta vytvořena jiným týmem, nebo osobou. Například jeden tým implementuje persistentní vrstvu, jiný tým aplikační vrstvu a jiný prezentační vrstvu. Důležité je aby si každý programátor zodpovědně otestoval všechny podkomponenty, na kterých pracuje pomocí jednotkových testů. Typické jednotkové testy se soustřeďují jen na funkcionalitu a zanedbávají dva důležité aspekty výkonu aplikace: využívání paměti a efektivitu algoritmů. Abychom se vyhnuli problémům s výkonem, vývojáři musejí dobře otestovat využívání paměti a hledat objekty, které zbytečně setrvávají v paměti, nebo cyklí. Efektivita algoritmů se dá zjistit pomocí profilovacích nástrojů, které zanalyzují výpočetní čas řádek po řádku a umožňují tak programátorovi najít problémové části jeho kódu. Dalším důležitým nástrojem při testování výkonu je pomůcka, která ukazuje jak velká a která část kódu je procházena v průběhu testu, jelikož se těžko najde slabé místo v aplikaci, pokud přes něj nikdy neprojde žádný test. Pokud spojujeme dobře otestované komponenty do jednoho celku a objeví se nějaký problém, víme, že tento problém způsobilo spojení částí a ne jednotlivé komponenty, což nám zjednoduší fázi hledání problému. Kdybychom stavěli auto, také bychom chtěli mít jistotu, že veškeré součástky fungují a až potom bychom tyto součástky spojovaly dohromady. Při vývoji auta nám tento postup přijde naprosto přirozený, ale bohužel při vytváření softwaru tyto návyky dost často chybí [7]. 3.2.3 APM ve fázi kontroly kvality Po tom co byly všechny komponenty řádně otestovány a spojeny dohromady, nastupuje tým kontroly kvality (Quality Assurance, dále jen QA), aby zjistil, jestli celá aplikace funguje, jak má. V kontextu APM, nestačí aby QA tým otestoval jen správnou funkcionalitu, ale musí také otestovat, jestli je dodržován dostatečný výkon, který byl definován ve SLA. Pokud při testování nějakého případu užití program funguje správně, ale nesplňuje nároky definované ve SLA, pak QA test nemůže projít a celá část se musí vrátit k vývojářskému týmu. K problému s výkonem by se mělo přistupovat stejně jako ke každé jiné chybě v programu, tedy buď je potřeba změnit jen implementaci, nebo dokonce celý návrh problémové části. Pokud necháme testování výkonu aplikace úplně nakonec fáze kontroly kvality, kdy je už celá hotová, zvyšujeme cenu oprav těchto problémů. A pokud jsme při celém vývoji nevěnovali pozornost výkonu, je pravděpodobné, že v této fázi najdeme závažné 16

problémy, které mohou mít za následek i nutnost kompletního předělání nějaké vrstvy a většiny komponentů, které s ní komunikují. Po otestování jednotlivých částí podle definovaných SLA je důležité otestovat celou aplikaci pod zátěží, kterou očekáváme v produkci, na což se často zapomíná a má za následek, že aplikace, která skvěle fungovala pro pár uživatelů při testování, najednou absolutně vyhoří po pár hodinách v produkci. Při velké zátěži bývají největší problémy s neefektivností algoritmů a špatnou prací s pamětí. Tyto problémy se neukáží při jednotkovém testování, jelikož pro nás není problém, pokud relace pro jednoho uživatele zabírá 1 MB paměti. Ale když máme najednou připojených tisíc uživatelů, potom už musíme uchovávat 1 GB, což může vést k pádům nebo zamrzání aplikace. 3.2.4 APM v předprodukci Před nasazením aplikace do produkce by se mělo provést stanovení kapacity. I když jsou splněny SLA při dané zátěži, měli bychom vědět, při jaké zátěži aplikace začne ztrácet rychlost a poruší dané SLA. Pokud jsou definované SLA pro tisíc uživatelů, dosahujeme těchto hodnot jen těsně a přidání dalších deseti uživatelů způsobí dosažení kapacitního stropu, měli bychom se dále zabývat zlepšením výkonu, protože je pravděpodobné, že aplikace v produkci neuspěje. Pokud máme stanovenou kapacitu systému, víme, pod jakou zátěži začneme porušovat dané SLA a kdy aplikace spadne úplně. Tyto informace pomohou při rozhodování, jestli investovat do rychlejšího hardwaru, nebo jestli jsme spokojení s nynějším výkonem. 3.2.5 APM v produkci Když se aplikace dostane do produkce, je potřeba monitorovat uživatele, abychom se ujistili, že se chová, tak jak jsme předpokládali při testování. Pokud jsme testovali výkon při jiných průchodech aplikace, než jaké uživatel opravdu používá, pak se musejí zopakovat zátěžové testy s novými uživatelskými případy užití, které opravdu imitují uživatelské chování. Je těžké dopředu přesně odhadnout, jak bude uživatel aplikaci používat, ale dobrá analýza uživatelského chování je důležitá a zvýší přesnost odhadů. Například se může stát, že budeme předpokládat, že uživatel se pokaždé před zavřením browseru odhlásí z naší internetové stránky. Toto v produkci způsobí nepříjemné úniky paměti, protože většina uživatelů se z internetových stránek 17

neodhlašuje, ale jen zavře browser. Uživatelská relace poté může zůstat v paměti několik hodin, než je tato paměť uvolněna pro další uživatele. Dále musíme v produkci sledovat, jestli aplikace správně využívá zdroje a sledovat odezvu pro koncového uživatele. Je důležité zjistit, jestli jsou uživatelé spokojeni při používání aplikace, tak jak jsme si představovali před nasazením do produkce. Dalším důležitým aspektem v produkci je ukládat si záznamy o užívání, které můžeme využít k odhadu směřování aplikace v budoucnu [7]. 3.3 Základní důvody problémů s výkonem aplikací Jedním z důvodů problémů moderních aplikací s výkonem je rychlá evoluce. Požadavky na rychlost aplikace jsou pořád stejné, ale rychle roste jejich složitost. Například rozdíl mezi rychlostí Windows 3.1 a Windows 7 není až tak znatelný, ale složitost těchto operačních systémů se nedá vůbec srovnat. Při zvyšování složitosti je vždy mnohem těžší odhalit výkonnostní problémy [8]. 3.3.1 Rozdělení aplikace do vrstev Rozdělení Java EE aplikací do vrstev, může způsobovat problémy při hledání problému s výkonem. Tyto aplikace jsou nasazeny na aplikačním serveru, na kterém běží JVM v operačním systému na fyzickém počítači. V nejjednodušší formě běží všechny tyto komponenty na jednom stroji, čemuž se říká vertikální složitost. Mnohem horší na hledání problémů s výkonem a také mnohem častější varianta je ale horizontální složitost, kde aplikace běží v distribuovaném prostředí. Když se zjistí problém s výkonem, musí se hledat ve všech vrstvách na všech strojích, což je skoro nemožné jen pro jednoho specialistu. Proto pro vyhledání problému v takovýchto rozsáhlých systémech je potřeba tým zkušených specialistů [7]. Vrstvou, ve které jsou často problémy, je ta databázová. Špatná optimalizace SQL dotazů a indexů v databázi zpomaluje výkon objemných aplikací, které často dotazují databázovou vrstvu. Při nevhodném přístupu k datům, může také docházet k zamykání některých tabulek nebo řádků v databázi. Problém mohou dělat také externí nebo legacy systémy, které s naší aplikací komunikují. Dlouhé čekání na odpověď externího systému může mít za následek dominový efekt a pád celé aplikace. Řešením může být zavedení časových limitů, které v případě neobdržení odpovědi z externího systému v nějakém časovém 18

intervalu ohlásí chybu. Důležité je také správně odhadnout a naplánovat, jak na dosažení limitu správně zareagovat [9]. 3.3.2 Špatné plánování kapacity systému Problémy s výkonem aplikace mohou začít už ve fázi návrhu. Špatné, nebo dokonce žádné, plánování kapacity systému (capacity planning), může mít za důsledek, že hotová aplikace nezvládá nápor uživatelů v produkci. Proto by se vždy ve fázi návrhu mělo odhadnout, kolik souběžných uživatelů bude k systému přistupovat a podle toho přizpůsobit návrh aplikace, databázi, hardware, na kterém by systém měl běžet a zátěžové testy [9]. 3.3.3 Aplikační rámce a pomocné aplikace Problém může být v implementaci zavedených aplikačních rámců (application framework) jako je například Spring 8. Používání těchto rámců zjednodušuje a zrychluje vývoj aplikace, ale může také způsobit problémy. Většina vývojářů, kteří je využívají, vědí přesně, jak je používat, ale nevědí, jak fungují vnitřně, což vytváří tzv. černou skřínku, do které vložíme nějaký vstup, ona provede nějakou funkcionalitu a vrátí nám výstup, ale my pořádně nevíme, co provedla. Tímto vlastně v aplikaci vzniká další vrstva, kterou musíme analyzovat, když nastane problém a pokud opravdu zjistíme, že náš problém je v používaném aplikačním rámci, musíme ho buď sami opravit, což vyžaduje jeho dobrou znalost, nebo musíme požádat poskytovatele o opravení chyby, což muže trvat i měsíce. Vývojářská prostředí a pomůcky mohou psaní aplikace ovlivnit podobně jako aplikační rámce. Na jednu stranu nám urychlují a zjednodušují práci, ale na druhou zase člověk většinou nerozumí tomu, co se děje pod pokličkou a tyto nástroje mohou nabídnout nevhodná řešení pro naše nynější potřeby [7]. 3.3.4 Flexibilita Javy Java EE je velice flexibilní platforma vhodná jak pro vývoj malých nenáročných aplikací, tak větších podnikových aplikací. Velká flexibilita může způsobit, že se vyvine systém, který funguje skvěle při testování, ale doslova se rozpadne při velké zátěži. Toto může být způsobeno i tím, že se Java v poslední době stává velice 8 http://spring.io/ 19

populární platformou a spousta programátorů, přechází na Javu z jiných jazyků, ze kterých si přináší špatné návyky. Proto by v každém úspěšném týmu měl vždy být nějaký zkušený Java vývojář. 3.4 Měření výkonu Ke správnému a užitečnému měření výkonu potřebujeme prvně získat data o výkonu aplikace a tato data poté správně interpretovat. Získání dat je technickou částí, ke které potřebujeme dobrou znalost aplikace a aplikačního serveru, zatímco ke správné interpretaci dat potřebujeme hlavně zkušenosti s analýzou výkonu, nebo detailní instrukce. Nestačí ale získat data jen o naší aplikaci, jelikož potřebujeme znát informace o celé infrastruktuře, která je s aplikací spojena, protože Java EE aplikace jsou vícevrstvé. Potřebujeme tedy získat následující informace z těchto vrstev: Aplikace doba odezvy služby, počet volání služby, doba odezvy na úrovni tříd a na úrovni metod, počet volání tříd a metod, alokace a dealokace objektů a další Aplikační server metriky zásobníku vláken, metriky zásobníku databázových spojení, metriky zásobníku JCA spojení, metriky zásobníku enterprise bean, metriky JMS serveru a transakční metriky JVM využití paměti a metriky garbage collectoru Operační systém využití procesoru, využití fyzické paměti, I/O metriky a síťové metriky Aplikační metriky prezentují specifické výkonnostní charakteristiky aplikace, které můžeme využít na zjištění slabých míst aplikace i externích zdrojů. Sledováním doby odezvy metody, která jde mimo JVM, například volání JDBC, které vykonává SQL dotaz na databázi, můžeme zjistit, jestli jde o problém v aplikačním kódu, nebo v externím zdroji. Navíc monitorováním doby odezvy a počtu volání můžeme lépe porozumět chování uživatele. Aplikační server obsahuje listener, který přijímá příchozí požadavky a frontu, která řadí požadavky ke zpracování. Obsahuje jeden, nebo více zásobníků vláken, které vyjmou požadavek z fronty a zpracují ho. Dále obsahuje zásobník spojení, který se používá na spojení s externími systémy nebo na služby zpráv. Další důležitou částí je 20

správce transakcí, který zajišťuje spolehlivost aplikace. Z hlediska výkonu jsou důležité všechny tyto části. Získání informací o JVM je důležité, jelikož aplikace běží na aplikačním serveru, který běží na JVM. Takže každý problém s JVM ovlivní aplikační server a to ovlivní naši aplikaci. Důležité je zaměřit se na správu paměti a garbage collector. Pokud garbage collector uklízí velké množství objektů, tak zastaví všechny ostatní procesy v JVM, což má za následek zamrznutí aplikačního serveru i naší aplikace. Proto je důležité věnovat JVM čas. Nakonec je důležité sbírat informace z operačního systému. Vytížení procesoru nám ukazuje, kolik práce provádí aplikační server. Využití fyzické paměti nám ukazuje, kolik paměti JVM spotřebovává mimo svoji haldu. Monitorováním sítě můžeme zjistit, jestli jsou naše komunikační algoritmy efektivní. Každá část je důležitá a může nám ukázat, kde se nacházejí problémy s výkonem [7]. 3.4.1 Získávání aplikačních metrik Nejužitečnější informace o aplikaci získáváme pomocí instrumentace kódu, jako informace o počtu volání metod, době odezvy metod a vytváření a mazání objektů. Pokročilejší implementace nesledují tyto informace jen pro jednotlivé metody, ale sledují celou dráhu volání požadavku. Toto nám umožňuje vidět celou dráhu požadavku a odhalit, které části nejvíce ovlivňují dobu odezvy. Některé implementace dokonce ukládají i argumenty metod, což pomáhá například při zjišťování problému u JDBC volání, protože víme, jaký SQL dotaz způsoboval problémy. Instrumentace kódu, má dvě formy: vlastní a automatickou. Vlastní instrumentace kódu, je vložení kódu, který monitoruje výkon aplikace vývojářem. Výhodou je, že získáváme jen data, která nás zajímají a navíc ve formátu, který si sami zvolíme. Pří automatické instrumentaci, vkládá monitorovací kód do aplikace nějaký nástroj. Výhody automatické instrumentace jsou následující: Kód aplikace zůstane nezměněn, takže zůstane stejně dobře čitelný. Nástroj dokáže monitorovat celou aplikaci, což by vkládáním vlastního kódu bylo náročné a zdlouhavé u větších aplikací. V nástroji se dá nastavit, jaké množství dat si přejeme monitorovat, což by jinak vyžadovalo změny v kódu. 21

Tyto nástroje vkládají monitorování do byte-kódu a ne do Java kódu, takže monitorování je lépe optimalizované. Informace jsou shromažďovány a udržovány v centrálním repozitáři. Většina nástrojů poskytuje intuitivní uživatelské rozhraní, se kterým je analýza výsledků jednodušší. 3.4.2 Získávání metrik aplikačního serveru V dnešní době už není získání dat takový problém, protože většina výrobců aplikačních serverů umožňuje zobrazovat informace o monitorování aplikace pomocí Java Management Extension (JMX). JMX používá objekty zvané MBeany (Managed Beans), k získání dat o běhu aplikace. Tyto MBeany musejí být zaregistrovány na MBean Serveru, který funguje jako správce všech MBean. K připojení k MBean serveru používáme JMX konektory, například přímo v JDK můžeme použít JConsole, nebo u aplikačních serverů JMX konzoli [10]. 3.4.3 Získávání metrik JVM Jednotlivé JVM prezentují informace o výkonu různými způsoby. Například velká část aplikačních serverů, jako například JBoss, poskytují tyto informace přes již zmiňovaný JMX. Nejdůležitější metriky z hlediska výkonu jsou tyto: Využití haldy potřebujeme znát stávající velikost, maximální velikost a další dostupné informace Četnost garbage collectoru zjišťujeme, jak často garbage collector běží Trvání garbage collectoru potřebujeme vědět, jak dlouho garbage collectoru trvá dokončit práci Efektivita garbage collectoru zjišťujeme, jestli byl garbage collector schopný získat dostatečné množství paměti Otálející objekty potřebujeme vědět, jestli procesy zanechávají v paměti nějaké objekty, které už nepotřebujeme 22

Cyklické objekty zjišťujeme, jestli jsou nějaké objekty vytvářeny a mazány příliš často a zbytečně Některé informace jsou zjistitelné bez většího zatížení aplikace jako využití haldy, ale velice náročné je nalezení otálejících a cyklických objektů. Získání informací o garbage collectoru jsou středně náročné a pohybuje se kolem pěti procent režie navíc. Otálející objekty v paměti zanechává nějaký požadavek, který je před svým ukončením nedereferencuje. Podobné chování může být chtěné, jako například potřeba udržovat v paměti, uživatelovo přihlášení k systému, nebo nechtěné, například když se v paměti udržuje celá tabulka databáze, která už není potřeba. Toto garbage collector odhalit nemůže a musíme se o správnou správu starat my [7]. Cyklické objekty jsou pravým opakem. Žádný objekt udržován dlouho v paměti není a všechny jsou při požadavku vytvořeny znovu a před koncem požadavku jsou zničeny. Když se toto opakuje příliš často, zahlcujeme JVM, která ztrácí volnou paměť, což často spouští garbage collector a zpomaluje celou aplikaci. V extrémních případech to může způsobit i obyčejný for cyklus, jako v ukázce kódu 1. for (Object object : objects) { Integer threshold = system.getthreshold(); if (object.getthing() > threshold) { // Do something } } Ukázka kódu 1. Nevhodný for cyklus. V tomto případě nastane problém, pokud máme velké množství objektů, například několik set tisíc, nebo kdybychom měli zanořených více takovýchto iterací v sobě. Při každé iteraci totiž alokujeme a mažeme proměnnou threshold. Pokud bychom se na tento příklad podívali pomocí profilovacího nástroje, viděli bychom několik set tisíc instancí, které jsou vytvářeny a hned zase mazány. Jednoduchou změnou snížíme dopad této iterace na výkon aplikace z velkého na minimální, viz ukázka kódu 2. 23

int threshold = system.getthreshold().intvalue(); for (Object object : objects) { if (object.getthing() > threshold) { // Do something } } Ukázka kódu 2. Oprava nevhodného for cyklu. 3.4.4 Interpretace dat I když máme přístup k datům o výkonu aplikace, neznamená to ještě, že máme lepší znalosti. Až správná interpretace dat nám tyto znalosti může poskytnout. Ke správné interpretaci musíme nadefinovat model, který reprezentuje prostředí naší Java EE aplikace. Potřebujeme měřit tři různé kategorie metrik: Doba odezvy Propustnost aplikace Využití zdrojů Obrázek 4. Ukazatele při zvýšení zátěže aplikace [7]. 24

Na obrázku číslo 4, můžeme vidět jak se ukazatele využití zdrojů, propustnosti aplikace a doby odezvy mění v závislosti na počtu uživatelů. Využití zdrojů se zvyšuje při zvyšování zátěže, protože systém musí zvládnout více práce. Více uživatelů potřebuje více paměti a silnější procesor. Zvyšování zátěže je přirozené, ale systém nakonec dojde do bodu, kdy jsou zdroje nasyceny. Když se systém snaží zpracovat více požadavků, než může zvládnout, procesor stráví více času přepínáním mezi vlákny, než zpracováváním požadavků. Propustnost se také zvyšuje při zvyšování zátěže, protože více uživatelů nutí systém více pracovat. Ale při výše zmiňovaném nasycení začne propustnost klesat, protože procesor stráví více řízením sebe sama. Doba odezvy také pomalu roste se zvyšováním zátěže systému. Problém ale nastává, když se po nasycení zdrojů zátěž stále zvyšuje, protože potom začne doba odezvy růst exponenciálně. 3.4.5 Agregace dat Někdy není lehké se v získaných datech orientovat, například když se snažíme zanalyzovat požadavek, který byl za třicet minut volán až tisíckrát. V této situaci není moc efektivní zkoumat každé volání zvlášť, a tak je dobré data rozdělit do menších částí a agregovat. Pro každou část spočítáme počet volání a nejmenší, největší a průměrnou dobu odezvy. Pokud máme data takto zpracována, je mnohem jednodušší se v nich orientovat a odhalit problémy [7]. 3.5 Profilování Profilování je forma dynamické analýzy programu, která může měřit například náročnost programu na paměť, časovou náročnost programu nebo četnost a průběh volání funkcí. Jak už bylo řečeno, nejvhodnější fází k profilování je fáze vývoje programu, přesněji jednotkové testování, protože si chceme být jistí, že při skládání komponent dohromady budou všechny části splňovat požadavky na výkon aplikace [8]. Nejpoužívanějším aplikačním rámcem pro jednotkové testování je open source JUnit 9. Tento Framework podporuje vytváření jednotkových testů při vývoji komponentů a 9 http://junit.org/ 25

validování funkcionality každé komponenty. Existují i vývojová paradigmata, kde se testy píší před vývojem jednotlivých komponent, jelikož to zlepšuje pochopení používání komponent před implementací. JUnit se soustřeďuje hlavně na testování funkcionality, ale jeho odnože obsahují také testování výkonu a škálovatelnosti. Výkonnostním testováním zjišťujeme doby odezvy a testováním škálovatelnosti zjišťujeme, jak se aplikace chová pod větší zátěží. Pomocí jednotkového testování výkonu bychom měli dosáhnout následujícího [7]: Identifikovat problémy s pamětí Identifikovat pomalé metody a algoritmy Změřit, jestli jednotkové testy pokrývají většinu kódu 3.5.1 Profilování paměti Nebezpečné a těžko zjistitelné problémy s pamětí v Java aplikacích jsou úniky paměti. Nejlepší cestou, jak se zbavit úniků, je zanalyzovat komponenty profilováním paměti. Paměťový profilovací nástroj vytvoří snímek haldy, potom spustíme náš jednotkový test a po dokončení testu nástroj vytvoří další snímek haldy. Po této proceduře nástroj zobrazí všechny objekty, které v haldě zůstaly. Analýzou rozdílu obou snímků najdeme objekty, které test nechal v paměti. U každého se musíme rozhodnout, jestli je žádoucí, aby tam objekt zůstával, nebo jestli se jedná o chybu. Pomocí paměťových profilovacích nástrojů je také možné odhalit další nebezpečný problém Java aplikací s pamětí a to cyklické objekty. Takovýto objekt se nám zobrazí jako stejný objekt, který se mnohokrát vytvoří a zase uvolní z paměti. Většinou takové chování žádoucí není a jednoduchou změnou kódu se ho dokážeme zbavit. 3.5.2 Profilování kódu Profilování kódu nám umožňuje zjistit výkon metod a algoritmů tím, že nám najde nejvíce procházené sekce kódu a sekce, u kterých provádění kódu trvá nejdéle. Tím nám odhalí důležité body, u kterých se můžeme pokusit a optimalizaci. Profilování kódu by mělo být spouštěno s jednotkovými testy, protože ty by měly odrážet jednotlivé akce uživatele. 26

3.5.3 Profilování pokrytí Profilování pokrytí ukazuje kolik procent tříd, metod a řádek kódu bylo použito při testu. Zjištění pokrytí je důležité při odhadování efektivity jednotkových testů. Pokud výsledky profilování paměti a kódu jsou dobré, ale profilování pokrytí ukazuje jen 20 % kódu, potom nemůžeme mít důvěru v náš program, ani v naše testy a musíme je rozšířit [7]. 3.5.4 VisualVM VisualVM je open source monitorovací a profilovací nástroj, který je součástí Java Development Kit balíku od verze 6, nebo je dostupná ke stažení samostatně z internetových stránek visualvm.java.net. Jedná se o jednoduchý, nenáročný a přehledný nástroj, který se nejčastěji používá na zjišťování problému s hotovou aplikací, jelikož profilování JUnit testů není dobře integrováno [11]. Po spuštění aplikace se zobrazí přehledný panel, který ukazuje všechny Java aplikace, které v současnosti běží na lokálních i vzdálených JVM. Po výběru aplikace se zobrazí záložky, ve kterých si uživatel může vybrat oblast, která ho zajímá. V záložkách je na výběr Overview, Monitor, Threads, Sampler a Profiler. V Overview jsou zobrazeny základní informace o aplikaci jako hlavní třída aplikace a její argumenty, verze Javy nebo systémové a JVM argumenty. V záložce Monitor jsou čtyři přehledné grafy (obrázek 5). První ukazuje využití procesoru a aktivitu garbage collectoru. Druhý ukazuje velikost haldy a její využití. Třetí graf zobrazuje statistiku načtených tříd a čtvrtý ukazuje statistiku aktivních vláken. Pro lepší přehled jednotlivých grafů se dají ostatní schovat. Z tohoto pohledu je možné spustit garbage collector nebo vytvořit snímek haldy, ve kterém můžeme prohledávat veškeré instance, které v době pořízení snímku byly v haldě. Důležité je i zobrazení referencí u každé instance, protože tak můžeme zjistit, co drží tuto instanci v paměti. Tento přístup by byl vhodný u obrázku číslo 5, jelikož nám v malém čase nebezpečně roste halda aplikace a potřebujeme zjistit, které objekty nám zůstávají v paměti a zamezit tomu. 27

Obrázek 5. Monitorovací grafy ve VisualVM. V záložce Threads jsou přehledně ukázána všechna vlákna aplikace na časové ose. Každé vlákno má barvu podle toho, jestli běží, čeká, spí, nebo je monitorováno. Tento pohled je vhodný na odhalení vláken, která jsou z nějakého důvodu zablokovaná. Je možné vytvořit i snímek vláken, který se dá prozkoumat později. Záložky Sampler a Profiler ukazují stejné informace. Rozdíl mezi profilováním a samplováním je, že samplování je méně náročné na výpočetní čas a nezatěžuje tolik aplikaci, jelikož nevkládá nic do bytekódu tříd, ale vytváří snímky vláken, které pak analyzuje. V těchto záložkách máme na výběr, jestli budeme profilovat procesor, nebo paměť. Při profilování procesoru vidíme všechny metody, které aplikace provádí a důležité informace o nich, jako jak dlouho se metoda prováděla, kolikrát byla zavolána, nebo kolik z celkového času běhu metoda zabrala. Takto můžeme jednoduše odhalit metody, které zabírají příliš mnoho času, viz obrázek číslo 6. 28

Obrázek 6. CPU profilování ve VisualVM. Na tomto obrázku můžeme vidět na první pohled podezřelou metodu getorderbyid(long) z třídy OrderManagerImpl, která zabírá 50 % celého výpočetního času a přitom je volána nejméně krát ze všech metod ostatních náročných metod. Taková jednoduchá metoda, která zabírá velké množství výpočetního času, je podezřelá a měla by být prozkoumána a změněna. Při profilování paměti nástroj přehledně ukazuje všechny objekty alokované v paměti právě v daném momentě. Objekty jsou seřazeny podle toho, kolik zabírají bajtů. Další zajímavý zobrazený údaj je počet objektů každé třídy nacházejících se v paměti. Na obrázku číslo 7 můžeme vidět ukázku profilování paměti. Zde jsou na první pohled podezřelé instance třídy OrderDto. Zabírají nám přes 20 % paměti a máme přes 200 tisíc instancí. S touto třídou budou nejspíše souviset i velká čísla u třídy Long, jelikož OrderDto obsahuje atributy této třídy a velká čísla u pole objektů. Pokud nevíme, kde se podezřelé objekty vytvářejí, můžeme vytvořit snímek haldy a prozkoumat ho, nebo zkusit profilování kódu, které nám ukáže, jaké metody se volají. 29

Obrázek 7. Profilování paměti ve VisualVM. Velice šikovná funkce je možnost filtrovat jak profilování procesoru, tak paměti podle Java balíků. Tak dostaneme informace jen o zvolených metodách a zvolených objektech, ale na druhou stranu můžeme přehlédnout důležitá data. 3.5.5 JProfiler JProfiler je komerční profilovací nástroj vyvíjen Německou společností ej-technologies. Pomocí JProfileru je možné profilovat aplikace na lokálních JVM i vzdálených aplikačních serverech. Nabízí podobné možnosti profilování jako nekomerční řešení, ale obsahuje spoustu výhod a zlepšení, pro zjednodušení práce a lepší profilování aplikací. Výhodou pro uživatele vývojového prostředí Eclipse je dobrá integrace v tomto prostředí, která se dá nastavit už při instalaci. JProfiler je možné používat ve zkušební verzi po dobu deseti dní [12]. Po spuštění aplikace nabízí Quick Start menu, ve kterém je na výběr například profilování lokální JVM, aplikačního serveru, nebo aplikací na vzdálených serverech. Pro začínající uživatele je vhodné vybrat možnost demo, ve které jsou tři ukázkové aplikace, na kterých si může uživatel vyzkoušet jednotlivé funkce. Tato část je dobře zpracovaná a uživatel má možnost spustit úniky paměti, nebo podobné problémy a vidět, jak se to projeví na monitorování. 30

Po vybrání aplikace, kterou chceme monitorovat, zobrazí JProfiler ještě přehledné nastavení profilování, kde se zobrazuje, jakou režii vybrané nastavení způsobí. Zde lze vybrat, jestli chceme aplikaci profilovat, nebo samplovat. Je zde také nastavení filtrů, kde je možné vybrat jen ty Java balíky, které nás zajímají a tím snížit režii. Nastavení se zobrazí také poté, co spustíme profilování z prostředí Eclipse, kde se po nainstalování pluginu zobrazí možnost spuštění aplikace, nebo testu v profilovacím módu, který spustí JProfiler. Poté už můžeme přistoupit k samotnému profilování. Jako první menu je zobrazeno profilování paměti, kde první záložka ukazuje alokované objekty v paměti podobně jako VisualVM. Nápomocné jsou ale i ostatní záložky, které má v této kategorii JProfiler navíc. Například strom alokací zobrazí strom metod, které vytvářejí objekty, které nám ukázal přehled objektů v paměti. V tomto stromu je pak lehké najít jednotlivé metody, které zahlcují paměť (Obrázek 8). Obrázek 8. Strom alokací v aplikaci JProfiler. Menu profilování paměti nabízí také více možností zobrazení, která zjednodušují hledání problému. Například lze zobrazit metody ve stromě stejně jako u alokací, nebo je zde zajímavá možnost prohlédnout si graf volání problémové funkce. Na obrázku 9 můžeme vidět graf volání problémové metody getorderbyid, kterou jsme odhalili při profilování procesoru. Volání jsou zobrazena v kolonkách a jsou obarvena podle toho, kolik výpočetního času spotřebují. Takto máme možnost jednoduše zjistit, které volání naší metody zabírá nejvíce času a optimalizovat ho. Zde například vidíme, že nejvíce času zabere třídění kolekce a hned druhé nejnáročnější je přidání prvku do kolekce. 31

Obrázek 9. Graf volání v aplikaci JProfiler. Následují menu, která známe z aplikace VisualVM jako ukazatel vytížení haldy, aktivita garbage collectoru, zátěž procesoru, přehled vláken, přehled tříd a další. Samozřejmě je zde také možnost vytvořit snímek haldy. Vláknům je zde také věnován celý pohled, ale v JProfileru je čistší a nezobrazuje tolik, pro nás, nedůležitých vláken. Dále je zde navíc pohled ukazující zamknutí vláken. V databázovém menu nám aplikace dává možnost profilovat volání do databází. V JDBC záložce můžeme vidět všechny důležité informace o připojeních k databázi, jako všechna připojení na časové ose a jejich akce, čas vytvoření a zavření připojení, nebo všechny dotazy do databází seřazené podle výpočetního času. Tento pohled je důležitý pro hledání problému s databází, můžeme zde zkontrolovat, jestli zavíráme všechny JDBC připojení k databázi nebo jestli jsou naše dotazy do databáze optimální. 32

Obrázek 10. Profilování JDBC dotazů do databáze v aplikaci JProfiler. Poslední záložka nám dává možnost získat více informací o Java EE aplikacích, například o servletech, JNDI volání, JMS komunikaci, nebo RMI volání. Celkově jde na první pohled vidět, že je JProfiler placenou aplikací a tedy se s ním mohou open source aplikace jen těžko srovnávat. VisualVM je dobrá a jednoduchá aplikace pro počáteční profilování, ale pro ty kteří to myslí s profilováním vážně je vhodné zaplatit si JProfiler, který více ulehčuje práci a nabízí mnoho užitečných pohledů, které vnesou do optimalizačních problémů nové světlo. 33