Sajnos fejlesztés közben viszonylag kevés figyelmet fordítunk arra, hogy könnyen üzemeltethető alkalmazásokat készítsünk. Pedig a Java technológia lehetőséget biztosít, csak kicsit jobban oda kell figyelnünk, kicsit jobban ki kell használni az eszközöket és az API-kat.
Hogy erre felhívjam a figyelmet, 2009. szeptember 16-án a SZÁMALK Aktuális 2009 rendezvényén előadást tartottam "Hol a határ? - Java alkalmazások üzemeltetéséről fejlesztőknek és üzemeltetőknek" címmel.
Az előadás során végigvettem egy fejlesztési életciklust, valamint egy tipikus n-rétegű alkalmazás architektúrát, és elemeztem a fejlesztők és az üzemeltetők feladatait, valamint a lehetséges konfliktus forrásokat.
Konklúzióként levonható, hogy a technológia már nagyon jó eszközöket ad a kezünkbe, a probléma mindig emberi oldalon szokott jelentkezni.
Java szempontjából talán a következőket érdemes kiemelni:
- Vastag kliens esetén a telepítés és a frissítések kezelésére érdemes a Java Web Start technológiát használni, mely alapban a JRE része.
- Hasznos eszköz a JConsole, mely a JDK része, és a futó Java alkalmazásokhoz képes hozzákapcsolódni, és azok állapotát lekérdezni.
- Hasznos API a Java Management Extensions (JMX), mely használatával könnyen üzemeltethető alkalmazásokat tudunk készíteni.
A JMX a Java SE 5.0-tól a platform része, olyan szabványos programozói interfész (JSR 3), melyel monitorozható és menedzselhető alkalmazásokat tudunk készíteni. A JMX alapját egy vagy több Java objektum, un. managed bean (MBean) képviseli. Az MBean-eket az MBean szerverbe kell regisztrálni, hogy a kliensek el tudják érni. Egy MBean-nek lehetnek attribútumai, melyeket lehet írni és/vagy olvasni, lehetnek műveletek (operations), melyeket meg lehet hívni, valamint bizonyos értesítéseket küldhetnek. Ezáltal az MBean-eken keresztül megfigyelhető egy alkalmazás állapota, közbe lehet avatkozni, és bizonyos eseményekről is értesítést kaphat az üzemeltető. Az MBean-ek lokálisan, de távolról is elérhetőek (JSR 160, Java Management Extensions Remote API).
Amennyiben elindítunk egy Java programot, és elindítjuk a JConsole alkalmazást, információt kaphatunk a memóriafogyasztásról, futó szálakról, betöltött osztályokról, stb. Az utolsó, MBeans nevezetű fülön jelennek meg az MBean-ek. Látható, hogy minden konfiguráció nélkül is van pár MBean, melyek a JVM-ről adnak információkat (memóriahasználat, szemétgyűjtő, osztálybetöltő, operációs rendszer környezet, stb.), valamint a JVM működésébe lehet beavatkozni (pl. java.lang/Memory - gc művelet).
A legtöbb alkalmazásszerver menedzsmentje is a JMX-re épülnek. Ilyen a Tomcat is, mely szintén JMX-en biztosítja a monitorozást és a menedzsmentet. Ehhez a következőket kell a induláskor a Java-nak átadni:
JAVA_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=6969 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
Ezt akár beállíthatjuk a setenv.bat/sh állományban is. Ekkor amint csatlakozunk a JConsole-lal a Tomcat-et futtató JVM-hez, az MBeans fülön megjelenik a Catalina és a Users folder. Ezekben rengeteg MBean-t találhatunk. A Tomcat olyan szinten biztosít információkat, mint pl. egy servlet betöltési ideje, meghívásának száma, legkisebb és legnagyobb lefutási idő, összes idő, mennyit hibázott, stb (Catalina/Servlet folder). Nézzünk is egy példát, írjunk egy egyszerű webes alkalmazást, mely egy servlet-ből áll, mely egy számlálót növel minden egyes meghívásakor. Ezt szeretnénk kiajánlani JMX-en. A számlálóhoz készítsünk egy külön osztályt Counter néven.
public class Counter
implements CounterMBean {
private long value;
public long getValue() {
return value;
}
public void setValue(long value) {
this.value = value;
}
public void storno() {
value = 0;
}
synchronized public void incrementCounter() {
value++;
}
}Ennek incrementCounter metódusát hívja a szerver. Ahogy látható, implementálja a CounterMBean interfészt, melyen keresztül a JMX-en ki lesz ajánlva.
public interface CounterMBean {
public long getValue();
public void setValue(long counter);
public void storno();
}
Eztán már csak egy ServletContextListener-t kell implementálni, mely az induláskor regisztrálja az MBean-t, leálláskor meg megszünteti a regisztrációt.
public class InitServletListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
CounterMBean counter = new Counter();
mbs.registerMBean(counter, new ObjectName("jtechlog:type=Counter"));
sce.getServletContext().setAttribute("counter", counter);
} catch (Exception e) {
e.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent sce) {
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.unregisterMBean(new ObjectName("jtechlog:type=Counter"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
A web alkalmazást, majd a JConsole-t elindítva láthatjuk, hogy megjelent a jtechlog folder, és azon belül a Conter MBean. Lekérdezhetjük vagy beállíthatjuk a value értékét, vagy meghívhatjuk a storno műveletet.
Amenniben értesítést is szeretnénk kapni a számláló értékének változásáról, a NotificationBroadcasterSupport osztályból kell származtatni, implementálni kell a getNotificationInfo metódust, majd meghívni a sendNotification metódust.
...
synchronized public void incrementCounter() {
value++;
Notification n =
new AttributeChangeNotification(this,
sequenceNumber++,
System.currentTimeMillis(),
"Counter value has changed",
"Counter value",
"long",
value - 1,
value);
sendNotification(n);
}
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
String[] types = new String[]{
AttributeChangeNotification.ATTRIBUTE_CHANGE
};
String name = AttributeChangeNotification.class.getName();
String description = "An attribute of this MBean has changed";
MBeanNotificationInfo info =
new MBeanNotificationInfo(types, name, description);
return new MBeanNotificationInfo[]{info};
}
...
A legjobb, hogy ezeket az értékeket nem csak JConsole-ról tudjuk lekérdezni, hanem parancssorból is, a Tomcat Ant task-okat definiál erre. A következő build.xml részlettel lehet lekérni a számláló értékét.
<jmx:open
host="${jmx.server.name}"
port="${jmx.server.port}"/>
<jmx:get
name="jtechlog:type=Counter"
attribute="Value"
resultproperty="value"
echo="false"
/>
<echo message="${value}" />Ez azért nagyszerű, mert így bármilyen monitorozó vagy menedzsment eszközbe (pl. Munin, Nagios) könnyen be tudjuk kötni.

0 megjegyzés:
Megjegyzés küldése