2009. november 30., hétfő

StAX

Technológiák: JAXP 1.4, StAX 1.0

Ha már a web szolgáltatásokról volt szó, mely szorosan kapcsolódik az XML-hez, nézzük, hogy mi újítást hozott a JDK 6-ban bevezetett JAXP 1.4. A legnagyobb újdonság a StAX bevezetése, mely egy nagy teljesítményű stream alapú XML feldolgozó szűréssel (filter), mely támogatja a módosítást is.

A JAXP-ben már a W3C által definiált SAX és DOM feldolgozási modell régóta létezett. A SAX esetében esemény alapú feldolgozást lehet megvalósítani, ahol a feldolgozó (parser) hívja az osztályainkat (parser client). Ezt hívják un. push parser-nek, mikor a parser megy végig az XML-elen, és tolja nekünk az adatokat. Ezt viszonylag nehéz programozni, mert tárolni kell az állapotot, manuálisan kell pl. vermet kezelni, hogy tároljuk, hol tartunk a feldolgozásban. A DOM a teljes XML-t betölti egy faként a memóriába, melyen lehet fabejárást is végezni, sőt tetszőlegesen módosítható is. Ez könnyen használható, a fa adatszerkezetet is a legtöbben ismerik, viszont rengeteg memóriára van szüksége. Ennek feloldására a BEA kezdett el kidolgozni egy API-t, mely a JSR 173 specifikációban lett megfogalmazva, Streaming API for XML címmel.

Célja, hogy egyszerűbben programozható legyen, mint a SAX, de kevesebb memóriát fogyasszon, mint a DOM. Streaming API-nak nevezik, mert a parser XML dokumentumnak csak egy részét látja egyszerre. Itt jön képbe a consume (felemészt) fogalom is, ami azt jelenti, hogy a stream-en nem haladhatunk visszafele, így ha egyszer átment rajta a parser, akkor a stream beolvasásra került, tehát ha újra fel akarjuk dolgozni, valamilyen módon biztosítani kell a stream újra rendelkezésre állását (pl. klónozás). Ezen kívül a parser-t pull parser-nek nevezik, mert a kliens irányítja, ő kéri el az adatokat. Ennek több előnye is van, pl. egyszerre több dokumentumot is lehet párhuzamosan feldolgozni, akár összefésülni az eredményeket, valamint a szálat teljes kontroll alatt lehet tartani, ugyanis akkor szüneteltetjük a végrehajtást, mikor akarjuk. A library is kisebb lesz, és a kliens kód is kisebb lesz.

A StAX további előnye, hogy nem csak olvasni (pl. SAX) képes a dokumentumokat, hanem írni is képes azokat. A StAX alapvetően két API-val is rendelkezik, az egyik a cursor API, a másik az iterator API. E mögötti meggondolás az, hogy inkább két egyszerű API-t készítenek, mint egy bonyolultat. Az előbbihez az XMLStreamReader, és XMLStreamWriter osztályok tartoznak, míg a másodikhoz az XMLEventReader és XMLEventWriter osztályok.

Nézzük is a cursor API használatával hogyan dolgoznánk fel a W3Schools népszerű XML példáját, mely egy könyvkatalógust tartalmaz. Példa XML:

<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<!-- ... -->
</bookstore>
A kód, mely ezt feldolgozza cursor API használatával:
XMLInputFactory f = XMLInputFactory.newInstance();
XMLStreamReader r = f.createXMLStreamReader(CursorApi.class.getResourceAsStream("bookstore.xml"));
while (r.hasNext()) {            
if (r.getEventType().isStartElement()) {
System.out.println(r.getName());
if ("book".equals(r.getName().getLocalPart())) {
 System.out.println("Category: " + r.getAttributeValue(null, "category"));
}
else if ("title".equals(r.getName().getLocalPart())) {
 System.out.println("Title: " + r.getElementText());
}
}
r.next();
}

Látható, hogy először gyártatunk egy XMLInputFactory példányt, majd egy XMLStreamReader példányt. Amíg tart a feldolgozás, addig feldolgozzuk az adatokat, de mindig mi lépünk a következő adatra a next() metódus segítségével (pull API). Az adat típusa, melyen a reader éppen áll, az XML-nél megszokottak lehetnek: XML deklaráció, nyitó tag, záró tag, karakterek, megjegyzések, stb. Attól függően, hogy mi, hívhatjuk meg a reader többi metódusát. Pl. nyitó tag esetén lekérdezhető a getName-mel a neve, vagy getText-tel a tartalma, sőt a getAttribute* kezdetű metódusokkal az attribútumai is. A XMLStreamException kivételt kezelni kell.

Nézzük, hogyan írjunk ki egy hasonló XML dokumentumot:

XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLStreamWriter writer = output.createXMLStreamWriter(System.out);
writer.writeStartDocument();
writer.writeStartElement("bookstore");
writer.writeStartElement("book");
writer.writeAttribute("category", "COOKING");
writer.writeStartElement("title");
writer.writeCharacters("Everyday Italian");
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndElement();
writer.flush();

Nézzük az XML feldolgozást most az iterator API segítségével:

XMLInputFactory f = XMLInputFactory.newInstance();
XMLEventReader r = f.createXMLEventReader(CursorApi.class.getResourceAsStream("bookstore.xml"));
while (r.hasNext()) {
XMLEvent event = r.nextEvent();
if (event.isStartElement()) {
if (event instanceof StartElement) {
 StartElement element = (StartElement) event;
 System.out.println(element.getName());
 if ("book".equals(element.getName().getLocalPart())) {
  System.out.println("Category: " + element.getAttributeByName(new QName("category")));
 }
 else if ("title".equals(element.getName().getLocalPart())) {
  System.out.println("Title: " + r.getElementText());
 }
}
}
}

Itt látható, hogy nem közvetlenül a reader példányt szólítjuk meg, hanem az event példányt. Ezt aztán a megfelelő típusra kényszeríteni kell, és már el is érhetjük a megfelelő metódusait.

Ahhoz, hogy eldöntsük, hogy a kettő közül melyiket érdemes választani, érdemes a következőket a fejben tartani:

  • Az iterator API XMLEvent osztályai nem módosíthatóak, a parse-olás után is megőrzik az értéküket
  • Emiatt többlépéses (bővíthető, plug-in-elhető) feldolgozásokat is könnyebben ki lehet dolgozni ezen példányok továbbadásával
  • A fentiekből következik, hogy a cursor API kevesebb memóriát használ, és a példányosítások hiánya miatt gyorsabb is
  • Az XMLEvent interfészt akár magunk is implementálhatjuk, akár teljesen új eseményt hozhatunk létre, akár egy meglévőt egészíthetünk ki utility metódusokkal
  • Az iterator API esetén módosítani is lehet a stream-et

Összességében, ha nem a teljesítmény az elsődleges szempont, érdemes a magasabb szintű iterator API-t használni.

2009. november 23., hétfő

JAX-WS mélyvíz

Ezzel a címmel tartottam előadást a JUM XII. alkalmán, mely a ustream.tv-nek köszönhetően utólag is megnézhető, és a diák is letölthetőek.

Az előadás kapcsán beszéltem a JAXB és JAX-WS referencia implementációval éles projektben szerzett tapasztalatokról, melyeket itt is összefoglalnék. Megpróbálok általános tippeket is adni, melyet egy SOA bevezetés során figyelembe kell venni.

A web szolgáltatásokkal kapcsolatban az egyik legnagyobb félreértés az szokott lenni, hogy kizárólag a HTTP(S)/SOAP web szolgáltatásokat értjük alatta. Ez nincs teljesen így, a W3C definíciója szerint a web szolgáltatások hálózaton keresztüli gép-gép együttműködést támogató szoftverrendszerek. Ez elég sok mindenre ráillik. Igaz azonban, hogy a leggyakrabban használt kombináció tényleg a HTTP(S)/SOAP, ahol a HTTP(S) az átviteli (transzport) protokoll, a SOAP az üzenet formátum, de mindkettő lecserélhető, pl. JMS protokollra, vagy JSON üzenetformátumra.

Amennyiben nem saját rendszereink kommunikálnak, már a SOAP-pal kapcsolatban is sok mindenben meg kell egyezni a kommunikáló partnerrel, mely lehet a web szolgáltatást nyújtó, és a web szolgáltatást igénybe vevő fél is. Erről a Web szolgáltatásokkal kapcsolatos szabványok című előző post-omban írok. A WS-I-n kívül meg kell említeni a WS-Security (web szolgáltatások biztonsága), WS-Reliability (biztonságos pontosan egyszeri üzenetküldés web szolgáltatásokkal) és a WS-Transaction (tranzakciókezelés web szolgáltatásokkal, itt a kompenzáló tranzakciókat érdemes megjegyezni) szabványokat is.

Az implementáció lehet bottom up, mikor már létező kódunk próbáljuk web szolgáltáson keresztül is elérni, top down, mikor a WSDL-ből indulunk ki, és fejlesztjük mögé a funkcionalitást, és meet in the middle is, mikor a már létező funkciókat kell egy meghatározott interfészen keresztül kiajánlani - értelemszerűen ez a legbonyolultabb, hiszen nem feltétlenül ugyanaz az interfészben definiált struktúra, mint amit a rendszerünkben már kialakítottunk. Az utóbbi esetben különösen, de amúgy is érdemes nem az üzleti funkcióinkat közvetlenül kiajánlani web szolgáltatásokként, hanem egy külön web szolgáltatás réteget kialakítani. Ez segít nekünk az interfész és az üzleti logika elválasztásában, és az interfészek verziókezelése is egyszerűbb. Persze ebben az esetben számolnunk kell a két réteg közötti adatátvitel miatti többlet munkával (hasonlóan mint mikor az üzleti adatokat DTO-kba másoljuk).

