Simple Object Access Protocol

Av og til vinner den enkleste teknologien. Derfor gir vi SOAP en sjanse.

Trykket i Nettverk & Kommunikasjon nr.10/2000
(c) Anders Fongen 2000

Anders Fongen er høgskolelektor og fagsjef ved Den Polytekniske Høgskolen. Web-stedet hans er på www.fongen.no

Ofte er teknologien altfor avansert. Ofte er teknologien laget av personer som bruker hele sin arbeidstid på å trenge inn i et problemområde, og som derfor oppnår mye mer innsikt enn de fleste. Så lager de teknologiske løsninger som reflekterer denne innsikten. Innenfor programvare har vi mange ganger sett eksempler på at slike løsninger krever mye mer innsikt enn hva de fleste brukerne har, til tross for at utviklerne har lagt mye krefter i å få til en "innkapsling" som skal være enkel å bruke.

Teknologiske løsninger som har denne egenskapen vil utbre seg sent, den er ofte kostbar i innkjøp og koster mye å bruke. Konsulenthonorarer eller vedlikehold av intern spisskompetanse bidrar til slike kostnader.

HTML var ikke det første hyperlenke-språket, heller ikke det beste. XML var ikke den første overføringssyntaks, heller ikke den beste. De fleste Internet-protokollene er i sin utforming enklere enn dem de har utkonkurrert. Disse eksemplene burde vise at teknologi ikke bare skal løse et problem, men også være tilgjengelig for bruk av "vanlige" fagfolk.

Klient/tjener, RPC og fjernobjekter

SOAP har sitt anvendelsesområde innenfor distribuert programmering, dvs. der hvor datamaskiner samarbeider gjennom et nettverk for å løse en oppgave. Hver enkelt beskjed som sendes fra en maskin til en annen har alltid en asymmetrisk natur - det er klienten som sender en beskjed til en tjener, og tjeneren svarer. Dette ligner på et prosedyrekall i et programmeringsspråk, hvor det er en som kaller (klienten) og en som blir kalt (tjeneren).

For å få utviklingen av distribuerte programmer til å ligne mest mulig på utviklingen av andre slags programmer liker vi å fremstille distribuerte programmer slik; at meldinger over nettet ligner på prosedyrekall, og meldingsinnholdet er parametrene. Returverdien til en slik funksjon er innholdet i en "svarmelding" som sendes motsatt vei.

Denne programmeringsmetoden kalles "Remote Procedure Call" (RPC), og den skaper denne illusjonen av nærværende prosedyrer ved å la fjernprosedyrer representeres lokalt av en "stub" prosedyre. En stub ser ut som den virkelige prosedyren, men inneholder ingen annen funksjonalitet enn å bidra til at parametrene og returverdien overføres i nettverket. Disse stub-prosedyrene lages ikke manuelt, men automatisk basert på en beskrivelse av fjernprosedyrens grensesnitt (navn og parametertyper).

Og nederst ligger nettverket

I bunnen av et slikt system ligger en nettverksprotokoll som skal overføre den resulterende meldingen. Inni denne meldingen ligger parametrene som er brukt. Overføringen av parametre er en komplisert prosess. Her er noen ting som en slik protokoll må ta hensyn til:
  1. Datatyper er representert forskjellig i ulike maskintyper. Et heltall kan ikke flyttes mellom en Motorola- og en Intel-CPU uten konvertering, fordi de tolker de samme bitene til å bety ulike tallverdier. Overføringsprotokollen må derfor sørge for den nødvendige konverteringen.
  2. Sammensatte datatyper (objekter) kan ha pekere til andre objekter. En peker kan ikke overføres som en vanlig dataverdi, man må passe på at de peker dit de skal etter overføring (det som de peker på må også være overført).
  3. En vanlig form for parameteroverføring er å sende en peker til en dataverdi fremfor å sende dataverdien selv (pass-by-reference). Gjennom pekeroverføring kan klienten og tjeneren dele en datavariabel i et lokalt system. Dette er kjempevanskelig å få til ved bruk av fjernprosedyrer, fordi det krever at datavariabler blir synkronisert mellom partene før, etter og endog under utførelsen av fjernprosedyren.
  4. Flere programmeringsspråk har en "nødutgang" fra prosedyren i form av Exceptions (Java og C++ har dette). Dette er ingen vanlig returverdi, men en "unntakstilstand" som kommer i retur fra prosedyren som blir kalt.

En slik nettverksprotokoll har en tendens til å bli meget komplisert, og bruken av den krever ganske omstendelig "mellomvare", i form av prosedyrebibliotek og hjelpeprogrammer (f.eks. for å lage stub-prosedyrene).

