Læg data i ?skyen?
I sidste post skrev jeg om 'Byggeklods services' og begyndte så småt at diskutere hvordan disse kan bruges i en web applikation. I denne post tager jeg fat i SQL Server Data Services og giver en kort introduktion.
!RDBMS
Data kan vi lægge på disk og selv opbygge en struktur så vi kan skabe, læse , opdatere og slette vores data (CRUD). Typisk foretrækker vi dog et database system, som sikre en fornuftig indeksering, relationer, integritet, rapportering osv. De fleste af os arbejder i den forbindelse med relationelle databaser.
Med 'sky'-databaser forholder det sig en smule anderledes og sky-databaser som jeg har kigget på er ikke traditionelle RDBMS?er. Deres primære funktion er at udstille en database gennem en simpel model, som kan manipuleres via et webservices api og som understøtter CRUD.
For at citere dokumentationen på Amazons SimpleDB: 'Today, many developers correlate the word "database" with Relational Database Management Systems (RDBMS). While RDBMS offerings provide deep functionality, for many use cases, they introduce more complexity (and more cost) than is necessary. Many developers simply want to store, process, and query their data without worrying about managing schemas, maintaining indexes, tuning performance or scaling access to their data.?
Og Googles App Engine Datastore: 'The App Engine datastore is not a relational database. While the datastore interface has many of the same features of traditional databases, the datastore's unique characteristics imply a different way of designing and managing data to take advantage of the ability to scale automatically.'
Det samme er tilfældet med Microsofts SQL Server Data Service (SSDS), som, på trods af navnet, heller ikke er en relationel database. Hver af de tre leverandørers 'sky'-database har sin egen model. Fælles for dem er at de er relativt simple. Jeg vil i det følgende give eksempler på en sådan simpel model ved hjælp af SSDS.
SSDS Model - Authority, Container og Entity
Den meget korte introduktion til disse begreber er en Authority kan indeholde en eller flere Containers, som kan indeholde en eller flere Entiteter. Hvis jeg skal forsøge at drage en parallel til RDBMS så kan man opfatte Authority, som en database, Container som tabeller og Entities som tupler i tabellerne. Det er så ikke hele sandheden, men for nu er det ok til en introduktion.
Webservices administration Kommunikationen til SSDS foregår enten ved hjælp af et SOAP eller et REST API. Eksempel på oprettelse af en database (SOAP/C# - proxy autogenereret på baggrund af service WSDL):
//createAuthority('foo-dyrefoto'); static public void createAuthority(string authorityId) { using (SitkaSoapService Client proxy = new SitkaSoapServiceClient()) { proxy.ClientCredentials.UserName.UserName = "xxxxxxx"; proxy.ClientCredentials.UserName.Password = "xxxxxxx"; Scope serviceScope = new Scope(); Authority auth = new Authority(); auth.Id = authorityId; proxy.Create(serviceScope, auth); } }
Metadata for den netop oprettede authority vil kunne hentes via HTTP GET på: http://foo-dyrefoto.data.beta.mssds.com/v1
Den næste trin bliver at oprette en tabel (Container) i vores database (Authority, som nu hedder foo-dyrefoto). I mit tilfælde vil jeg oprette en Container, som hedder 'billeder'. En Container skal have en unik id.
Denne skal placeres i et bestemt namespace ('http://schemas.microsoft.com/sitka/2008/03) ? se createContaner nedenfor!
Eksempel på oprettelse af contaner i uddrag (Java/Rest):
public class CreateContainerUsingREST { final private static String authorityId = "foo-dyrefoto"; final private static String sampleContainerId = ?billeder"; final private static String ssdsContentType = "application/x-ssds+xml"; final private static String HttpPostMethod = "POST"; public static void main(String[] args) { //mangler tildeling af credentials String AuthorityUri = String.format("https://%s.data.beta.mssds.com/v1/", authorityId); CreateContainer(AuthorityUri); } private static void CreateContainer(String authorityUri) throws IllegalArgumentException { final String ContainerTemplate = "" + "%s" + ""; if (authorityUri == null || authorityUri.isEmpty()) { throw new IllegalArgumentException("authorityUri"); }
De sidste jeg vil vise i forbindelse med oprettelse af data, er entities i min container(database). Mine entity skabelon med eksempel data ser ud som følger:
Billede1 Humpbackwhale.jpg Havdyr En han pukkelhval fotograferet under efterårstræk mod... 20 DKK QUasjkl....=
Som det kan ses af denne entity så har SSDS understøttelse for Xml Schema typerne 'string' og 'base64binary'. Derudover understøttes 'boolean', 'decimal' og 'DateTime'. Sidst men ikke mindst er der BLOB support, som pt kun kan bruges over REST.
Et eksempel på oprettelse af en entity med C# og REST:
public static string CreateImage(string id, string title, string category, string description, string price, string data) { const string EntityTemplate = @" {0} {1} {2} {3} {4} {5} ";
return String.Format(EntityTemplate, id, title, category, description, price, data); }
public static string CreateEntity(string containerUri, string requestPayload) { const string HttpPostMethod = "POST"; const string XmlContentType = "application/x-ssds+xml"; string entityUri = null; WebRequest request = HttpWebRequest.Create(containerUri); request.Credentials = new NetworkCredential(userName, password); request.Method = HttpPostMethod; UTF8Encoding encoding = new UTF8Encoding(); request.ContentLength = encoding.GetByteCount(requestPayload); request.ContentType = XmlContentType; using (Stream reqStm = request.GetRequestStream()) { reqStm.Write(encoding.GetBytes(requestPayload), 0, encoding.GetByteCount(requestPayload)); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { entityUri = response.Headers[HttpResponseHeader.Location]; }
return entityUri; }
static void Main(string[] args) { string ContainerUri = String.Format("https://{0}.data.beta.mssds.com/v1/{1}", authorityId, containerId); string requestPayload = CreateImage("Billede1", Humpbackwhale, "Havdyr", "En han pukkelhval fotograferet under efterårstræk mod...", "20 DKK", getBase64binaryImage(@"C:\pics\humpbackwhale.jpg")); CreateEntity(ContainerUri, requestPayload); }
Når jeg så har oprettet min database med Authority, Container og muligvis lidt mere data aka Entities er jeg klar til at spørge på data. Det er ikke SQL, som bruges hos hverken Amazon, Google eller Microsoft, hver leverandør implementere sit eget forespørgelsessprog. I SSDS er der tale om et sprog, som til forveksling ligner LINQ.
Her er et HTTP GET eksempel: http://foo-dyrefoto.data.beta.mssds.com/v1/billeder?q='from e in entities where e["Kategori"]=="Havdyr" select e'
Med den antagelse at jeg kun har en entity med kategorien 'Havdyr' får jeg følgende retur:
Billede1
19852
Humpbackwhale.jpg
Havdyr
En han pukkelhval fotograferet under efterårstræk mod...
20 DKK
QUasjkl....=
Som det kan ses af svaret er der kommet et 'Version'-element på denne entity. Udover 'Id' og 'Version' som vil være at finde på en Entity's metadata kan man også bruge den 'Kind' ' denne vil typisk sættes på hvis man har entities af forskellig type i en Container.
Opsummering
Det var et første kig på en af de data services, som findes på nettet. Jeg har ikke set meget på Google App Engine Datastore, men kan umiddelbart læse mig til at applikationer, som gør brug af Googles dataservice skal afvikles på Googles servere og pt kun kan skrives i Python (jeg vil dog meget gerne rettes hvis der er andre som har erfaring med denne service).
Amazon Simple DB og Microsoft SSDS er 'klassiske'webservices med løskobling i databehandlingen gennem REST og SOAP API'er. Fælles for API'erne er at de alle indeholder den forsinkelse, som forespørgelse på en database, der kun er tilgængelig over HTTP, indeholder. Det betyder at som med hvilken som helst anden webservice er programmeringsmodellen, design og arkitekturen sandsynligvis en ganske anden end hvis klientapplikationen lå direkte 'oven på' databasen. På trods af dette vil min næste web applikation komme til at benytte en data service, SSDS, som datalag.
Amazon SimpleDB og Microsoft SSDS er begge i beta og kommer begge til at have en betalingsmodel tilknyttet. I dokumentationen for SimpleDB er der kodeeksempler i Java, C#, Perl, PHP og VB.Net. I SSDS kommer eksemplerne i C#, Java og Ruby.
I de næste indlæg i denne could service serie bevæger jeg mig længere op i stakken og kigger bl.a på Identity management, message passing/transformation og Workflow. [/i]
Kommentarer (1)
Vi har i vores firma et slogan der hedder:
“Databases are just containers: It’s the content that matters.”
Et spændende element ved data i skyen er de enorme muligheder der ligger i at kunne udnytte data, der allerede er opsamlet et andet sted.
For at kunne udnytte dette, er det dog ikke nok at have fælles protokoller. Vi er også nødt at have en fælles definition, navngivning og identifikation af data – eller i det mindste håndtere, at dette er et for stort krav.
Hvis du for eksempel ønsker at vide noget om:
• Oehlenschlægersgade 213 i København
måske for at lave en mashup eller på anden måde at sammenstille data – så har du et problem, når andre data sandsynligvis er lagret under:
• Øhlenslägersgade 213, København V
• Oehlenschlægersgade 213, baghuset, 1663
Byggeklodstjenester til datalaget kan derfor, ud over de rent tekniske og logistiske anvendelser, også bidrage med:
• Indhold i form af konkrete data lige fra valutakurser og postnumre optil store fortegnelser om alverden, som du så kan få forærende – eller nemt købe
• Intelligens til at identificere, strukturere og klassificere data