Az XML API-k közül a következők érdekesek:

  • JAXP (1.0 – JSR 5, 1.1 és 1.2 JSR 63, 1.3 és 1.4 JSR 206): XML feldolgozásra, DOM és SAX technikákon kívül megjelent a StAX is (erről későbbi post-ban még írok), XML séma alapján történő validálásra, valamint transzformációra (XSLT), mely erősen épül az XPath-ra.
  • JAXB (JSR 222): Java objektumok és XML közötti megfeleltetésre (binding)
  • SAAJ (JSR 67 - Java APIs for XML Messaging része): SOAP üzenetek alacsony szintű, DOM faként történő kezelésére
  • JAX-RPC 1.1 (JSR 101): legacy/deprecated API, távoli eljáráshívás web szolgáltatásokkal
  • JAX-WS 2.0 (JSR 224): JAX-RPC utódja, de átnevezésre is került, mert nem csak RPC-re, hanem dokumentum alapú web szolgáltatások implementálására és hívására is használható

Ezekből a JAXP már régóta a Java SE része, de a többi részlegesen csak a Java SE 6-ban jelent meg. A Java EE 5 már mindet teljes mértékben tartalmazza.

A JAXB és JAXB trükkök post-jaimban már írtam a JAXB-ról, arról többet itt nem is írnék.

A JAX-WS követi az EJB3 alapelveket, hogy minél egyszerűbben lehessen programozni, és annotációkkal konfigurálható legyen. A protokoll HTTP(S), de le lehet cserélni JMS-re, SMTP-re, de akár lokális metódushívásokra is (In-VM). A JAX-WS az XML binding-ot JAXB-vel oldja meg, de ezt akár le is lehet cserélni a referencia implementációban (pl. JSON-ra). De akár Source, SOAPMessage vagy DataSource példányként is kezelhetjük az beérkező XML-t, ekkor Provider<T> interfészt kell implementálni, ez gyakorlatilag a SEI dinamikus alternatívája szerver oldalon. A payload mód esetén a SOAP boríték belseje kerül átadásra, ellenkező esetben a teljes boríték. Kliens esetében a Dispatch<T> példányt kell a Service factory-vel gyártani, ami a kliens oldali proxy dinamikus megfelelője.

Fontos fogalom a SEI (Service Endpoint Interface), mely a web szolgáltatásként meghívható metódusokat definiálja. Használata nem kötelező, ekkor implicit SEI generálódik. Kliens oldalon proxy-t kell használni, mely becsomagolja a hívást és áttolja a hálózaton, valamint a választ feldolgozza (marshall/unmarshall). Érdemes még a handler-ek ismerete, melyek lehetnek protokoll független (logikai) handler-ek, valamint protokollfüggő (pl. SOAP) handler-ek is. Ezeket úgy kell elképzelni, mint servlet-ek esetn a filter-eket, képesek elkapni a hívásokat, és a válaszokat, és akár módosítani is azt. Tipikusan jók biztonságra, tranzakciókezelésre, naplózásra, AOP web szolgáltatás szinten.

Az inout típusú paramétereket a Holder osztállyal lehet kezelni.

A JAX-WS aszinkron hívást is támogat, ilyenkor a kliens egy külön szálon hívja a web szolgáltatást, és az alkalmazás futhat tovább blokkolás nélkül. Lehet később visszakérdezni, hogy hogy áll, valamint eseményfigyelőt is lehet a web szolgáltatás hívásának befejezésére definiálni.

A fenti betűszavak csak specifikációk, ezeknek különböző megvalósításai is vannak, a Sun biztosítja a GlassFish projekt keretében a referencia implementációkat. A web szolgáltatásokkal kapcsolatos projektek a Metro gyűjtőprojekt alatt szerepelnek:

  • GlassFish > JAXP Reference Implementation
  • GlassFish > Metro > JAXB Reference Implementation
  • GlassFish > Metro > SAAJ Standard Implementation
  • GlassFish > Metro > JAX-WS Reference Implementation

Sajnos az összes projektet a java.dev.net hosztolja, melynek rendelkezésre állása tragikus. A támogatással sem voltam megelégedve, szemben a SOAPUi gyors reakciójával, ugyanis belefutottam abba a hibába, hogy a SEI-ben nem lehet konstansokat definiálni. A fórumban megkédeztem, hogy miért, hiszen egyik specifikációban sem láttam (, valószínűleg JAX-RPC örökség), és forráskódot is csatoltam. Azóta sem érkezett válasz.