Ulempe 1:

Selv de enkleste klient-tjener anvendelser er henvist til å bruke denne mellomvaren. Om du bare trenger å lese av en klokke eller en temperaturverdi, må både klienten og tjeneren ha "full pakke" installert. Dersom tjeneren er en ganske enkel liten mikrokontroller med et mikro-OS, er dette oftest umulig.

Vi ønsker oss en alternativ nettverksprotokoll som lar oss "manuelt" gå inn i protokollen og lage og lese meldingene uten bruk av komplisert mellomvare. En protokoll og et meldingsformat som er så enkelt at et par hundre linjer med programsetninger kan betjene den nødvendige kommunikasjonen.

Ulempe 2:

En nettverksprotokoll for RPC-bruk er lite brannvegg-vennlig. Med det mener vi at en normal måte å sette opp en brannvegg på vil ha en tendens til å blokkere de meldingene som skal sendes. Dette kan skyldes:

Dersom man klarer å benytte en "kjent" internet-protokoll (Web, E-mail, FTP) til RPC-formål, kan vi oppnå at rekkevidden av de tilbudene som tjeneren gir kan blir mye større i Internet-verdenen.

Remedium 1: XML

XML (eXtensible Markup Language) er en måte å kode data på. XML er velegnet for mange formål hvor dataene trenger å være strukturert, dvs. være i en kontekst (f.eks. for det er avgjørende om en E-post adresse representerer en avsender eller en mottager). XML er velegnet for bruk i en RPC-protokoll, fordi den kan i tillegg til parameterverdier overføre strukturerte data (objekter) og navn på prosedyren. Et XML-"dokument" inneholder bare tekst, noe som gjør det lett å lese med "det blotte øye", og lett å lage og forstå (kan programmeres med vanlige funksjoner for å behandle tegnstrenger).

Remedium 2: HTTP

En RPC-protokoll kan gjøres veldig avansert, men vil i sin vanligste form kun forlange at en melding blir sendt fra klienten til tjeneren og en returmelding returnert tilbake fra tjeneren til klienten. For dette formålet er de enkle Internet-protokollene velegnet, og protokollen HTTP (for bruk med WWW) i særdeleshet. HTTP er laget med nettopp det formål for øye å sende en melding til en tjener og få et svar tilbake. Samtidig er HTTP ikke engasjert i hvordan innholdet er kodet, så det går utmerket å sende et XML-dokument med HTTP (trenger ikke å være HTML-kodet melding).

Og så har HTTP den fordel at den er godt kjent av brannvegger, som nesten alltid slipper slik trafikk forbi, i det minste der hvor klienten er på "innsiden" og tjeneren på "utsiden" av brannveggen.

Dette er SOAP

Og SOAP er nettopp dette: En RPC-protokoll som baserer seg på XML-kodede meldinger oversendt med HTTP-protokoll. Da oppnår vi en mulighet for å "gå til fots" i utviklingen av klient-tjener applikasjoner, og å ta i bruk disse metodene uten kostbare kjøretidsmiljøer eller mye krangel med brannveggene.

SOAP er en spesifikasjon laget av WorldWideWeb Consortium (W3C) og baserer seg som sagt på XML. SOAP sier egentlig ikke at HTTP er nødvendig, men at mange slags protokoller kan brukes. Vi venter oss lite bruk av SOAP på andre protokoller derimot, siden HTTP er såpass skreddersydd for dette formålet.

SOAP sier ikke bare at meldingene skal være XML-kodet, men gir en del nærmere bestemmelser om hvordan meldingen skal bygges opp og hvilke XML-egenskaper som skal brukes (bestemmer f.eks. bruk av diverse "namespaces").

Et eksempel på en melding og et svar i SOAP er vist i tekstboksen. I motsetning til mange andre protokoller vil SOAP som nevnt overføre alle data som "lesbare" meldinger. Det innebærer at programvaren kan bruke vanlige tegnstreng-funksjoner for å lese og skrive dataene, men ikke minst viktig er det at en slik melding kan leses av mennesker. For en person med kjennskap til SOAP-protokollen kan det å lese meldingen slik den overføres gjøre feilfinning og testing mye enklere.

Forholdet til CORBA

Merk at SOAP ikke erstatter CORBA, DCOM eller andre plattformer for distribuert programmering. SOAP er en nettverksprotokoll som i noen utstrekning kan erstatte den nettverksprotokollen som disse arkitekturene benytter seg av. Et CORBA-produkt inneholder mye mer enn bare transportmekanismer.

