6. A REST nem támogatja a tranzakciókat
A tranzakció fogalma többféleképpen értelmezhető, azonban általában, amikor az emberek tranzakciókról beszélnek, akkor az adatbázisok ACID (Atomicity, Consistency, Isolation, Durability) tulajdonságára utalnak, mely azt garantálja, hogy ezeknek az adatbázis-tranzakcióknak a feldolgozása megbízható módon történik. Egy SOA környezetben, mely alapulhat webes szolgáltatásokon vagy csupán HTTP-n, valószínű, hogy minden szolgáltatás (vagy rendszer, illetve webes alkalmazás) implementációja kommunikál olyan adatbázisokkal, melyek támogatják a tranzakciókat: ez nem jelent nagy változást, eltekintve attól, hogy valószínű, hogy explicit módon, magunk hozzuk létre a tranzakciót (hacsak a szolgáltatásunk nem EJB konténerben vagy egy olyan más környezetben fut, mely elvégzi számunkra a tranzakciók létrehozását). Ugyanez a tranzakcionalitást jellemző akkor is, ha több mint egy erőforrással kommunikálunk.
A különbség akkor jelenik meg, ha elkezdjük a tranzakciókat nagyobb egységekbe ötvözni (vagy szerkeszteni). Webes szolgáltatási környezetben legalább van egy olyan lehetőség, hogy úgy alakítsuk a dolgokat, hogy azok a szokásos módon viselkedjenek, mint például ahogy ahogy azt 2PC (kétfázisú commit) esetén Java EE környezetben megszoktuk. Ilyen példul a WS-Atomic Transaction (WS-AT), ami a WS-Coordination szabvány család tagja. A WS-AT implementációja alapvetően nagyon hasonló az XA által specifikált 2PC protokollhoz. Ez azt jelenti, hogy a tranzakciós kontextus a SOAP (Simple Object Access Protocol) fejlécben továbbítódik, az implementáció pedig biztosítja majd, hogy az erőforrás menedzserek egy meglévő tranzakcióhoz kapcsolódjanak. Ez ugyanaz a modell, mint amit az EJB fejlesztők már megszoktak: az elosztott tranzakciók ugyanolyan atomikusan viselkednek, mint a helyiek.
Van az atomikus tranzakcióknak néhány hátránya a SOA környzetben.
- A laza csatolás és a tranzakciók, különösen az ACID tulajdonságok esetén, egyszerűen nem illenek össze. Pusztán az a tény, hogy több független rendszeren keresztül koordinálunk egy commitot, meglehetősen szoros csatolást eredményez a rendszerek között.
- Ennek a koordinációnak az előfeltétele az összes szolgáltatás feletti központi ellenőrzés. Ezért például meglehetősen valószínűtlen, sőt nagy valószínűséggel lehetetlen, hogy a vállalati határokon kívül, tehát például különböző vállalatok között 2PC tranzakciókat futtassunk.
- Az infrastruktúra, melynek ezt támogatnia kell, általában nagyon költséges és összetett.
SOA vagy REST környezetben az ACID tranzakciók iránti igény a tervezésre vezethető vissza: a szolgáltatásainkat vagy erőforrásainkat valószínűleg rosszul modelleztük. Az atomikus tranzakciók természetesen a tranzakciók csak egy fajtáját képezik, vannak azonban olyan kiterjesztett tranzakciós modellek, melyek lazán csatolt rendszerekhez jobban illeszkedhetnek. Ezeket a modelleket még nem sokan alkalmazzák, még a webes szolgáltatások fejlesztőinek körében sem.
7. A REST megbízhatatlan
Már sokan rámutattak, hogy a WS-ReliableMessagingnek nincs megfelelője RESTesített HTTP esetén. Ebből sokan azt a következtetést vonják le, hogy ezért ez nem alkalmazható olyan esetekben, ahol a megbízhatóság kritikus kérdés (ez pedig gyakorlatilag minden olyan rendszerre vonatkozik, mely bármilyen fontossággal bír az üzleti környezetben). Azonban gyakran nem elegendő néhány, az üzenetek szállítását kezelő infrastruktúra komponens használata, hanem azt is tudni akarjuk, hogy egy adott üzenet kézbesítve lett-e vagy sem.
Ha egy válaszüzenetet kapunk, mint például az egyszerű 200 OK üzenetet HTTP esetén, akkor ez tipikusan azt jelenti, hogy a kommunikációs partnerünkhöz megérkezett a kérés. A problémák akkor merülnek fel, ha nem kapunk választ, és nem tudjuk, hogy a kérésüzenet veszett el útközben, vagy a válaszüzenet.
A legegyszerűbb módja annak, hogy biztosítsuk azt, hogy a kérés eléri a címzettet az az, ha újból elküldjük azt, ami természetesen csak akkor lehetséges, ha a címzett a duplikátumokat kezelni tudja (például figyelmen kívül hagyással). Ezt a képességet idempotenciának hívjuk. A HTTP biztosítja, hogy a Get, a Put és a Delete idempotensek, és ha az alkalmazásunk helyesen van implementálva, akkor a kliens egyszerűen csak újból küldi ezeket a kéréseket, ha nem kapott választ. A Post üzenet azonban nem idempontens, legalábbis a HTTP specifikációban nincs olyan utalás, mely garantálná, hogy az lenne. Több lehetőségünk is van: az egyik, hogy a Put használatára váltunk (ha a szemantika leképezhető rá), a másik, hogy az általános bevált módszereket alkalmazzuk, vagy pedig a meglévő ajánlások egyikét alkalmazzuk ennek szabványosítására (mint például Mark Nottingham POE-je, Yaron Goland SOA-Rity-je, vagy Bill de hÓra HTTPLR-je).
Míg ezen megoldások a megbízhatósági kihívás jó részére választ adnak, semmi sincs, ami a kézbesítés bizonyos tulajdonságait garantálná, mint például a HTTP kérések és válaszok egymásutánjának sorrendiségét. Fontos azonban rámutatni, hogy számos meglévő SOAP/WSDL forgatókönyv jól alkalmazható WS-Reliable Messaging, vagy annak számos elődje nélkül is.
8. Nincs publish/subscribe támogatás
A REST alapjában véve kliens-szerver modellre épül, a HTTP pedig mindig egy kliensre és egy szerverre hivatkozik a kommunikáció két végpontjaként. A kliens a szerverrel úgy kommunikál, hogy kérést küld és választ kap. A pub/sub modellben az érdekelt fél egy adott információ-kategóriára előfizet, és minden alkalommal, amikor valami új megjelenik, erről értesítést kap. A pub/sub modell hogyan támogatható RESTesített HTTP környezetben?
Nem kell messzire mennünk, hogy meglássuk ennek a tökéletes példáját, melyet szindikációnak nevezünk. A szindikációra jó példa az RSS és az Atom Syndication. A kliens úgy kérdezi le az új információt, hogy egy HTTP parancsot ad egy olyan erőforrásra vonatkozóan, amely erőforrás a változásokat gyűjteményét reprezentálja, például egy adott kategóriára vagy időtartamra szűkítve. Ez egy rendkívül kevéssé hatékony megoldás lenne, de mégsem az, mivel a Get a leginkább optimalizált művelet a weben. Sőt, könnyen elképzelhetjük, hogy egy népszerű webes blog szerver sokkal méretezhetőbb lenne felfelé, ha nem kellene minden előfizetett klienst egyenként, minden változásról értesítenie. Az értesítést helyettesítő pollozás hihetetlenül jól méretezhető.
A szindikációs modellt kiterjeszthetjük az alkalmazási erőforrásainkra, például kiajánlhatunk egy Atom feedet az ügyfelek erőforrásainak változására, vagy például foglalások audit naplójára. Amellett, hogy egy alapjában véve korlátlan számú előfizető alkalmazást ki tudunk elégíteni, ezeket a feedeket egy feed olvasóban is megtekinthetjük, ahhoz hasonlóan, ahogy a HTML reprezentációt megtekintjük a böngészőnkben.
Természetesen ez néhány forgatókönyv számára nem nyújt megfelelő megoldást. Például „puha” valósidejűségi követelmények esetén más technológia megfelelőbbnek bizonyulhat. Azonban sok esetben a laza csatolás, a méretezhetőség, illetve az értesítés ötvözése, melyet a szindikációs modell lehetővé tesz, kitűnő megoldás.
9. Az aszinkron interakciók hiánya
Ha figyelembe vesszük a HTTP kérés/válasz modelljét, felmerül a kérdés, hogy hogyan tudunk aszinkron kommunikációt megvalósítani? Ismét fontos megjegyezni, hogy aszinkronitás alatt több mindent értenek. Néhányan a programozási modellre utalnak, mely lehet blokkoló vagy nem blokkoló függetlenül az alacsonyabb szintű információáramlás típusától. De nem ez a fő kérdésünk, hanem az, hogy hogyan szállítunk egy kérést a klienstől (fogyasztó) a szerverhez (szolgáltató) olyan esetekben, amikor a feldolgozás órákba is telhet? A fogyasztó hogyan értesül arról, hogy a feldolgozás megtörtént?
A HTTP rendelkezik egy specifikus válaszkóddal, a 202-vel (Accepted – elfogadott), melynek jelentése a következő: „A kérés be lett fogadva feldolgozáshoz, de a feldolgozás még nem fejeződött be.” Na, mi pont ezt keressük. Az eredményt illetően több lehetőség van: a kérés a szervertől visszatérhet egy erőforrás URI-jával, melyen a kliens egy Get parancsot hajthat végre annak érdekében, hogy az eredményhez hozzáférjen (habár, ha kimondottan e kérés miatt hozták volna létre, egy 201 Created válaszkód valószínűleg jobb lenne). A másik mód az, hogy a kliens csatolhat egy URI-t, melyen majd a szerver POST műveletet hajt végre, amikor kész lesz.
10. Az eszközök hiánya
Végül, gyakran panaszkodnak a REST-esített HTTP fejlesztésének támogatására szolgáló eszközök hiányáról. Ahogy azt a kettes pontban taglaltuk, ez az adatok szempontjából nem igaz, mivel az összes adat kapcsolati módszert és más adat API-kat is használhatunk, melyekhez hozzászoktunk. Ez egy olyan aggodalom, mely ortogonális a módszerek és az eszközök számára, valamint a meghívásuk módjára. A sima HTTP ésURI támogatás minden programozási nyelvben, keretrendszerben és eszköztárban benne van, használatra készen. Végül pedig, a gyártók egyre több és feltehetően egyszerűbb, jobb támogatást hoznak létre a REST-esített HTTP fejlesztéséhez a keretrendszerükben. Erre példa a Sun JAX-RS (JSR 311) vagy a Microsoft REST támogatása a .NET 3.5-ben vagy az ADO.NET Data Services keretrendszerben.
A következtetés
Tehát arra a következtetésre jutottunk, hogy a REST és a legáltalánosabb implementációja, a HTTP, tökéletes? Természetesen nem. Semmi sem tökéletes, főleg nem minden forgatókönyv esetén, és a legtöbbször még egyetlen forgatókönyv számára sem. Nem vettünk számba jópár nagyon logikus problématerületet, melyek sokkal összetettebb válaszokat kívánnak, mint például az üzenet-alapú biztonság, a részleges frissítések és a kötegelt feldolgozás.