A legfontosabb dolog, melyre a fejlesztés során rájöttem, hogy nem elegendő a JDK-ban lévő eszközökkel dolgozni, mindig a legfrissebb eszközöket kell használni, mivel mind iszonyú iramban fejlődik, és rengeteg hiba található régebbi verziókban. A "schemagen.exe –version" paranccsal lehet a JAXB verzióját lekérdezni, mely a jdk1.6.0_17-ban JAXB 2.1.10 in JDK 6, a JAX-WS-t a "wsimport –version" paranccsal, melynek verziója ugyanezen JDK-ban JAX-WS RI 2.1.6 in JDK 6. Mostanában akár update verziónál is változik a JDK-ban lévő JAXB vagy JAX-WS implementáció, ezzel kapcsolatos bonyodalmakkal az előbb is említett post-om foglalkozik. Azóta kiderült, hogy a régebbi verzió az ANY típusú tag-et sem megfelelően kezelte, valamint az Axis által küldött mime fejléccel is problémái voltak. A verziófrissítés mindkét problémát megoldotta (az utóbbinál a teljes JDK-t kellett).

A JAXB és JAX-WS parancssori eszközök mindegyikének van Ant task párja is.

Teszteléshez mindenképp a SOAPUi eszközt javaslom, mely képes nem csak web szolgáltatásokat meghívni, hanem szimulálni is. Erre is érvényes a verziókkal kapcsolatos megállapításom. Az attachment kezeléssel belefutottam egy hibába a 3.0.1-es verzióval (Exception, üres kérést generált), amit jelentettem is a fórumon. Másnap jött a válasz, hogy próbáljam meg a nightly build-del, amivel tényleg ment.

A fejlesztés között a verziókon kívül a legtöbb problémám az ANY típusú tag-ekkel volt. Példaként nézzünk is egy ilyen részletet:

<xs:complexType name="AnyType">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded"
namespace="##any" processContents="skip" />
</xs:sequence>
</xs:complexType>

Ebben az esetben a belső tartalmon nem végzi el a JAX unmarshall-t, hanem DOM-ot kapunk. Ezt nekünk kell manuálisan unmarshall-olni. A JAXB File, Stream és DOM-on kívül képes unmarshall-olni bármilyen Source-ból, valamint a StAX-os XMLStreamReader-ből és XMLEventReader-ből is. Any esetén egy olyan hibába is beleütköztem, hogyha más névtérben volt a belső tartalom, és az nem volt prefix-szel megjelölve, akkor annak elrontotta a névterét. A setPrefix hívás segített.

A JAXBContext-t érdemes cache-elni, hiszen szálbiztos.

A JAXBElement a JAXB 2.0-ban jelent meg. Az XJC, ha az adott típus nem használható más néven, akkor egy POJO-t generál. Azonban ha használható, akkor JAXBElement példányba burkolva lehet használni. Ezt kikerülhetjük, ha használjuk a gyártófüggő <xjc:simple /> konfigurációt, vagy mi példányosítunk new JAXBElement(new QName("uri","local"), MessageType.class, messageType) módon.

Alapesetben web szolgáltatás híváskor teljesítmény okok miatt nem történik validáció, de ezt a com.sun.xml.ws.developer.SchemaValidation annotációval bekapcsolhatjuk a @WebService annotációt tartalmazó osztályon.

Attachmentet kezelhetünk SwA (SOAP with attachment), és MTOM szabvány szerint is. Mivel az előbbi már kevésbé támogatott, az utóbbit érdemes használni. Az MTOM (SOAP Message Transmission Optimization Mechanism) egy szabvány arra, hogyan tud egy SOAP kommunikációban a két kommunikáló fél megegyezni abban, hogy kihasználva az átviteli közeg előnyeit vigyen át adatokat. Ennek egy megvalósítása a XOP-ra (XML-binary Optimized Packaging) épülő Optimized MIME Multipart/Related Serialization of SOAP Messages). Ez gyakorlatilag azt jelenti, hogy egy állományt hatékonyabban lehet átvinni, ugyanis nem a szöveges kommunikációba lesz bekódolva BASE64-gyel, ami 33%-kkal növeli a hosszt, hanem az e-mail-hez hasonlóan az üzenet két különböző mime type-ú részre van osztva, egy szövegesre, mely hivatkozik az állományra (xop:Include tag-gel), és egy binárisra, mely tartalmazza az állományt. JAX-WS-ben az @MTOM annotációval lehet kihasználni. Az XML xop:Include hivatkozást fog tartalmazni. Sajnos nekem az előbbit kellett használnom, ahol az attachment-et kötelező megadni, sajnos a másik fél, nem alkalmazkodott a szabványhoz, így 0 bájtos állományokat kellett küldenünk.

A WSDL-lel kapcsolatban is belefutottunk egy hibába, a wsdlLocation beállítása relatív, protokoll nélkül nem működött (CLASSPATH-ról resource). A 2.2-es JAX-WS-ben javítva.