Kan SOAP brukes som nettverksprotokoll i store klient-tjener anvendelser basert på f.eks. CORBA? Ja, det kan det i noen utstrekning, men noen av egenskapene ved CORBA's nettverksprotokoll (kalt IIOP - Internet Inter-Orb Protocol) er vanskelig å få til med SOAP, men det kommer vi tilbake til litt senere i denne artikkelen.

Kommersielle CORBA-produkter som Orbix beveger seg i retning av å utnytte SOAP, og de har demonstrert prototyper på dette. Noen utviklingsverktøy som lar oss studere SOAP implementasjonen i detalj er derimot ikke tilgjengelig, så noen av våre uttalelser om forholdet mellom CORBA og SOAP er antagelser.

Et CORBA-produkt vil inneholde verktøy for å lage prosedyre "stubs", og for å ta i bruk SOAP må dette verktøyet endres slik at stub-prosedyrene lager meldinger kodet etter SOAP-regler, ikke lenger etter IIOP-regler. I tillegg må hjelpeprosedyrene for kjøremiljøet støtte bruk av HTTP-protokollen.

En CORBA-tjeneste tilbudt via SOAP-protokollen har som tidligere antydet den egenskap at motparten (klienten) ikke trenger å være en full CORBA-klient, men kan være en liten mikrokontroller programmert i assembler, eller et PC-program programmert i et språk hvor det ikke finnes CORBA-støtte lett tilgjengelig (vi har f.eks. aldri hørt om CORBA for Perl).

Objektorientert?

CORBA er et rammeverk for fjernobjekter, ikke fjernprosedyrer. Forskjellen er at du i det første tilfelle ikke snakker til en prosedyre, men et objekt. Objektet kan være ett av flere av samme klasse, og kanskje er dette objektet bare ditt som representerer deg på tjenersiden. Inni objektet ligger kanskje handlekurven din, kontonumrene dine eller ditt brukernavn og passord.

Objekter er bra å ha i et programmeringsspråk, men objekter må skapes og fjernes (lifecycle management). I et lokalt objektmiljø oppstår objekter ofte gjennom eksplisitt instansiering (en new-operasjon) og fjernes gjennom en prosess som kalles garbage collection. Garbage collection sørger for å fjerne objektet når det ikke lenger er noen som henviser (peker) til objektet.

I CORBA er det ikke mulig å skape fjernobjekter med new-operasjonen, men man ber et objekt hos tjeneren (et fabrikkobjekt) om å skape et. Objektet fjernes ved at vi bruker distributed garbage collection (DGC), som innebærer at en henvisning til et fjernobjekt blir vedlikeholdt gjennom regelmessige meldinger (hjerteslag) i nettverket. Når disse meldingene opphører, ansees henvisningen som borte, og objektet kan etterhvert fjernes når alle henvisningene er borte.

DGC er ikke mulig å til i SOAP, men det finnes alternative metoder, kalt leasing. Leasing innebærer at en klient sier "dette objektet trenger jeg i 5 minutter", og etter denne tiden opphører henvisningen dersom det ikke er kommet en ny leasing-melding. Leasing krever noe mer programmering på klient-siden, men metoden skalerer bedre enn DGC, og foretrekkes derfor i mange sammenhenger. Lifecycle Management basert på Leasing er mulig å få til med SOAP.

Konklusjon

Hva vi liker med SOAP er at den senker terskelen for å lage klient-tjener applikasjoner. Helt uten CORBA kan du lage en tjener dersom du skriver kode for en HTTP-tjener (ca. 100 programlinjer) og har en XML-parser (finnes gratis for mange språk) og noe programmeringskunnskap. Det du da kan lage er en tjener som kan utnyttes fra alle slags klienter og alle slags programmeringsspråk. Du kan også beskrive tjenesten din (i form av en IDL-fil) slik at en CORBA-klient også kan utnytte den. Det er mulig at du må lage flere "interfaces" til tjenesten din for å kunne støtte flere CORBA-produkter, siden det kan tenkes at de bruker SOAP-protokollen på ulike måter. Det gjenstår å se.

Sitatbokser:

Tekstboks:

En SOAP-melding (noe forenklet) som representerer prosedyrekallet SetTermostat(22.1) i tjeneren Termostat:
POST /Termostat HTTP/1.1
Content-Type: text/xml;
Content-Length: xxxx

<Envelope>
   <Body>
      <SetTermostat>
		<verdi>22.1</verdi>
	</SetTermostat>
   </Body>
</Envelope>