Sajnos a NetBeans-sel is voltak problémáim. Amennyiben az interfész nem volt megfelelő (pl. BARE = "unwrapped" módnál több paraméter megadása, vagy List típusú visszatérési érték), nagyon szűkszavú hibaüzenet írt ki: Error starting wsgen:. Ebből nem lehetett rájönni a hiba okára, a megoldás a jaxws-build.xml-ben a wsgen Ant task-nál a verbose="true" fork="true" paraméterek elhelyezése. Ezt beírva a hibaüzenetek már beszédesebbek, több paraméter esetén:

Exception in thread "main" com.sun.xml.ws.model.RuntimeModelerException:
runtime modeler error: SEI [osztály neve] has method [metódus neve] annotated as
BARE but it has more than one parameter bound to body. This is invalid.
Please annotate the method with annotation:
@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

List visszatérési érték esetén:

Exception in thread "main" com.sun.xml.ws.model.RuntimeModelerException:
runtime modeler error: SEI [osztály neve] has method [metódus neve] annotated as
BARE but it has more than one parameter bound to body. This is invalid.
Please annotate the method with annotation:
@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

Sajnos a NetBeans-ben a WSDL validáció sem működik, ha szerepel benne az attachment miatt <mime:multipartRelated> tag. Hibaüzenet: "ERROR: At least one <soap:body> element is required per input/ouput message in a soap operation."

A JAX-WS Spring-gel is használható, a GlassFish > Metro > JAX-WS commons > Spring support projekttel. Sajnos ebbe is hibába futottam, ugyanis ha a WSDL-t kézzel akarjuk megadni (sajnos a megoldás nem szimmetrikus, WSDL alapján gyártott osztályok nem mindig ugyanazt a WSDL-t generálják ki), akkor nem lehet több erőforrás megadni a Spring névteres módon, hanem trükközni kell. Álljon itt egy Spring applicationContext.xml részlet erre.

<bean id="metadata" class="java.util.ArrayList" >
<constructor-arg>
<list>
<value>/WEB-INF/wsdl/1.xsd</value>
<value>/WEB-INF/wsdl/2.xsd</value>
</list>
</constructor-arg>
</bean>

<bean id="loggingHandler" class="jtechlog.LoggingHandler"/>

<wss:binding url="/service">
<wss:service>
<ws:service bean="#mySIB">
<ws:handlers>
   <ref bean="loggingHandler" />
</ws:handlers>
<property name="metadata" ref="metadata" />       
</ws:service>
</wss:service>
</wss:binding>

A NetBeans-nek nem lehet megmagyarázni, hogy Spring-gel akarom használni a web szolgáltatást, ő mindenképp generálni akarja a szabvány JAX-WS-es dolgokat.

A naplózásra érdemes még kitérni. Handler-rel próbáltam megoldani. Először is összeakadt a Handler , Tomcat, Log4J hármas, lefagyott tőle a Tomcat, de csak kivétel esetén (persze rendesen le volt kezelve) - valahogy a konzolra írás és olvasás deadlock-kolt. A NetBeans forrásában látott Thread.sleep(100); megoldotta a problémát. Ezen kívül nem érdemes erre használni a standard handler-eket, ugyanis van benne DOM parse-olás, inkább javasolt a gyártófüggő com.sun.xml.ws.api.handler.MessageHandler használata. Sajnos itt is több problémába ütköztem. Érdemes még arra is gondolni, hogy a viszonylag nagyméretű XML-eket érdemes aszinkron naplózni.

Összegzésként azt kell megállapítanom, hogy a Sun ígéretei, miszerint a szabványokat és az eszközeiket úgy alkotják meg, hogy ne kelljen az infrastruktúrával foglalkozni, csupán az üzleti logikára koncentrálni, nem igaz. Sajnos a projektben többen is úgy véljük, hogy legalább 60-80%-ot töltünk az infrastruktúra megtanulásával, hibakeresésével, és a többi marad az üzleti logikára. Tapasztalatok alapján más framework-kel sincs ez másképp. Érdemes a jól bevált, kitapasztalt, támogatott eszközöket használni.

JAX-WS mélyvíz diák letöltése

2009. november 1., vasárnap

Szabad Szoftver Konferencia

Ma volt a Free Software Foundation Hungary Alapítvány által szervezett Szabad Szoftver Konferencia és Kiállítás 2009. Úgy látszik, mostanában főleg konferenciabeszámolókat írok, de mostanában nagy a termés, érdemes ellátogatni ezekre, nyomon követni a trendeket. Figyeljétek a jobb oldali Google Naptárat, melybe minden Java-val kapcsolatos hazai eseményt megpróbálok felvenni. A mostani konferenciáról is a meglátogatott előadásokról fogok írni, címszavakban az érdekességekről. A rendezők ígérete szerint legy egy PDF-ben letölthető több, mint 100 oldalas kiadvány, mely minden előadásról 4-5 oldalt fog tartalmazni, valamint a videók is fenn lesznek a FLOSS videóblog oldalon.

Dr. Szentiványi Gábor A felhőkön túl című előadásából kiderült, hogy az előadó kicsit szkeptikus a felhők jelenlegi felhasználását illetően. A semmibe vezető hídhoz hasonlította a jelenlegi állapotot. Számolni kell a vendor lock-in-nel, a kisebb versenyzők a "nagyokat" (Amazon, Google) követve próbálnak felemelkedni, nincs kiforrott, all-in-one üzleti modell. Érdemes figyelni, merre tartanak, de merészség teljes lendülettel beszállni.

Trencséni Márton: Skálázható elosztott rendszerek

A kulcs-érték alapú adatbázisokról, MapReduce-ról, CouchDB-ről már írtam egy előző postban.
Keyspace
Az előadó cége (Scalien) által BSD alatt fejlesztett kulcs-érték adatbázis. A NoSQL irányvonal megtestesítője, mely azon adatbázisok gyűjtő neve, melyek használatához nem szükséges SQL. C/C++-ban íródott, BerkleyDB-n alapul, de a következő verzióban ezt szeretnék kiváltani. Alapvetően konzisztenciát tart, de minden műveletnek van egy un. dirty párja, mely könnyen párhuzamosítható, de sérülhet a konzisztencia. Szóba került még a Paxos és a Vector Clock algoritmusok is.
Shared nothing architektúra
Az SN egy olyan elosztott architektúra, ahol nincs verseny egy közös erőforrásért, mint pl. egy központi adatbázis. Most a webes fejlesztéseknél, valamint a felhők világában különösen fontos, hiszen nagyon jól skálázható, újabb alacsony költségű gépek beállításával növelhető a teljesítmény, és nincs szűk keresztmetszet, illetve olyan meghibásodási pont, mely a teljes rendszert megbénítaná (single point of failure). Ezt a Google is bebizonyította, az ilyen típusú adattárolást sharding-nak hívja, aminek lényege, hogy az adatokat valamilyen osztályozás szerint külön tárolja (horizontális partícionálás), ezáltal egyszerre kisebb adatmennyiségen kell dolgozni.
Eventual consistency
Olyan konzisztencia modell (elosztott rendszerek esetén használatos, van-e ellentmondás a tárolt adatok között), melynek használatával lehetséges, hogyha egy adatot módosítunk, majd visszaolvasunk, nem a módosított értéket kapjuk. Ez úgy lehetséges, hogy a konzisztenciát feláldozzuk a teljesítmény oltárán, azaz nem blokkoljuk a módosítást addig, míg az szét nem terjed a replikátumokon. Pl. egy közösségi oldal képfeltöltésénél elfogadható, de banki rendszernél ne használjuk. Hátránya, hogy amikor inkonzisztencia lép fel, nem kezelhető automatikusan, hanem az alkalmazást kell rá felkészíteni, ami vagy feloldja, vagy a felhasználóra bízza a konfliktus feloldását.
Distributed lock manager
A megosztott erőforráshoz való hozzáféréseket vezérli.
Memcached
Nagy teljesítményű, elosztott, memóriában helyet foglaló cache rendszer, mely nagyszerűen tehermentesítheti az adatbázist. Legnagyobb felhasználója pl. a Facebook, ahol a tartalom 95%-a cache-ből jön.
Redis
A Memcached-hez hasonló, memóriában tartott kulcs-érték adatbázis, azzal a különbséggel, hogy az adatokat bizonyos időközönként képes aszinkron módon lemezre menteni, valamint szövegen kívül halmazokat és listákat is kezel, valamint képes replikációra.
MemcacheDB
Bár nevében hasonlít a Memcache-re, és másra asszociálnánk, nem egy cache, hanem egy BerkleyDB-t használó perzisztens megoldás, mely API szinten nagyon hasonlít a Memcache-re, és C-ben lett megírva.
Google stack
Google File System (GFS), Chubby distributed lock manager, BigTable adatbázis kezelő és a MapReduce.
Hypertable
Nyílt forráskódú adatbázis a BigTable hasonlatosságára, C++-ban.
Dynamo
Az Amazon kulcs-érték adatbázisa.
Dynomite
Dynamo klón, nyílt forráskóddal, Erlang-ban megvalósítva.
Apache Hadoop
A Yahoo! által használt nyílt forráskódú, Java-ban fejlesztett szoftverek gyűjtőprojektje a megbízható, skálázható, elosztott rendszerek fejlesztéséhez. Része a HBase, mely egy nyílt forrású BigTable klón.
PNUTS
A Yahoo! által használt elosztott adatbázis, mely nem nyílt.
Cassandra
Facebook mögött lévő adatbázis, Java-ban.
Project Voldemort
LinkedIn mögött lévő kulcs-érték adatbázis, Java-ban.
MongoDB
Nyílt forráskódú, dokumentum-orientált adatbázis, C++-ban.
Tokyo Cabinet
Egy újabb kulcs-érték adatbázis, C-ben.
Neo4j
Beágyazható, lemezre perzisztáló, tranzakcionált gráf alapú adatbázis.
Eucalyptus
Amazon API kompatibilitást ígérő nyílt forráskódú megoldás.
Hail
Célja nyelv- és platformfüggetlen, felhő építését lehetővé tévő, nyílt forráskódú infrastruktúra szolgáltatások kifejlesztése.
Deltacloud
Egységes REST API a különböző felhők (cloud) kezelésére, megszabadulva ezzel a vendor lock-in-től. Jelenleg támogatott felhők: EC2, RHEV-M, RackSpace; VMWare ESX.

Elég sok szó esett a kulcs-érték alapú adatbázisokról, itt található egy rövid összehasonlítás. Személyes véleményem, hogy még nagyon nagy kavar van, nem árt kicsit várni, míg kitisztul a kép.

Szántó Iván: A KVM helye a virtualizáció világában

Egy korábbi postban, és a Tumblr-en is írtam már a virtualizációról, és ez az előadás is erről szólt. Szó esett a CPU virtualizációról, ahol érdemes ismerni az x86-os architektúrában alkalmazott gyűrűk (ring) fogalmát. A gyűrűk bevezetése a biztonságot nyújtják. 0. gyűrű a kernelé, és korlátlanul hozzáférhet a CPU-hoz, memóriához és egyéb erőforrásokhoz, az 1. és 2. a meghajtó programoké, és a 3. az alkalmazásoké. A supervisor mód jelzi egy task-ról, hogy hozzáférhet a védett erőforrásokhoz. A hypervisor a CPU-k hardveres virtualizáció támogatásával jelent meg. Segítségével a vendég operációs rendszerek 0. gyűrűben végrehajtható utasításokat futtathatnak. A CPU virtualizáció három formája a full virtualizáció, a paravirtualizáció, valamint a virtualizáció hardveres támogatással. Az első esetben a virtualizált operációs rendszer hívásait egy szoftver fordítja át. Ekkor az operációs rendszert nem kell módosítani. Paravirtualizáció esetén az operációs rendszert megváltoztatják, így ez a megoldás csak nyílt forráskódú operációs rendszereknél jöhet szóba, viszont kétségkívül gyorsabb, mint a szoftveres megoldás. A harmadik eset az előző kettő előnyeit ötvözi. A virtualizáció lehet host/guest alapú, amikor is egy operációs rendszeren felhasználói programként fut a virtualizációs megoldás, és abban a virtuális operációs rendszer, valamint lehet hypervisor/os alapú, mikor alul nem egy operációs rendszer, hanem egy hypervisor üzemel. Ebben az esetben azonban ki kell jelölni egy elsődleges operációs rendszert, mely direkt hozzáférést kap az erőforrásokhoz.

A memóriavirtualizáció során a virtuális operációs rendszer lapjait le kell képezni a virtuális gép lapjaira (page tables), és azt tovább le kell képezni a fizikai memória lapjaira (shadow tables). Az IO eszközök virtualizációja történhet full virtualizációval, paravirtualizált operációs rendszerrel, paravirtualizált driver-rel, vagy pass-through driver-rel (direkt hozzáférés).

A KVM, melynek neve is mutatja, kernelen alapuló virtualizáció, fő ötlete, hogyha a Linux kernelben úgyis meg van valósítva az ütemezés, erőforrás kezelést, stb., akkor azt továbbra is oldja meg a kernel, és csak a többi problémával foglalkozzon a virtualizáltságot biztosító szoftver. A QEMU-n alapul, mely egy nyílt forráskódú processzor emulátor. Elhangzott egy olyan trükk is, hogy azonos operációs rendszerek futtatásakor sok azonos memóriaterület lehet, ezt nem tárolja többször, hanem összeolvasztja (Kernel Sam Page Merging), és amennyiben az egyik virtuális gép mégis módosítani akarja, különválasztja (COW - copy on write). Említésre került a SPICE (Simple Protocol for Independent Computing Environments) is, mely egy virtualizációra optimalizált távoli adatátvitelt biztosító protokoll, melynek tulajdonságai az akár 30 fps-es video és Flash átvitel, kétirányú audio és video átvitel, valamint egy trükk, mely megvizsgálja a távoli és lokális gép videokártyáját, és a gyorsabbon renderel. A KVM kezelhető grafikus eszközzel (virt-manager) és parancssori eszközzel (virsh) is. A libguestfs is jó ötlet, a virtuális gép disk-je a virtuális gép elindítása nélkül írható/olvasható. Menedzsment eszköz a Redhat RHEV-M is.

Mátó Péter: Adatbiztonság és üzembiztonság mindenkinek? Egy frappáns válasz: uDS

A uDS projekt lényege röviden összefoglalható: a belső winchester és egy USB pendrive RAID-1-be kötése, titkosítással. Mire is jó ez? Ha azt akarjuk, hogy ne kelljen manuálisan menteni az adatainkat, ezzel megoldható, hogy pl. a home könyvtárunk módosítása automatikusan, titkosítottan a pendrive-ra is átkerüljön. Ezzel meg van oldva a backup, és másik gépre átvíve azonnal szinkronizációs megoldás is. Az előadás a felmerült problémákról, és megoldásukról szólt, mint pl. a pendrive lassú sebessége (aszinkron írással kiküszöbölhető), valamint a pendrive különösen érzékeny a sok írásra (terítési algoritmus).

Höltzl Péter: Központosított napló gyűjtés, classifikáció és előfeldolgozás syslog-ng OSE és más szabad eszközökkel

Ez az előadás a syslog-ng-ről szól. Pont úgy működik, ahogy azt az ember egy naplózó rendszertől elvárja. Vannak források (source), amin bejön a napló (fájl, legacy syslog UDP - borzasztó formátum, kerüljük, TLS (Transport Layer Security) - SSL elődje, titkosított, stb.), valamint vannak célok, ahova kiírja azokat (destination). Definiálhatók filter-ek, melyek szűrik a napló bejegyzéseket. Mindkettő nevesített, és a log path köti össze őket. Probléma ugye a különböző formátumok kezelése. Erre template-eket lehet definiálni, melyek a naplót formázzák kiíráskor, valamint parser-eket, amik a bejövő naplókat elemzik. Ekkor un. makrók jönnek létre, melyeket használni lehet. Ezt elérési útban is meg lehet adni, így megoldható vele az archiválás is (havonta másik könyvtárba tesszük). Erre jól jöhet a logrotate is, ami már nem nevezgeti át az állományokat. Érdemes figyelni, hogy a napló állományba a szerver időpecsétje kerüljön, nehogy a kliens óra eltérése miatt ne lehessen az naplókat összefésülni. A napló bejegyzéseket át is lehet írni (rewrite). Támogatja a napló bejegyzések klasszifikációját is minta adatbázis alapján, valamint szó esett az artificial ignorance-ról, ahol nem a rossz dolgok vannak mintaként az adatbázisban, amire a rendszer riaszt, hanem a normális eseményeknek és minden attól eltérő kivizsgálásra kerül. A klasszifikáció nem regexp alapján történik, mivel az lassú, és on-the-fly történik, és nem batch jelleggel. Konkurrencia: Logcheck, Rsyslog. Lásd még RFC 5424 (The Syslog Protocol), RFC 3164 (The BSD syslog Protocol).

Czakó Krisztián: Virtualizáció & HA cluster: szeparált, egyszerű és biztos működik

Az előadás első része a XEN-ről szólt, mely egy hypervisor alapú virtualizáció, mely a hardveres támogatást is ki tudja használni. Képes a live migrációra, mikor menet közben, egy kis döccenővel tudunk átállni az egyik gépen futó virtuális gépről a másikra. (Úgy működik, hogy egyre kisebb differenciákat visz át, és a legutolsónál van a pillanatnyi leállás.) Le lehet állítani, majd újraindítani a hypervisor-t úgy, hogy a virtuális gépeket nem kell leállítani, gyakorlatilag a leállásból azok semmit nem vesznek észre (suspend/resume). Hasznos eszköz lehet az OpenQRM GPL alatt, mellyel több virtualizációs megoldást is lehet menedzselni. High availability a tervezett és nem tervezett rendszer leállások minimalizálása, a fault tolerance esetén a rendszer hiba esetén is működik tovább, anélkül, hogy ezt a felhasználó észrevenné. A Linux-HA projekt alakult a Linux alatti HA megvalósítások implementálására, melynek fő terméke a Heartbeat. Jelenleg azonban a honlapja átirányít a Pacemaker honlapjára, mely egy cluster infrastruktúra, mely képes OpenAIS és Heartbeat felett is működni. A cluster működhet SAN felett (AOE, iSCSI, FiberChannel), páratlan számú node-dal, hiszen itt a lényeg a többségi cluster, és DRBD felett, mely tulajdonképpen egy szoftveres RAID 1 megoldás TCP/IP felett, de csak két node-ot támogat. Az előadás konklúziója, hogy a XEN Heartbeat támogatása igen erős, kész script-ek vannak, így aki pl. egy Apache HA-t már kialakított Heartbeat-tel, annak nem lesz különösebben bonyolult ugyanezt virtuális gépekkel megoldania.

Ígérem, a következő bejegyzés teljesen Java-s lesz.