Võta Silverlight siit.

Windows Azure

Windows Azure on oma olemuselt serverimajutusteenus, aga tegelikult võib seda nimetada omaette operatsioonisüsteemiks. Klient paneb üles oma .NET-rakenduse ja Microsoft jooksutab seda. See on sarnane sellega, mida UNIXi baasil on aastaid pakutud: paned oma failid üles ja majutaja hoolitseb ülejäänu eest. Ainult et see kõik on nüüd kättesaadav .NET-maailmas.

Jätame täiesti kõrvale teema kas Linux või Windows, PHP või Java või C#. See sait ja Azure on inimestele, kes ütlevad, et Windows ja C#. (Kuigi, jah, Azure'ile on saadaval ka Java, PHP ja Ruby SDK-d, aga kas see on mõttekas, ma ei tea.)

Miks eelistada Azure'i oma serverile?

Lühidalt öeldes: süsteemiadministraatorit ei ole vaja ja riistvarameest ei ole vaja ja internetiteenuse pakkujat ei ole vaja ja varundamist ei ole vaja. Lihtsalt kirjutad tarkvara ja paned üles ja seal ta tiksub päevast päeva.

Tarkvara arendamine on muidugi suur kulukoht, aga igapäevased kulud koosnevad suuresti just neist ülal nimetatud punktidest.

Azure'is ei ole peaaegu midagi vaja konffida. Andmete säilivus on tagatud, viirusi ei tule, operatsioonisüsteemi uuendusi ei pea tegema, tulemüüri ei ole vaja, kettad ei sure. Internetiühendus ei katke. Kõik need jamad olemata, mis mulle suurimat minu-suurimad-mured-oma-serveri-pidamisel|meelehärmi on teinud.

Kas Azure on rahaliselt mõttekas?

Jah, on. Ühe rakenduse pidamine Azure'is maksab alates umbes 60 eurost kuus. Hind kasvab vastavalt andmemahtudele, aga see ongi asja võlu, et kasvamisruumi on tohutult: toru kitsaks ei jää, maksad vastavalt rohkem ja saadki rohkem.

Tegelikult maksab sama palju korralik internetiühendus. Aga oma ühenduse korral tuleb lisaks sellele server osta, kulutada selle administreerimisele ja hooldusele jne. Nii et Azure on tõepoolest mõttekas.

Mida Azure sisaldab?

Windows Azure on koht, kuhu saab oma rakenduse üles panna. Sellel on ühe rakenduse kohta 250GB kõvakettaruumi. Eraldi teenus on sql-azure|SQL Azure, mis on sisuliselt tavaline MS SQL Server mõningaste kitsendustega (administreerida pole midagi). Lisaks pakutakse otse netist ligipääsetavat azure-storage|andmemajutust. Klõpsa eeltoodud linkidel, et iga komponendi kohta lisa lugeda.

Mis rakendusi Azure'is kasutatakse?

Azure on mõeldud .NET-rakendustele. Selle programmeerimiskeeled on niisiis C# ja VB. Azure'i jaoks saab kirjutada Visual Studios ja seal saab kasutada tavalisi .NETi teeke. Rakendusest tehakse pakett, mille Visual Studio oskab ise üles panna. Alustamisõpetust vaata kuidas-alustada|siit.

Azure kommertslahendusena

Azure on ideaalne edasimüüjatele, kes pakuvad ise selle peale tarkvaarendust, kuna nad saavad keskenduda puhtalt arendusele ja optimeerida edasimüüdavaid ressursse. Eestis pakub sellist teenust näiteks Semitar OÜ.

Ajutised load Azure'i salvestile

Azure'i blobidele saab väljastada ajutisi ligipääsulubasid. See on kasulik näiteks juhuks, kui pärast sisselogimist on vaja veebikliendile ligipääs, nii et veebiklient kirjutab otse blobi, hõivamata serveri ressursse. Mina ise leidsin selle eriti kasulik olevat, kuna nii saab mõne rakenduse puhul Microsoftile CPU eest mitte eriti maksta.
Ajutine luba on väljastatav kuni 1 tunniks, see võib olla nii lugemiseks kui ka kirjutamiseks, sellel on algus- ja lõpukellaaeg.

Lihtne taotleda

Loa saab loomulikult taotleda ainult see, kellel on salvesti ligipääsuvõti.

CloudBlobClient client = new CloudBlobClient(address, credentials);
CloudBlockBlob blob = client.GetBlockBlobReference("katse/katse.txt");
DateTime dt = DateTime.Now.ToUniversalTime().AddMinutes(-1);
string s = blob.GetSharedAccessSignature
(
  new SharedAccessPolicy 
  { 
    Permissions = SharedAccessPermissions.Read | SharedAccessPermissions.Write, 
    SharedAccessStartTime = dt, 
    SharedAccessExpiryTime = dt.AddHours(1) 
  }
);


Nagu näete, ei ole keeruline. Muutujasse s pannakse mingi selline sigri-migri:

?st=2010-12-09T09%3A52%3A50Z&se=2010-12-09T10%3A52%3A50Z&sr=b&sp=rw&sig=rVFDah2Qtac98%2B4hlMegIUPH93%2BJPszZH27plzmXe9Q%3D


Selle saab lisada blobile ligi pääsemisel blobi aadressile. See meetod on eriti mugav http-päringuid (REST-päringuid) tehes, sest mingit autoriseerimist ja eripäiseid vaja ei ole.

Tühistada ei saa

Ainuke viga sellise loa juures on see, et seda ei saa tühistada. Näiteks kui klient välja logib, siis luba jääb ikka kehtima. Kriitiliste rakenduste jaoks tuleks ilmselt loa kehtivusaega lühendada. Aga muidu igati vinge asi.

Andmeturg on avatud

See, mis oli varem tuntud varjunime all "Dallas", on nüüd Windows Azure Marketplace DataMarket. Ja minu rõõmuks jookseb Azure'i peal, saadaval sellises kohas nagu datamarket.azure.com.
Kohe sisenedes võtab meid vastu plakat One stop shop for Data ehk "ühe poeskäiguga kõik andmed". See veel päris nii ei ole, sest kuigi lette on palju, on memmesid nende taga müümas veel suhteliselt vähe. Töö algab tasa ja targu, sest see, mis suure käraga lahti tehakse, põleb ruttu maha (vähemalt kui turuhoone on puust).

Vaatame mis leti peal pakutakse

Andmed on ilusti purgistatud ja kategooriate järgi osakondadesse jaotatud. Silma paistab suhtumine, et väiketarbija saab tasuta.
Igihuvitav teema Ilm on eraldi kategooria. Nii-nii, ma valin sealt ühe Super-Micro-Cast-Fast asjanduse.
Selgub, et esiteks tuleb ikka Live ID abil sisse logida. Ja siis registreeruda. Ja siis andmed tellida ning nõustuda tingimustega. Okei, kõik tehtud, ilma midagi läbi lugemata.
Nüüd läheb põnevaks. Help on saadaval lingist "Learn how to use this data in Visual Studio" ja tuhat rida koodi on saadaval lingist ".NET C# Class Library". Põnev!
Teen uue Console Application projekti. Lisan alla tõmmatud koodi projektile. Lisan projektile viite teegile System.Data.Services.Client.
Ma ei viitsi seda helpi lürpida, asun kohe koodi rebima. Ja tõepoolest, 5 minutiga on tulemus käes:


using System.Net;

namespace TestDataMarket
{
  class Program
  {
    static void Main(string[] args)
    {
      WeatherCentral.SuperMicrocastContainer c = new WeatherCentral.SuperMicrocastContainer(new Uri("https://api.datamarket.azure.com/data.ashx/WeatherCentral/SuperMicrocast"));
      c.Credentials = new System.Net.NetworkCredential("tan@semitar.com", "/adfdfalkj6938532y9r8wfr9328r239r48yrsfsdfsfs=");
      
      foreach (var result in c.GetSummaryDailyForecast(58.4, 26.7, "3:00:00", "metric"))
        Console.WriteLine(result.Day + " " + result.TemperatureMin + ".." + result.TemperatureMax);

      Console.ReadLine();
    }
  }
}

//tulemus, mida on kunagi suvel tore lugeda
Monday 3.9..4
Tuesday 4.2..6.4
Wednesday 4.4..7.7
Thursday 4.4..6.8
Friday 1.9..5.7
Saturday -1.7..3.7
Sunday -2.8..2.1
Monday -2.9..3.1
Tuesday 1.3..2
Wednesday 1.4..3.6
Thursday 3.9..8.4
Friday 2.3..8.8
Saturday 1.4..2.2
Sunday 0.8..1.5
Monday 1..3.3
Tuesday -0.2..3.5



Vau! Nii lihtne oligi!
See Uri on andmete lehel pealkirja Details all leiduv aadress. Kasutajatunnus on sinu Live ID meiliaadress ja salasõnaks on sinu konto all antav võti (ärge nähke vaeva, ma vahetasin oma võtme suvalise teksti vastu).
Protseduure erinevate andmete saamiseks on mitu, aga see siin tahab lisaks laius- ja pikkuskraadidele (minu näites Tartu) saada ka ajavööndit (tundides UTC suhtes) ja mõõtühikute süsteemi. Pane kasvõi kohe oma ilm.ee püsti.

Mis andmeid sinna postitada?

Minu mõtted lähevad kohe sinna, et meie e-riik võiks ju hakata sinna postitama kõikvõimalikku statistikat. Sakslastel pidi mingi linnake olema, mille elanike peal katsetatakse uusi asju. Eesti võiks itivaldkonnas sama teha. Nende andmete eest saaks ju raha küsida, rääkimata sellest, kui kasulikud oleksid need kohalikele ettevõtjatele.
Rahvaloendus on tulemas, siin võiks avaldada statistika... Oot, ja meie geenid on ka mingis varamus vist? Telefoniraamatud ja sellised värgid... loetelu jätkub ja jätkub.
Väga vinge asi.

Azure ja paljas domeen

Windows Azure lubab sul valida unikaalse teenusenime ja annab sulle veebiaadressi nimi.cloudapp.net. Nii on see kõigil ja puudub võimalus kasutada oma domeeninime.
See kõik ei ole probleem, ainult et... IP-aadress pole kunagi staatiline.
Nii, oletame, et oled registreerinud endale nimi.com või nimi.ee või mingi muu. Sellele sa saad DNSis teha A-kirje, mis vajab IP-aadressi. Aga seda pole. Appi tuleks dünaamiline IP, aga see ka ei sobi.

Miks dünaamiline IP ei sobi

Dünaamiline IP on ehitatud sellele ideele, et sinu arvutis on klient, mis võtab teatud aja tagant ühendust dünaamilise IP teenuse pakkujaga ja too teenusepakkuja vaatab, ahah, ahsoo, milliselt IP-aadressilt see päring tuli, tohoh, ongi aadress muutunud. Ja muudab sinu A-kirje ära. Samuti eeldab dünaamiline IP seda, et DNSi TTL ehk eluiga on lühike, mis sunnib kõiki nimeservereid maailmas oma infot iga minut uuendama. Ja nii ongi, et paari minuti jooksul teab juba terve maailm, et sinu IP on muutunud.
Aga Azure'iga see kõik ei toimi sel lihtsal põhjusel, et sul pole sedasamust dünaamilise IP klienti, mis keskusse helistaks, kuskile pista. Sul on seal üldjuhul ainult veebiroll, mis ärkab ellu selle peale, kui keegi sinu veebilehele läheb. Hehehee, ja kui sinu IP-aadress on vahepeal muutunud, siis ei lähegi keegi kunagi sinu veebilehele ja ka sinu dünaamilise DNSi pakkuja ei saa teada, et see on muutunud.
Maailmas on kümneid, ilmselt sadu dünaamilise DNSi pakkujat, ja mitte üksainuski neist ei tea, mis asi on Azure. Kõik suruvad oma keskusse helistavaid kliente. Mulle pakuti isegi sellist varianti: "Kas teil siis kodus arvutit ei ole, mis kontrolliks teie serveri IP-aadressi ja annaks meile teada, kui see on muutunud?" Müristuste müristus! Ma maksan Azure'i teenuse eest selleks, et see oleks 99,99999.... protsenti kindel värk ja siis sõltub kogu minu serveri elu ainult sellest, kas keegi kuskil naabermaja taga koppa maasse ei löö või tuul puuoksa elektritraadi otsa ei puhu! Elik, kokkuvõte -- põlegi Azure'i jaoks sobivat DNS-teenust.

Mis vahe on "paljal" ja "riides" domeenil?

Paljas ehk inglise keeles "naked" on domeeninimi, mille ees pole www-d ega midagi, on ainult nimi.com. Mul endal on kalduvus aadresse veebisirvijasse just sellistena kirjutada.
Mõned inimesed kirjutavad alati www ette, isegi siis, kui seda ei tohi teha. Nendega on lihtne. Nimelt on erinevus selles, et paljale domeenile saab teha ainult A-kirje, aga alamdomeenile ehk riides domeenile saab teha ka CNAME-kirje.
CNAME on sisuliselt suunamine, mis ei vaja sihtkohaks mitte IP-aadressi, vaid teist domeeninime. Nii võid teha CNAME www.nimi.com nimi.cloudapp.net ja kõik töötab nagu õlitatult. Aga satub sinu Azure'i lehte proovima mõni jultunud tegelane, kes www-d ette ei pane ja ongi mulje, et server maas.
Ja selle jaoks, et niisugust probleemi välistada, tuleb teha imetrikke.

Imetrikid palja nime lubamiseks Azure'is ehk plaan B

Plaan B oleks siis selline, et sul on kuskil miski server, mis on staatilise IP-aadressiga ja A-kirje on tehtud selle aadressile. Kui sellele tuleb klient, kes tahab minna aadressile nimi.com, siis see server ei tee muud kui suunab kõik päringud aadressile www.nimi.com.
See kõik tõmbab Azure'i usaldatavusele vee peale, kui sinu server on nõrgim lüli.
Õnneks pakuvad mõned DNS-teenuse osutajad ka WebForwardi või URL Redirecti nimelist teenust, mis seda (pahatihti lisatasu eest) siis sinu eest teeb.

Miks CNAME-lahendus pole ideaalne

Sellel on ka miinuspool: kasutaja kirjutab veebisirvijasse nimi.com, DNSist küsitakse selle nime IP-aadress, siis minnakse sinna serverisse ja tehakse veebipäring. Sealt öeldakse, et vabandage, aga te tulite valesse kohta, õige koht on hoopis www.nimi.com. Noh, ok, siis tehakse uus päring DNSi, et uurida, kus see www.nimi.com veel asub. Sealt vastatakse, et see on hoopis nimi.cloudapp.net. Siis tehakse kolmas DNSi päring ja küsitakse, et kes see nimi.cloudapp.net selline on. Noh, sealt saadakse õige IP-aadress, kuhu võib siis külla minna ja veebilehe alla tõmmata. Kolm korda rohkem tõmblemist, nagu näete, aga muud võimalust hetkel polegi.

Azure ja selle lähim tulevik

Microsoft on võtnud eesmärgiks lihtsustada olemasolevate rakenduste viimise pilve ja pakkuda täisteenust.
Lähemad eesmärgid hõlmavad admin-taseme ligipääsu ja kaugtöölauda. Virtuaalmasinaid hakkab saama laadida virtuaalkettalt. SQL Azure'ile lisatakse uued andmesünkimisvahendid ja uus SQL Azure Reporting.
Maarjamaalastele teeb rõõmu odavama ja lihtsama "mikro"-Azure'i tulek.
Microsoft on pilve kohta öelnud, et nad on "all in". Ehk et tulevik on täiesti pilves. See võtab aastaid, aga algus on minu arvates olnud väga hea.

Azure ja Silverlight

Silverlighti rakenduse tegemine Azure'is on täiesti võimalik, nagu tõendab käesolev rakendus. Aga Silverlight on natuke pirtsakas küll.
Esiteks, mul ei ole veel õnnestunud see variant, et XAP-fail on blobis ja HTML tuleb Windows Azure'ist. Kui teil on selle jaoks lahendus, siis jagage. Minul on hetkel nii tehtud, et veebiteenus võtab Silverlighti XAP-faili blobist ja hoiab seda mälus kõigi jaoks, kes küsivad.
Blobi ei saa teha samasse domeeni kus on Windows Azure, küll aga saab teha alamdomeeni. Näiteks on mul blob.azure.ee ja *.azure.ee (viimane siis Windows Azure). Selleks, et Silverlight oleks nõus alamdomeenist infot küsima, tuleb sellele luua juurkataloog (mahuti ehk container nimega $root) ja panna sinna ClientAccessPolicy.xml. Ära unusta selle juurkataloogi blobe ka avalikuks teha.
ClientAccessPolicy.xml on mingi taolise sisuga:
 
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
  <cross-domain-access>
    <policy >
      <allow-from http-methods="*" http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>


Teine võimalus on panna crossdomain.xml, mis on midagi taolist:
 
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*"/>
</cross-domain-policy>


Kolmas võimalus on panna mõlemad failid. Muidugi võid ligipääsu siis piirata, nii et domeenide ja uride koha peal ei ole mitte tärnid, vaid sinu veebiteenuse domeen.
Kui Silverlight suhtleb serveriga WCFi kaudu, siis see pole probleem, kõik töötab nagu kellavärk.

Silverlighti komponendi jagamine dünaamiliselt

Võib-olla sa ei taha Silverlighti XAP-faili paketi sisse panna. Muidu peaks paketi ringi vahetama pelgalt selleks, et Silverlighti komponendis miskit muuta.
Selle jaoks, et .xap-laiendiga failid tuleksid veebiteenusesse ja sa saaksid neid jagada, tee handler. Kirjuta see info oma rakenduse (rolli) Web.config-faili:
 
<system.webServer>
  <handlers>
    <add name="xap" path="*.xap" verb="*" type="Web.HttpHandler" resourceType="Unspecified" preCondition="integratedMode" />
  </handlers>
</system.webServer>


Üks handler võib handeldada ka mitut failitüüpi. See "Web.HttpHandler" on siis sinu koodis oleva handleri klassi nimi (Namespace.Class). See näeb välja umbes nii:

namespace Web
{
  public class HttpHandler : IHttpHandler
  {
    public void ProcessRequest(HttpContext context)
    {
      context.Response.Write(bytes, 0, bytes.Length);
    }
  }
}


Azure: kuidas teada, kas bloob on muutunud

Azure Storage paneb kõigile bloobidele külge ETag-atribuudi, mis muutub iga kord kui bloobi sisu muutub.
See on käepärane, et kindlaks teha, kas bloobi sisu tuleks uuesti alla tõmmata.
Seejuures tuleb tähele panna, et bloobile viite saamisel ei tõmmata midagi veel alla, seega tuleb esiteks teha FetchAttributes(), mis võtab salvestist bloobi päised. Etagi väärtuse võid salvestada koha peal järgmise kontrolli tarvis.

bool HasChanged(CloudBlob blob, ref string etag)
{
  blob.FetchAttributes();
  if (blob.Properties.ETag == etag)
    return false;
  etag = blob.Properties.ETag;
  return true;
}


Plokkbloobid

Ülaltoodu kehtib ka plokkbloobide korral, aga ETag muutub sel hetkel kui plokid on kehtestatud (pärast PutBlockList() väljakutsumist). Üksikute plokkide üleslaadimine veel midagi ei muuda.

Azure pani mul käntsa

Minu Azure'i rakendus, mis on kuude kaupa ilma mingite probleemideta üleval olnud, kukkus uppi, ja just sel ajal, kui olin reisil.
Proovisin restarti teha, aga see ei aidanud.
Selgus, et mul oli antud luba suurendada automaatselt rakenduse op-süsteemi versiooni. Proovisin panna see manuaalse peale ja aitas.

Põhjus selgus 2 nädalat hiljem, kui sattusin Microsofti uudise peale, mis teatab, et ketta cache vajab alates versioonist 1.8 20MB lisaruumi ja kõik varasemad rakendused, mis sellega ei arvesta, "will likely fail". Olgu nimetatud, et uudis tuli välja 2 päeva pärast uuenduse rakendamist.
Õppetund on see, et igaks juhuks ja selliste üllatuste vältimiseks hoidke oma versiooni manuaalselt fikseerituna.

Azure sai odavamad variandid

Windows Azure'i hindades on kaks uut säästuvarianti: Pay as you go ning Extra Small Instance.

Pay as you go

Kui varem pidi võtma kindla maksumusega paketi millel olid ettemakstud osad, siis nüüd võib valida ka sellise paketi, millel püsitasud puuduvad ja kasutaja maksab ainult reaalselt tarbitud kauba eest. See on kasuliku juhul, kui kõiki teenuseid täismahus ei vajata.
Vaata hindu ja pakettide võrdlusi siit.

Extra Small Instance

See on eriti hea uudis, sest enamus projekte on oma alguses vähenõudlikud. Veebiprojekti puhul sõltub ressursside vajadus otseselt külastatavusest ja on selge, et algtasemest on odavam alustada.

             CPU              Mälu    Salvesti  I/O jõudlus Tunnihind
Extra Small  1.0 GHz        768 MB       20 GB  väike           $0.05
Small        1.6 GHz       1.75 GB      225 GB  keskmine        $0.12
Medium       2 x 1.6 GHz    3.5 GB      490 GB  suur            $0.24
Large        4 x 1.6 GHz      7 GB    1,000 GB  suur            $0.48
Extra Large  8 x 1.6 GHz     14 GB    2,040 GB  suur            $0.96


Praegune Azure SDK ei võimalda veel seda Extra Small taset valida. Seda lubatakse 2010. aasta jooksul. Ilmselt tuleb siis SDK uus versioon.

Odav algus

Pay as you go ja tra small instancekombineerituna vähese kettamahuga võimaldavad alustada veebiprojekte $40 eest kuus, samas säilitades täieliku skaleeritavuse, sest taset saab mõne klõpsuga hõlpsasti tõsta. See ongi see, mis teeb Azure'ist nii ihaldusväärse.

Azure Storage

Azure võimaldab salvestada andmeid päris mitmekesiselt. Kohalik salvesti (Local Storage) on ainult ajutine ja selle andmed kaovad koos paketi uuendamisega. Kaugsalvesti on püsiv (ja varundamisega turvatud). See on pika võtme abil kättesaadav kõikjalt internetist.

Kohalik salvesti

Ühe rakendusühiku käes on 250GB andmeid, mis on kohalikul kõvakettal. Seda on enam kui küllalt, kuna andmed on ajutised (kehtivad kuni paketi vahetamiseni). Kohalikku salvestit saab konffida rolli atribuutide alt (Properties) ja see võib sisaldada mitut osa.

Kohaliku salvesti faili tee saab koodis teada nii (eeldades, et salvesti nimi on "LocalStuff"):

using Microsoft.WindowsAzure.ServiceRuntime;
using System.IO;
string GetLocalStuffPath(string filename)
{
  return Path.Combine
   (
     RoleEnvironment.GetLocalResource("LocalStuff").RootPath,
     filename
   );
}


Saadud failiteed saab IO-operatsioonides kasutada nagu tavalist teed.

Kaugsalvesti

Kaugsalvesti on kättesaadav üle interneti ja Windows Azure'i rakendused liginevad sellele samamoodi (üle interneti). See on ühtaegu hea ja halb.
See on hea sellepärast, et kaugsalvestis oleva info pärimine kolmandate isikute poolt ei koorma rakendust ning ei ole sõltuv rakenduse stabiilsusest. See on halb sellepärast, et kaugsalvestist info küsimine on muidugi aeglasem kui kohalikul kettal oleva info küsimine ja see suurendab välist andmeliiklust (mille eest küsitakse tasu).
Kaugsalvesti infosalvestusviise on mitmeid: Table, Queue ja Blob.

Table

See on sisuliselt koht, kuhu saab ID-dega varustatult üles panna XMLi. Teed koodis objekti (class) ja paned selle üles. XMLi moodustamine käib teegi sees ja on üpris primitiivne (ühetasemeline).

Queue

See on järjekord, kuhu saab panna ja kust saab saabumise järjekorras võtta sõnumeid. Kasulik juhul, kui erinevad tööriistad ja rakendused ei suuda muidu omavahel suhelda (ülesandeid jagada). Ühe rakendusega lahenduste puhul on sellele raske otstarvet leida, kuna järjekord on jäik (midagi vahelt välja võtta ega otsida ei saa).

Blob

Blob on nagu fail, kuhu võid salvestada mida iganes (binaarinfot või teksti). Blobidel on 2 alaliiki: Block Blob (võimaldab vahelekirjutamist) ja Page Blob (võimaldab info lisamist).
Blobid on mahutites (container) ja mahutites olevaid blobe saab veebis avalikkusele nähtavaks teha, kus nad on veebisirvijaga kättesaadavad. Vaata blobide kasutamise näidet siit.

Ketas

Kasutajale kõige mugavam variant on luua virtuaalne ketas. See toimib nii, et ketta sisu salvestamiseks tehakse ketta suurune Block Blob. Võimekuse parandamiseks on võimalik osa kohalikust salvestist (Local Storage) kasutada ketta vahemäluna.
Pärast ketta loomist saab selle poole pöörduda nagu mistahes ketta poole (küsides süsteemilt selle tee). Süsteem hoolitseb siis ise selle eest, et vahemälus olev info blobi uuendatakse ja vajaduselt sealt võetakse.
Kettal olev info säilib ka pärast paketivahetust, sest see on tagatud blobi säilimisega.
Ketta kasutusnäidist vaata siit.

Azure uue haldusliidesega ja v2

Azure'il on uus haldusliides. See on tehtud Silverlighti baasil ja on märksa parem. Kui eelmine liides oli tehtud postitavate veebivormide peal, kus pärast igat sammu terve leht uuesti sisse laeti ja kasutamine nõudis tükk aega ringi klõpsimist, siis nüüdne on tõeliselt mõnus. Saidid on kenasti puustruktuuris ja navigeerimine lihtne.
Vajakajäämistest ehk nii palju, et kui HTML võimaldas teksti suvalisest kohast kopeerida, siis Silverlight seda muidugi ei luba ja mõnede aadresside jaoks pole kopeerimise võimalust jäetud. Aga küllap nad varsti avastavad ja lisavad võimaluse.

Serveri versioon 2

Uus serveri versioon v2 sisaldab tervet rida uuendusi, millest ma saan veel kaua kirjutada.
Näiteks saab nüüd instantsi restartida.
Samuti on nüüd kättesaadav uus mikro ehk "Extra Small" instants, mis on üle 2 korra odavam senisest odavaimast.
Veel on saadaval Remote Desktop ligipääs, aga sellest mõnikord hiljem, kui ja saan mahti seda katsetada.
Mulle pakub kõige rohkem põnevust "Full IIS for Web Role", mis peaks avama palju varem suletud uksi.

Azure vähendas liiklustasusid

Windows Azure vabastas alates tänasest tasust rakendusse siseneva liikluse. Ehk et Azure ei võta nüüd tasu selle eest, mida klient üles laeb.
Loomulikult on see märksa väiksema osakaaluga liiklus, välja arvatud ühte liiki tarkvara: töörollid, mis otsivad netist infot ja töötlevad seda. Mul endal on üks otsingumootor, mis seda teeb, ja see maksuvabastus on seetõttu väga tervitatav.

AzureXplorer

Päris kasulik toode on ClumsyLeaf AzureXplorer.
Olukorras, kus Microsoft ei ole oma tööriistaga välja tulnud, on erinevaid tööriistu, mis võimaldavad Azure'i salvesteid hallata, tekkinud nagu seeni pärast vihma. Ja tore on.
AzureXplorer on tore selle poolest, et integreerub Visual Studioga. Funkab nii 2008 kui ka 2010-ga.

Mul on nendega isiklik rõõm ka: tegin 5-10 parandusettepanekut ja ei võtnud nädalatki kui need kõik olid teostatud! Tublid poisid.
Prooviversioon töötas 30 päeva, siis tuli maksta 40 taala. Aga see oli seda väärt.

Blobide kasutamine

Blobide loomiseks on esiteks vaja lehel windows.azure.com luua salvestiteenus, millel on unikaalne kasutajatunnus ja kaks võtit. Kaks võtit selle jaoks, et teist võtit oleks võimalik kellelegi ajutiselt anda ja see siis aja möödudes vahetada.
Samas moodulis on toodud veebi kaudu ligipääsemise aadressid. Salvestit saab mäppida ka teisele aadressile (kui sul on ligipääs oma DNSi CNAME-kirjetele).

Salvestile saab määrata sõpruskonna ("Affinity Group"), et sinu rakendus ja salvesti oleksid lähestikku, ja geograafilise asukoha ("Geographic Location", et Eestist tulevad päringud ei peaks Ameerikast infot hankima).
See, mis on aadressis kohe http:// järel, ongi kasutajatunnus. Võtmed on need pikad stringid, mis on uduseks tehtud (kasutada võib ükskõik kumba).
Info info üleslaadimine blobi käib nii (blobuser ja blobkey on siis kasutajatunnus ja võti):

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
void UploadToBlob(string containername, string blobname, string text)
{
  var client = CloudStorageAccount(new StorageCredentialsAccountAndKey(blobuser, blobkey), false).CreateCloudBlobClient();
  var blob = client.GetContainerReference(containername).GetBlobReference(blobname);
  blob.UploadText(text);
  blob.Properties.ContentType = "text/plain";
  blob.Properties.ContentEncoding = "utf-8";
  blob.Properties.CacheControl = "public";
  blob.SetProperties();
}


Ülaltoodud näide pani blobile külge ka valikulised atribuudid (Properties), et seda oleks võimalik veebisirvijaga vaadata.
Blobist info allalaadimine käib DownloadText() abil. Samuti on saadaval meetodid baitide, voogude ja failide üles- ja allalaadimiseks.
Juhul, kui mahutit (container) ei ole loodud, tuleb see luua. Vajadusel tuleb mahuti sisu avalikustada:

var container = client.GetContainerReference(containername);
container.CreateIfNotExist();
container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });


Pane tähele: kuigi võib olla ahvatlev kasutada "CreateIfNotExist()" iga kord, tähendab see ühte lisapäringut.
NB! Mahutite nimed võivad sisaldada ainult väiketähti, sidekriipse ja numbreid (siin on vist arvestatud Guidi nimekujuga).

Kuidas kindlaks teha, kas blob eksisteerib?

Ei saagi kindlaks teha muidu kui vea kaudu. Kui sul on plaanis blobi sisu alla laadida, pane allalaadimine try/catch vahele. Kui ei ole plaanis alla laadida ja blob on suur, püüa lugeda blobi atribuute (Attributes), mis tõmbab vähem alla kui terve sisu (ainult päised).
Sellel on mõistlik selgitus: blobi kättesaamiseks tehakse nagunii http-päring üle interneti. Seega pole mõtet mitut päringut teha (esiteks küsida, kas eksisteerib ja siis alla tõmmata). Kui blobi ei eksisteeri, saadakse 404-viga ja visatakse erand, mida on lihtne kinni püüda.

Kuidas saab blobi lõppu ridu lisada?

Väga lihtsalt ei saagi. Block Blob on üks variant, aga see eeldab lehekülgedele ID-de andmist. Kui sa tahad näiteks logikirjeid lisada, tee ketas, pane sinna üks tavaline fail ja lisa sinna oma logikirjed. Operatsioonisüsteem hoolitseb siis nende kirjete jõudmise eest blobi.

Edu eeldavad rööptehingud Azure'i salvestis

Kui andmehulgale pääseb ligi mitu kasutajat, on vaja mehanismi, mis hoiaks teiste kasutajate karvased käed kirjutamise hetkel salvestist eemal.
Klassikaline võte on tabeli või kirje lukustamine, mis on Azure'i salvestis saadaval nime all Lease, kuid paraku on see olemas vaid HTTP-päringutes ja mitte klienditeegis.
Mitme operatsiooni puhul kasutatakse andmebaasides tehinguid (paremini tuntud ingliskeelse väljendi transaction järgi), kus kogu tsükli vältel on tagatud andmete evimine.
Azure pakub välja lihtsama meetodi, mida inglise keeles nimetatakse optimistic concurrency ja mis võiks maakeeli olla edu eeldav rööptehing. See asendab lihtsamatel juhtudel lukustamist.

ETag

Iga bloob sisaldab ETag-atribuuti, mis on string, mille sisu muutub alati, kui bloobi on midagi kirjutatud.
Bloobi avades saad selle endale salvestada.

blob.OpenRead() ...
string etag = blob.Properties.ETag;


Kõigi blobile tehtavate kirjutamis- ja lugemispäringutega on võimalik see ETag nüüd tingimusena kaasa panna: päring ebaõnnestub, kui bloobi ETag ei kattu etteantuga.

blob.WritePages(..., new BlobRequestOptions { AccessCondition = AccessCondition.IfMatch(etag) });


ETagi esialgne küsimine alustab tehingu. On loomulik, et järgnevad päringud toimuvad vahetult selle järel. Võtame näiteks sellise süsteemi, kus kirjeid lisatakse lehtbloobi, mille esilehel on kirjas järgmise vaba lehe number:
1) loed bloobi esilehe, saades sealt viimase lehe numbri, ja pärast sama päringut salvestad ETagi;
2) suurendad esilehel olevat väärtust ühe võrra, andes tingimusena kaasa ETagi;
3) kirjutad andmed äsja broneeritud viimasele lehele (ETagi kaasa ei anna).
Tehing ebaõnnestub, kui punktis 2 selgub, et keegi on bloobi vahepeal muutnud. Sel juhul minnakse uuele ringile alates punktist 1. Tehing lõpeb punktiga 2, sest selleks hetkeks on viimane leht kirjutamiseks juba broneeritud ja järgmine esilehele pöörduja saab kirjutamiseks uue lehe.
Seda loogikat nimetatakse "edu eeldavaks" selle pärast, et enne tehingu alustamist me ei küsi, kas andmestik pole lukustatud. Me hakkame kohe kirjutama ja eeldame, et see õnnestub.
Vea korral võib minna uuele ringile kohe, sest kui ETag on muutunud, on kirjutamine juba lõpetatud ja andmestik vaba uue kirjutuse jaoks.

Plussid ja miinused

Edu eeldava rööptehingu plussiks on kiirus, sest tehingut ei ole vaja kehtestada (pole tarvis tehingu lõpus commit öelda) ja lukustuse alt ei ole vaja midagi vabastada.
See on võimalik tänu sellele, et Azure'i salvestil on endal sisemine mehhanism, mis välistab olukorra, kus ühe lehe kirjutamise ajal seda keegi loeb (järgmine päring ootab kuni esimene on lõpetanud).
Edu eeldava rööptehingu miinuseks on võimaluse puudumine soovijatel end järjekorda panna. Kõik soovijad peavad proovima nii kaua kuni õnnestub (umbes nagu raadio avalikule mikrofonile helistamisel).
Seega sobib see süsteem hästi juhul, kui üheaegselt bloobile ligi pääsevate kohtade arv ei ole väga suur. On selge, et see pole mõeldud asendama SQL-andmebaasi tehinguid, aga lihtsamate rakenduste jaoks on edu eeldavad rööptehingud väga tõhusad.

HTTPS ja Azure

Turvalise ühenduse võimaldamiseks Windows Azure'is peab sul olema SSL-sert. Sa võid katsetamiseks kasutada ka enda allkirjastatud serti, aga klientidele see ei sobi, sest tänapäeva veebisirvijad näitavad sellist kohates väga ränki veateateid, mis enamuse klientidest minema peletavad.
Serdi saamiseks tuleb koostada taotlus, edastada see serdi väljastajale, maksta raha ja saada sealt valmis sert. Serte väljastavad mitmed firmad. Kõige odavam on GoDaddy, aga nende kasutajaliides on nii segane ja bugine, et sealt tellimine või tellimuse pikendamine võib olla uskumatult keeruline, kohati isegi võimatu. Omalt poolt soovitaksin sellist nagu RapidSSL.
Azure'is ei ole võimalik serdi taotlust koostada. Kui sul on käepärast Windowsi server koos IISiga, siis see on lihtsaim variant. Otsi IISis üles jaotis Server Certificates ja vali Create Certificate Request, mis küsib sinult mõningaid andmeid. Kõige tähtsam on esimene lahter, see on sinu veebilehe aadress.
Valmis taotlus edasta serdi väljastajale, kes annab sulle valmis serdi faili, mille saad Windowsi serverisse importida, kasutades sealsamas valikut Complete Certificate Request. Sinu sert ilmub serveri sertide loetelusse. Kui ei saa hakkama, siis otsi abi veebist, näiteks siit.
Nüüd paremklõpsa oma sertifikaadil ja vali ekspordi. Serdi vorminguks vali PFX. Sul palutakse sisestada salasõna. Mõtle see koha peal välja, seda läheb vaja Azure'is.

Serdi import Azure'i

Azure'is mine oma veebisaidi haldusse (windows.azure.com) ja leia sertide sektsioon ning vali Manage.



Lae sinna üles äsja serverist eksporditud PFX-fail, sisestades salasõnaks sellesama salasõna, mille sa lõid faili eksportides. Rohkem seda salasõna ei kasutata, see oli ette nähtud ainult faili turvamiseks selle transpordi ajal.
Edukalt üles laetud sert ilmub lehe allosas olevasse sektsiooni. Pööra tähelepanu serdi ID-le Thumbprint. See on vaja viia Azure'i rakendusse Visual Studios.
Visual Studios ava Solution Exploreris projekti all Roles ja leia sealt sinu veebirakenduse roll. Paremklõpsa ja ava Properties. Rolli aknas on alumine sakk Certificates. Ava see ja klõpsa nuppu Add Certificate.
Anna serdile nimi (omal valikul), vali Store Location väärtuseks LocalMachine ja Store Name väärtuseks My. Lahtrisse Thumbprint kleebi seesama jada, mille sa kopeerisid Azure'i haldusest.


Pakett tuleb nüüd uuesti üles laadida. Aga see ongi kõik, see veebirakendus aktsepteerib nüüd HTTPS-päringuid.

Vaata ka

Installing an SSL Certificate in Windows Server 2008
Installing Certificates in Windows Azure

ID-kaart Azure'is

ID-kaardiga autoriseerimiseks tuleb esiteks Azure'i üles laadida serdid, mis ID-kaardi serti kontrollida lubavad. Seda on vaja põhjusel, et ID-kaardi väljastaja ei kasuta ülemaailmselt tunnustatud serte, vaid omaloomingut (nii on odavam).
ID-kaardi kasutamine on võimalik ainult HTTPS-protokolliga. Vaata selle kohta artiklit siit.
Mine Azure'i haldamise saidile (windows.azure.ee), aga seekord mitte veebirakenduse haldusse, vaid jaotisse Account. Sealt leiad lingi Manage My API Certificates.



Lae serdid Sertifitseerimiseskusest. Sul on vaja järgmist kolme: Juur-SK, ESTEID-SK, ESTEID-SK 2007. Vali linkide hulgast PEM, mis annab sulle failid laiendiga .cer ja mida sööb ka Azure.
Nüüd polegi muud kui need kolm faili täpselt sellistena Azure'i üles laadida.



Oled saavutanud selle, et Azure oskab hinnata ID-kaarti. Jääb üle veel 2 sammu: anda veebisirvijale teada, et kasutajalt tuleb ID-kaaarti küsida, ja ID-kaardi info lugemine.

ID-kaardi nõudmine

Ma ei ole veel leidnud viisi, kuidas Azure'is saaks nõuda ID-kaarti teatud konkreetsele lehele. IISis on see võimalik, aga Azure'is vist mitte.
Nõude sissekirjutamiseks terve veebisaidi jaoks on vaja lisada kolm rida web.config faili sektsiooni <system.webServer>:

  <security>
    <access sslFlags="SslNegotiateCert"/>
  </security>
</system.webServer>


Selle muudatuse jõustamiseks on vaja kogu pakett Azure'i uuesti üles laadida.
Nüüd küsitakse kõigilt sinu veebiserverisse https-protokolliga sisenejatelt serti, mis üldjuhul tähendab Eestis ID-kaarti (aga edastatava serdi valik on täiesti kasutaja käes).

ID-kaardi lugemine

See on üllatavalt lihtne:

if (Context.Request.ClientCertificate.IsPresent)
  info = Context.Request.ClientCertificate.Subject;


Subjectis on kirjas kogu info ID-kaardi kasutaja kohta.
Märkus: enne seda infot talletama tõttamist tasub lugeda seadusi, et sulle mõni inspektsioon kammi turja ei lööks.

IISi konffimine Azure'i veebirollist

Windows Azure'i veebirolli alustades on võimalik IISi programmiliselt konffida. Siinkohal siis väikesed juhised, kuidas seda teha.

1. Võimalda õigused

ServiceDefinition.csdef peab veebirolli kohta sisaldama sellist kirjet:

<ServiceDefinition ...>
  <WebRole ...>
    <Runtime executionContext="elevated"/>


2. Kasuta DLLi

Lisa veebirolli References alla viide administreerimisteegile, mis asub:
C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll
Windows Azure'i masinas on see juba olemas ja seda kaasa panema ei pea.

3. Tee vajalikud muudatused OnStart()-meetodis

Nimelt on lugu selline, et kõrgendatud õigused kehtivad ainult veebirolli OnStart()-meetodis (failis WebRole.cs) ja mitte hiljem, kui veebiroll on juba käivitunud.
Lisa faili

using Microsoft.Web.Administration;


ja siis meetodisse mis vaja:

public override bool OnStart()
{
    ServerManager sm = new ServerManager();
    sm.GetApplicationHostConfiguration().GetSection("system.webServer/security/access", "Web_IN_0_Web/idcard.htm")["sslFlags"] = "Ssl, SslNegotiateCert, SslRequireCert";
    sm.CommitChanges();


Antud näites minnakse ja pannakse konkreetsele failile tingimus, et sellele ligisaamiseks peab klient andma kaasa serdi (selles näites on see tingimus vajalik ID-kaardiga sisselogimise teostamiseks).
See meetod (GetApplicationHostConfiguration) avab applicationHost.config faili, mis nagu teisedki failid on serveris kataloogis D:\Windows\System32\inetsrv\config
Muude muudatuste tegemiseks ongi kõige lihtsam veebirolli kaugtöölauaga sisse minna, muudatus ära teha ja siis vaadata, kuidas see konfifailis avaldus. ServerManager lähtub samast struktuurist ja loogikast.
Vajadusel tasub tutvuda teegi spikriga.

Ketta kasutamine

Windows Azure'i ketas on üks paremaid andmete salvestamise võimalusi. See kasutab ketta suurust Block Blobi, kuhu info on tegelikult salvestatud.
Kohalikust salvestist on võimalus valida osa, mida kasutatakse vahemäluna. Ja sinu rakendusele paistab see nagu tavaline kõvaketas. Block Blobi plokkide vähim suurus on 512 baiti. See on siis vähim andmehulk, mida kettal olevat infot uuendades blobi kirjutatakse.
Ketast kasutades on hea meeles pidada, et see sobib eelkõige tihti kasutatavate andmete jaoks (väikesed failid, mida sageli loetakse/kirjutatakse).
Optimaalne arhitektuur tähendab seda, kõik staatilised ja harva muutuvad andmed on avalikes blobides, kust klient need ise kätte saab. Blobide kaitsmiseks võõraste silmade eest võib kasutada võtmetena pikki nimesid (GUID või topelt-GUID, kui oled paranoiline).
Need andmed, mida server peab iga kell kätte saama, saad panna kettale.
Esiteks peab sul olema loodud vastav kohalik salvesti (Local Storage). Seda saad teha, kui valid paremklõpsuga oma rakenduse (Role) atribuudid.

Meie näites on sellele antud nimeks DriveCache. Seejärel saad koodis luua ketta ja määrata selle ketta vahemäluks vastava kohaliku salvesti:
 
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
LocalResource local = RoleEnvironment.GetLocalResource("DriveCache");
CloudDrive.InitializeCache(local.RootPath, local.MaximumSizeInMegabytes);
var account = new CloudStorageAccount(new StorageCredentialsAccountAndKey(blobuser, blobkey), false);
CloudDrive drive = StorageAccount.CreateCloudDrive("drives/mydrive");
drive.Create(32 * 1024); //32GB
string drivepath = drive.Mount(local.MaximumSizeInMegabytes, DriveMountOptions.None);


Selles näites võetakse nime järgi kohalik salvesti, kasutatakse seda vahemäluna ja avatakse kasutajakonto (kasutades blobi kasutajatunnust ja võtit). Ketas luuakse, kasutades mahuti ja blobi nime (vaata, et mahuti oleks eelnevalt olemas), ning antakse kettale maht megabaitides. Lõpuks tagastatakse muutujasse "drivepath" ketta tee (näiteks "B:\").
Tähelepanuväärne on siin see, et ketta suurusest ei sõltu maksustamine. See kasutab ära Block Blobide omadust, kus tasu alla läheb vaid rakendatud plokk. Need plokid, mis blobist on kasutamata, ei ole rakendatud (committed), seega neid ka ei maksustata.

Kui Azure ei saa kohalikule salvestile ligi

Minul juhtus selline asi, et kohalik salvesti ei olnud enam veebisaidile ligipääsetav. Lihtsalt tuleb Access denied ja kogu lugu. See on muidugi jabur, sest kes siis veel seda salvestit peaks kasutama, kui mitte minu enda veebiteenus, aga nii see on.
Panin siis pilverakenduse käivitusprotseduuri sellise jupi koodi:

  public class WebRole : RoleEntryPoint
  {
    public override bool OnStart()
    {
      try
      {
        DirectoryInfo di = new DirectoryInfo(RoleEnvironment.GetLocalResource("Local").RootPath);
        DirectorySecurity ds = di.GetAccessControl();
        ds.AddAccessRule(new FileSystemAccessRule
        (
          "Everyone", 
          FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, 
          PropagationFlags.None, 
          AccessControlType.Allow
        ));
        di.SetAccessControl(ds);
      }
      catch
      {
      }


See lahendas asja.
1: See "Local" on muidugi muutuv väärtus vastavalt sellele, mis nimi kohalikule salvestile on pandud.
2: Ma saan aru, et "Everyone" kõigele ligi lasta võib olla pisut ohtlik, aga mul pole aimugi, kes see selle asemel peaks olema. Seega panin "Everyone" ja oletan, et nagunii keegi muu minu serverisse ligi ei saa.

Kuidas alustada

Sul peab olema Visual Studio 2008 või soovitavalt 2010 (ka "Web Developer Express" ehk tasuta versioon sobib).
Installi Windows Azure Tools for Microsoft Visual Studio. Sel lehel on ka parasjagu pikk loetelu tingimustest ja hotfixidest, mis sul peavad täidetud olema.
Uute projektide valikusse Visual Studios tekib "Cloud", mille alt leiad "Windows Azure Cloud Service". Sellele tuleb anda nimi ja lisada uus veebiroll (projekti peal Solution Exploreris vali paremklõpsuga "Add New Web Role Project").

Anna projektile nimi ja sa võid selle juba käivitada (F5). Käivitamisel tõmmatakse üles kohalik Windows Azure'i simulaator, mis avab veebisirvija õigel kohalikul aadressil (näiteks pordis 81). Projekti seiskamiseks pane veebisirvija kinni.

Konto tegemine Microsofti juures

Selleks läheb vaja krediitkaarti ja kuni 2010. aasta novembrini peab ütlema, et elukohariik on Finland. Mõnetunniseks katsetamiseks antakse proovikonto, pikemaajaliste projektide puhul on tarvis kohe maksta. Liituda saab siin.
Omalt poolt soovitan tõsisema plaani korral sellist paketti nagu "Development Accelerator Core", kus kuni aastaks saab 42.52 euro eest kuus 750 tundi rakenduseaega, 10GB andmemahtu ja 21GB andmeliiklust.

Lisainfot

Microsofti selgitus keskkonna käimasaamise kohta
Download the Tools
Walkthrough: Create Your First Windows Azure Local Application
Walkthrough: Deploy and run your Windows Azure Application

Kuidas kulusid kokku hoida

Lihtsa veebirakenduse pilt on siin:

Aga ups! Azure'is see ei tööta. See tähendab, töötab, aga pole mõttekas. Küsimus on maksustamise mudelis. Sa maksad kettaruumi eest (üsna vähe) ja siis lisaks sellele siseneva ja väljuva võrguliikluse eest. Selle viimase koha pealt tasub mõtelda, enne kui teha. Vaata allolevat skeemi.

Kuna Azure'is asuvad nii blobid kui ka SQL-server internetis ja mitte enam veebiserveri tagatoas (või väiksemate lahenduste puhul koguni samas masinas), tähendab see, kui veebiserver küsib midagi SQL-serveri käest, väljuvat liiklust veebiserverile, sisenevat SQL-serverile, siis väljuvat SQL-serverile ja jälle sisenevat veebiserverile. Ja loomulikult lisame siia veel kliendilt tuleva päringu ja talle saadetava vastuse.
Kui mulle see kohale jõudis, siis ma mõtlesin, mis on kogu selle asja point? Kas üldse on mõtet Azure'is midagi teha? Tegelikult on ikka mõtet teha. Ainult et teha tuleb Azure'i viisil ja optimeerida kulutusi (ehk andmeliiklust). Toon all mõned mõtted.

Paks klient on ilus klient

Selle asemel, et koostada kogu HTML-leht serveris ja see siis kliendile kätte anda, kasuta paksu klienti (Desktop-rakendus, Flash või minu lemmik Silverlight). Kasutajate masinatel on powerit küll ja küll, milleks osta seda CPU-jõudlust ja op-mälu Microsoftilt?

Lase kliendil andmeid otse küsida

Kirjuta kõik vähegi staatilisemad andmed avalikesse blobidesse. Kui need andmed on salajased, pane blobile pikk nimi (üks GUID on palju kindlam kui 99,9% kasutatavatest salasõnadest). Anna nüüd kliendile blobi nimi ja lase tal endal see info sealt alla tõmmata, miks see peab serveri kaudu käima? (Klientidele SQLi ligipääsu lubamist ma ei pea turvaliseks.)

Mõtle, mida kuhu salvestada

Ühes minu vanas rakenduses oli 10GB SQL-andmebaas ja mõned failid. Nüüd on mul 10MB andmebaas, 5GB blobe ja mõned failid. Hea näide on geograafiliste koordinaatide järgi kohanime leidmine. Varem oli mul kogu maailma andmebaas SQLis. Maru lihtne on sealt lähimat kohta leida. Siis mõtlesin, et nii ei saa. Natuke nuputamist ja tekitasin algoritmi, mille järgi koordinaatidest arvutatakse välja blobi nimi, kus lähim koht kindlasti sees on. See tähendas küll, et iga koht peab esinema vähemalt 2 blobis, aga who cares? sest blobide salvestusruum ei maksa peaaegu midagi!
Pea siis meeles, et
Avalikku blobi andmed, mis väga tihti ei muutu
SQLi andmed, mida muidu on väga raske hallata
Kohalikku salvestisse andmed, mida kaua ei hoita
Kettale andmed, mis muutuvad tihti

Näide siinsamas

Käesolev sait on ehitatud neid põhimõtteid silmas pidades. See on muidugi väga lihtne rakendus, aga ikkagi.
Nagu oled ilmselt märganud, on tegemist Silverlighti kliendiga (paksuke teine). Veebiserver on nii õhuke, et enam õhem olla ei saa. See hoolitseb ainult selle eest, et sa saad avalehe ja Silverlighti komponendi. Ja serveri teine töö on ülespandavate artiklite salvestamine ja indekseerimine. Veel kolmas töö on otsingumootoritele tekstikujul info jagamine. Aga need on kõik harvaesinevad tööd.
Pärast avalehe avamist ei tee selle saidi kasutaja veebiserverile enam ühtegi päringut. Kõik pildid, artiklid ja isegi otsingutulemused tulevad otse blobist. Selle rakenduse lihtsuse tõttu ei kasutata üldse SQLi, kohalikku salvestit ega ketast.

Kuidas saiti dünaamiliselt uuendada

Windows Azure'i paketi ülespanemisel luuakse operatsioonisüsteemi uus instants. See võib toimuda täiesti teises füüsilises kohas ja tõenäoliselt on sellel ka teine IP-aadress. Kohalikule salvestile tõmmatakse vesi peale. Ja kogu protsess võtab umbes 15 minutit.
Kui paketis on mingi viga (kasvõi konfifailis), jääb pakett sellisesse nõiaringi, kus see tõmmatakse käima, seisatakse ja tõmmatakse uuesti käima.
See pani mind juba alguses mõtlema, et tarkvara vahetamiseks minu veebirakenduses peab olema mingi parem võimalus. Ja ongi. Idee on selline, et paketti pannakse üles minimaalne vajalik kogus koodi, mis on võimeline blobidest vajalikud DLLid võtma. Siinjuures on oluline, et DLLid ei ole seotud staatiliselt (References), sest muidu ei saa kord juba rakenduse mällu laetud DLLe enam mingi trikiga sealt maha võtta (vahetada).
Kasuta sellist lähenemist:

var assembly = Assembly.Load(blob.DownloadByteArray());
var type = assembly.GetType("MyNamespace.MyType", true);


Nüüd laaditakse DLL dünaamiliselt. Teatud aja tagant võid kontrollida, kas blobis ei ole uuem DLL (näiteks blobi kuupäeva järgi või kasutades blobi erinevat nime). Teine võimalus on mingi URLi parameetriga teada anda, et DLL tuleb vahetada.
Mina olen kirjutanud väikese programmi, mis kompileeritud DLLi õigesse blobi üles paneb. Nii saab selle lisada ka automaatselt projekti Build Eventide alla.
Dünaamiliselt laaditud DLLi võib siis teha rakenduse staatiliseks parameetriks (lõimeohutult muidugi), niimoodi jääb see laadituks.
Selliselt DLLi laadides tuleb kasutada ühist mõlemapoolselt viidatud DLLi, mis on staatiline ja sisaldab suhtlemisstandardeid (Interface).

Viidatud DLLid

Need DLLid, millele on sinu projektis viidatud (Reference), ei saa paraku olla mingis süsteemikataloogis, sest sellele sul ligipääsu ei ole. Paketi kompileerimisel pannakse need automaatselt kaasa, aga mis juhtub siis, kui mõnele teegile viitab dünaamiliselt laetud DLL?
Sul on võimalik panna oma teegid Azure'i kettale või laadida neid blobist. Siin tuleb appi domeeni event AssemblyResolve. Alltoodud näide loeb teegi kettalt (eeldades, et drivepath on teekide asukoht).

AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => 
  { 
    return Assembly.LoadFrom(drivepath + e.Name.Substring(0, e.Name.IndexOf(',')) + ".dll"); 
  };


Kuidas ühe rakendusega hakkama saada

Nagu juba mujal mainitud, võetakse iga rakenduse eest, mis Azure'is jookseb, üks ühik raha (näiteks alla 50 euro kuus).
Azure'is on kahte sorti rakendusi: veebiserver ja tööline. Veebiserver töötab siis, kui klient teeb päringu ja tööline töötab iseseisvalt ja pidevalt (nagu Windowsi service).
Ühe veebiserveri alla saab loomulikult panna suurel hulgal saite. Ja keegi ei keela panna sinna ka tervet posu erinevaid WCF-teenuseid. Seega need üksteist ei sega. Ja isegi juhul, kui üks proseühik ei piisa nende kõigi teenindamiseks, saab proseühikuid koos mäluga juurde osta. Sellega on niisiis lihtne.

Vaese mehe palgatööline

Mul on näiteks rakendus, mis tsekkab sissetulevat ja masinloetavat meili. Maru mõnus oleks, kui selle jaoks oleks tööline, mis seda meili iga minut kontrolliks. Aga ma ei taha selle eest nii palju maksta, et mul on sisuliselt üks äratuskell, mis iga minuti järel seal masinas korraks tiriseb.
Siis ma avastasin, et kui iga veebipäring käivitab ühe lõime, mis kontrollib, kui palju aega viimasest päringust on läinud, ja võtab meilid kui vaja, saan hakkama. Lõim on vajalik selleks, et veebipäringu vastus läheks kohe tagasi.
Kui sinna ehitada süsteem, mis kuni uue lõime avamiseni vana käigus hoiab (nii et harvade päringute korral ikka meili iga minut tsekatakse), jääb üks lõim alati püsti. Siin on üks aga: nimelt tundub, et teatud aja järel paneb Azure selle poe kinni. Aga see polegi nii hull, sest ma ei pea öösiti oma meili tsekkama. Kui ärkavad esimesed kliendid, ärkab jälle ka minu äratuskell (ja noh, öösiti on ka päris palju päringuid).
Märkus: kui lõim on taustalõim (Background = true), siis pealõime sulgemisel killitakse see julmalt ära. Kui see ei ole taustalõim, siis oodatakse kuni see on lõpetanud.
Praegu olen ma selle lahendusega igatahes rahul ja see on piisav. Kui oskate selles suhtes midagi kommenteerida, olen infost huvitatud.

Microsoft Dynamics CRM Pilves

Mitu kuud beetas olnud Dynamics anti ametlikult välja pilveversioonina. Hind $34/kuus kasutaja kohta pole ka üldse palju küsitud.
Minu jaoks kõige põnevam uudis on see, et lisade arendus on .NETis Windows Azure'i all. Mis ta muu on kui järjekordne järvetäis vett Azure'i veskile.
Ma ei taha ennast korrata, aga ma kordan: ma olen seda korduvalt öelnud, et tulevik on pilves.

Vaata ka:

Dynamics

Minu suurimad mured oma serveri pidamisel

Mul on 3 serverit. Üks minu pakutavatest kommertsteenustest on MINITAX.NET. See on nüüdseks suures osas Azure'i üle viidud. Laske mul jutustada, miks.

Teiste peale ei saa loota

Esiteks majutasin oma serveri ühte Tartu firmasse, kelle missioon kodulehe järgi on luua toimivaid lahendusi ja kel on mitu toatäit patsiga poisse, kes pidevalt portide suunamise ja taolisega tegelevad. Tundus usaldusväärne. Selgus, et põhiline osa probleemidest tekib, kui nad kuskil oma tulemüürides ja ruuteritest midagi muudavad (ja nad teevad seda pidevalt). Miskit juhtub, et minu IP pole enam kättesaadav. Ja kui neile nüüd rikkest teatada, siis nad lähevad lähema paari päeva jooksul serveriruumi ja vajutavad minu serveril resetit. Mis ei muuda midagi. Minu pikim katkestus nende juures kestis 10 päeva. Ostsin vahepeal koguni uue serveri, kuna olemasolev vajavat pidevalt restarti ja tal olevat mälurike (ette rutates olgu öeldud, et seesama server on täiesti korras ja ei ole minu käes kunagi restarti vajanud). Oli ilmselge, et pidin midagi ette võtma, sest sellise teenusega ei saa kommertslahendusi pakkuda.
Järgmine oli Tallinna firma, kes pakub väga kallist serverimajutust koos 100-megabitise internetiga ja ütleb oma kodulehel, et on keskendunud "nõudliku äriklientuuri varustamisele kõrgekvaliteediliste side- ja serveriteenustega". Selle firma nõrgaks kohaks osutus see, et probleemide lahendamise võimaluse eest väljaspool tavatööaega tuli maksta umbes 1000 krooni kuus lisatasu. Rääkimata sellest, et mul oleks endal võimalik oma serverile ligineda. Kuigi minu serveril oli hädaolukorra jaoks olemas ILO-port (teine võrgukaart, kustkaudu saab ligi isegi kui terve server maas on), ei pidavat olema tehniliselt võimalik mulle lisa-IP-aadressi anda ja selleks tuleks maksta teise serveri eest (mitu tuhat krooni kuus). Teeb meele mõruks küll, kui mingi tühise probleemi pärast tuleb mitu päeva oodata, et server püsti saada. Lisaks veel ülbed müügimehed...

Oma serverid oma toas

Otsustasin, et ma pean oma serveritele ise ligi saama, maksku mis maksab. Üürisin kontoriruumi ja ostsin ühe serveri juurde. Panin oma kolm serverit sinna tuppa, kus nad nüüd jooksevad. Muuseas, nüüd kus nad minu käes on, pole kordagi vaja olnud resetit vajutamas käia (kuigi varem teenusepakkujad alati ütlesid, et viga ei ole mitte nende juures, vaid minu viletsates serverites). Aga probleemiks on ikka veel internetiühendus. Mul on kaks kiiret internetiühendust: üks maja poolt ja teine Elionilt. Maja oma käib eriti tihti maas. Ja ega Elioni ühendus ka pidevalt korras ei ole. Ja muidugi, kui majas on näiteks vool ära, siis on tuksis.
Kolme Windowsi masina eest hoolitsemine nõuab märkimisväärselt tööd. Nad tahavad kogu aeg uuendusi saada, kettad vajavad defragmentimist, rääkimata andmebaasist, millest on vaja pidevalt varukoopiaid teha. Ja MS SQL vajab käigushoidmiseks ikka päris palju administraatori tasemel teadmisi, et ta oleks korralikult peegeldatud ja optimeeritud jne. Nii olingi probleemi ees: suur osa energiast ja rahast läheb serverite eest hoolitsemisele, samas ei saa seda tööd ka käest anda, sest siis kukub asi hoopiski kokku.

Niisiis Azure

Pärast teenuste Azure'i kolimist saan keskenduda puhtalt tarkvaraarendusele. Kogu administreerimise jama on jäänud selja taha. Microsoft garanteerib mulle 3-kordsed varukoopiad minu andmetest ja ma pole kunagi kohanud sellist nähtust, et minu server pole kättesaadav.
Juba pelgalt serverite ostmiseks kulutatud raha eest oleksin saanud 3 aastat Azure'i tarbida. Kui arvestada, et 3 aasta pärast võib olla tarvis osta uus server, tasub Azure'is olemine end juba puhtalt selle pealt ära. Lisaks sellele maksab palju internetiühendus, ruumide rent, administreerimine, varundamine, rikked jne.
Soovitan soojalt Azure'i. Aga kui ei meeldi, siis mul on müüa korralikke HP räkitavaid servereid :)

Osalege kokasaates

Eneta kommuuniõhtut "Paneme Azure'i tuksuma" ette valmistades mõtlesin, et see on tegelikult otse-eetris kokandussaade. Kõige selle juures meenutab kokandust eriti see, et Azure'i rakendust üles pannes tuleb 20 minutit oodata, kuni see ahjus "küpseb". Samal ajal saab muidugi mune kloppida või muud vajalikku teha.
Nali naljaks, aga mul ei ole kavas mitte pilve piltidega slaide näidata, vaid hakata laivis koodi kirjutama. Teen seda natuke teistmoodi kui Getting Started stiilis, et selle lühikese aja jooksul edasi anda võimalikult palju praktilisi kogemusi.
Milline toit selle kokandussaate lõpuks valmis saab, see selgub 1. detsembril.
Olete oodatud osalema!

Paketivahetus ja ketas

Azure'is tähendab paketi ülespanek uue virtuaalse masina loomist. Arusaadavalt võtab see mõnevõrra aega. Minu kogemuste järgi vähemalt 15 minutit. Aga kesse tahab, et tema server ja kõik teenused 15 minti maas oleksid?
Kuna iga konto juures on Production ja Staging (avalik ja testkeskkond), siis on loogiline lähenemine selline, et paneme oma paketi testkeskkonda üles ja siis tõstame ta avalikuks. Selle jaoks on antud hea vahend, mis vahetab omavahel test- ja avaliku rakenduse ühe hiireklõpsuga. Ja see kõik võtab aega vaid mõne sekundi.

Paned siis oma vidina Stagingusse üles, võtku see kasvõi pool tundi, ja siis klõpsti...

Ups!

Aga kui ma kasutan ketast, siis on lugu selline, et ketta andmeid sisaldav blob on ketta kasutaja poolt lukustatud. See on ka loogiline, kuna ketas koosneb blobist ja tema vahemälust, mis on rakenduse kohalikul kettal. Ketta tervist on võimalik kontrollida siis, kui vahemälu pidajal on blobi üle täielik kontroll.
Esimene ilming on see, et testkeskkonda üles pandud rakenduses ketas ei tööta, kuna seda ei õnnestu samast blobist lukustada. Teine (ja loogiline) üllatus ilmneb pärast klõpsu tegemist: nüüd on ketas testkeskkonnas ja avalik keskkond on ilma kettata (ja panges, kui seal kõik kettast sõltub).
Mis oleks siis lahenduseks? Pakkuge välja, kui teate midagi paremat, aga ega vist muud varianti pole kui kirjutada rakendusse sisse kaugjuhitav ketta loomine ja vabastamine. Enne klõpsu tegemist tuleb avalik keskkond ikkagi kinni panna ja teha seal kettale Unmount(). Ja testkeskkonnas ketas käima panna ehk teha Mount(). Kui sellist Unmounti programmile sisse kirjutatud ei ole, saab ketta vabaks vaid kogu värki restartides (mille peale kulub nii-ehk-teisiti see 15 minutit).
Veel üks variant oleks automaatne kettahaldus, mis oskaks ise kindlaks teha, kas programm jookseb Stagingus või Productionis ja seda, kui tema staatus vahetub. Kuidas seda teha, ma veel ei tea.
Või on teil, lugupeetud lugejad, paremaid ideid?

PHP, MySQL, Eclipse ja Azure

Sügisel on välja tulnud terve hulk uuendusi neile, kes armastavad PHP-d ja arendavad Eclipse'iga.
See on nüüd siis uus komplekt LAMPi (Linux, Apache, MySQL, PHP) asemele. Kas selle nimeks saab WAMP (Windows, Azure, MySQL, PHP)?
Uuenduste hulgas on SSL-sertide tugi, mitme rolli tugi, ketta tugi, MySQLi jooksutamise tugi eraldi rollina.
MySQLi tugi eraldi rollina paneb kukalt sügama, sest kui MS SQLi andmebaasi saab $9.99 eest kuus, siis üks compute instance MySQLi jaoks maksab $87.60.
Novembris on oodata sügisese väljaande lõpetamist, see tähendab täielikku dokumentatsiooni.
Aga vinge... arusaamine, et tehnoloogiaid on mitmeid, ja nende hea meelega toetamine annab tootele kõva tõuke edasi. Jõudu, Azure!

Silverlight - REST - Azure

Ma tegin vahepeal ühe huvitava projekti, kus Silverlight läheb otse Azure'i blobide kallale. See ei olnud nii lihtne kui alguses võis loota, sest tee peal oli üht-teist avastada. Jagan leitut teiega.

Miks selline lahendus?

See on mul niisugune teenus, kus palju kliente näpib paljusid andmeid ja ma tõesti ei taha serverit sinna vahele, sest antud juhul on igal kliendil oma väike maailm. Ma tahtsin, et iga klient saab kätte oma blobid ja näpib neid kui vaja.

Azure'i blobid vastavad toredale REST standardile, see tähendab, et sinna saab teha http päringuid. Ainult üks väike "aga" on asja juures: need REST asjad vajavad näiteks PUT-meetodit.

Tegemist on Block Blobidega, see tähendab, et klient saab ligipääsu ühele blobile ja paneb sinna üles plokke kuhu vaja.

Mis teeb keeruliseks

Koodi teeb keeruliseks see, et Silverlight saab veebipäringuid teha ainult asünkroonselt. Ja kui on vaja teha kolm päringut järjestikku, siis seda nikerdamist asünkivate jublakatega on omajagu. Siin siis protseduur:

Võta serverist blobile jagatud võti

Jagatud võtmest ma kirjutasin oma eelmises blogis. Silverlighti komponent logib serverisse sisse ja saab jagatud võtme. See ongi põhimõtteliselt kõik, milleks ta Windows Azure'i vajab, sest XAP-fail ise tuleb ka blobist, rääkimata HTML-failist, mis on samuti blobis.

Selle jaoks, et see õnnestuks, peab Windows Azure'i serveris olema clientaccesspolicy.xml (kuna WA server on alati erinevas domeenis).

Võti vananeb ühe tunniga. Kui võti on sul olemas, siis kontrolli, et see pole vanaks läinud, ja vajadusel küsi uus.

Lukusta blob

Kui on tegemist suure blobiga, millel sa uuendad ainult mõnda plokki, siis tasub enne plokkide loetelu allatõmbamist blob lukustada. Muidu vahepeal keegi muudab seda loetelu ja sa kirjutad muudatused hiljem üle.

Siin tuleb lukustamisest teine kasu: sa saad proovida oma lukku uuendada, enne kui uue loetelu alla tõmbad. See tähendab, et olles kord plokkide loetelu alla tõmmanud ja blobi lukustanud, võid lukustamist järgmine kord uuendada. Kui see õnnestub, tähendab see seda, et keegi pole vahepeal midagi lukustanud (ja uut plokkide loetelu pole vaja, sest vana kehtib).

Lukustamiseks tuleb teha PUT-päring, mis peab saama kaasa mõned kohustuslikud päised.


HttpWebRequest wr = WebRequest.CreateHttp(uri + key + "&comp=lease");
wr.Headers["x-ms-date"] = DateTime.Now.ToUniversalTime().ToString("o");
wr.Headers["x-ms-version"] = "2009-09-19";
wr.Headers["x-ms-lease-action"] = "acquire"; //see on "renew" kui uuendad
//wr.Headers["x-ms-lease-id"] = leaseid; //anna see kui uuendad
wr.Method = "PUT";
wr.BeginGetResponse(rp =>
  {
    leaseid = wr.EndGetResponse(rp).Headers["x-ms-lease-id"];
  }, null);



Nagu näete, tuleb teha tühi PUT-päring ja luku võti (leaseid) antakse vastuse päises. Blob jääb lukku kõige rohkem minutiks.

Kohustuslikud päised

x-ms-date on kohustuslik, sest Azure Storage server ei luba päringuid, mis on vanemad kui 15 minutit. Seega peab tagama, et kliendi arvutis on võimalik saada adekvaatne maailmaaeg.
x-ms-version on kohustuslik. Kasuta seda konstanti, see on viimane võimalik versioon.
x-ms-lease-id tuleb muidugi edaspidi kaasa anda, et sa saaksid oma lukus blobi kasutada.

Tõmba alla plokkide loetelu

Seda on vaja uuesti alla tõmmata juhul, kui luku uuendamine ei toiminud (sisu on vahepeal muudetud).

WebClient wc = new WebClient();
wc.Headers["x-ms-date"] = DateTime.Now.ToUniversalTime().ToString("o");
wc.Headers["x-ms-version"] = "2009-09-19";
wc.Headers["x-ms-lease-id"] = leaseid;
wc.DownloadStringCompleted += (sender, e) => ParseBlockList(e.Result);
wc.DownloadStringAsync(new Uri(uri + key + "&comp=blocklist", UriKind.Absolute));



Pane üles oma muudetud plokk

Ploki id peab olema base64-vormingus, kusjuures ühe blobi kõigi plokkide id-d peavad olema sama pikad.
See on PUT-päring, kus aadressiks on uri + key + "&comp=block&blockid=" + id ja päringu keha sisaldab ploki baite.

Pane üles uus plokkide nimekiri

Ära unusta lisamast plokkide nimekirja oma uut plokki.
See on PUT-päring aadressiga uri + key + "&comp=blocklist", mille keha sisaldab plokkide nimedest koosnevat XMLi.

StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?><BlockList>\r\n");
foreach (string id in ids)
{
  xml.Append("<Latest>");
  xml.Append(id);
  xml.Append("</Latest>");
}
xml.Append("</BlockList>");



Vabasta lukustus

See on samasugune päring nagu lukustuse taotlemisel, ainult et x-ms-lease-action on "release". Selle viimase osa võid ka tegemata jätta, sel juhul vabaneb blob automaatselt 1 minuti jooksul.

Kõik see asünkroonis

Minu rakenduses on nii, et klient võib samal ajal muidugi uusi muudatusi teha. Seega peaks kontrollima, kas meil on hetkel blob lukustatud (või mis seisus ta üldse on) ja sokutama vahepeal tehtud muudatused üles, enne kui lukustuse alt midagi vabastatakse.

Nendes koodinäidistes pole muidugi veakontrolli, aga see peab olema, sest eriti lukustuse taotlemisel võib keegi teine olla ette jõudnud.

Kogu see asi on päris tükk tööd (minul tuli ploki ülespanekuks blobi kokku 400 rida koodi), aga tulemus on väga lahe: minu WA server ei pea enam nende asjade pärast üldse muretsema.

Silverlighti XAP-faili lugemine blobist

Vaikimisi turvasätted ei võimalda lugeda Silverlighti allikat (src) mujalt kui samast domeenist. Et see võimalik oleks, tuleb muuta kahte sätet:
Pane HTMLi enableHtmlAccess

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
  <param name="source" value="http://blob.azure.ee/xap/08cd38bc55ba395c.xap"/>
  <param name="enableHtmlAccess" value="true"/>


Pane Silverlighti projekti Properties/AppManifest.xml-i ExternalCallersFromCrossDomain

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ExternalCallersFromCrossDomain="ScriptableOnly">
    <Deployment.Parts>
    </Deployment.Parts>
</Deployment>


Selle lahenduse leidmine võttis mul omajagu aega. Ka silverlight.net foorumis vastati, et pole võimalik... Hea, et siiski on võimalik.
Nüüd tuleb meeles pidada, et Silverlighti komponent on erinevas domeenis kui koduleht. Kui see tahab kodulehele näiteks WCF-päringuid teha, peab kodulehel omakorda olema clientaccesspolicy.xml

Sisu lisamine Block Blobi

Block Blob võimaldab nimeliste plokkide lisamist blobile. Blobi sisu alla laadides võetakse kõik plokid selles järjekorras nagu nimed olid esitatud.
Block Blob on natuke aeglane seetõttu, et ploki lisamiseks tuleb esiteks alla tõmmata kõiki plokkide nimed, lisada loetelule üks, panna üles uus plokk ja lõpuks kehtestada uus plokkide nimekiri (laadides kogu nimekirja uuesti üles). Asi oleks märksa efektsiivsem, kui Azure võimaldaks teha lihtsalt k.Aga parem ikka kui mitte midagi.
Teine asi, mis on puudu, on konkreetse ploki lihtne allalaadimine (aga baitidega saab mängida).

Ploki lisamine


void AddBlock(string text)
{
  //ava blob
  var blob = container.GetBlockBlobReference("minublob");
  //tõmba alla plokkide loetelu
  List<string> blocks = new List<string>(blob.DownloadBlockList().Where(w => w.Committed).Select(s => s.Name));
  //genereeri uus ploki id
  string blockid = Convert.ToBase64String(Guid.NewGuid().ToByteArray()); //ploki id saab olla ainult base64
  //pane plokk üles
  blob.PutBlock(blockid, new MemoryStream(Encoding.UTF8.GetBytes(text)), null);
  //lisa ploki id loetelusse
  blocks.Add(blockid);
  //pane plokkide loetelu üles
  blob.PutBlockList(blocks);
}


Plokkide lugemine

Ülal demonstreeritud blobi saab lugeda tervikuna nagu tavalist blobi. Kui sul on sealt vaja konkreetset plokki, siis tõmba alla plokkide loetelu. Iga ploki juures on märgitud selle maht baitides. Kui blob ei ole suur, võid seejärel alla tõmmata terve blobi ja sealt õige ploki positsiooni järgi välja korjata.

string GetBlock(string id)
{
  var blob = container.GetBlockBlobReference("minublob");
  //tõmba sisu alla
  var bytes = blob.DownloadByteArray();
  //tõmba alla plokkide loetelu ja otsi õige plokk
  int cursor = 0;
  foreach (var block in blob.DownloadBlockList().Where(w => w.Committed))
    if (block.Name == id)
       return Encoding.UTF8.GetString(bytes, cursor, (int)block.Size);
    else
       cursor += (int)block.Size;
  return null;
}


Veel üks võimalus konkreetse ploki lugemiseks (kui kogu blobi ei ole mõttekas alla tõmmata) on kasutada blobi lugemisel x-ms-range päringupäist, millega saab kaasa anda positsioonivahemiku. Paraku ei ole selle jaoks olemas teegifunktsiooni. Selle kohta võib rohkem lugeda siit.

Optimeerimine

Plokkide sagedasel lisamisel tasuks kohalikus mälus või kohalikul kettal hoida kehtivat plokkide nimekirja, mis aitab säästa ühe päringu.

Mis tolku sellest kõigest on?

Block blob on kasulik juhul, kui blob on selline fail, kuhu kirjutatakse infot juurde, ja mida tuleb üldjuhul tervikuna lugeda.
Süsteem ei tasu end ära, kui plokid on väikesed ja neid on palju (plokkide loetelu igakordne ülekirjutamine vajab tohutult rohkem andmeliiklust kui plokk ise). Alternatiivne variant on Page Blob, kus leheküljed on nummerdatud ja iga lehekülg on 512-baidine. Ka see pole vähese info jaoks kuigi efektiivne (näiteks 5 baidi kirjutamisel peab ikkagi hõlmama 512 baiti).
Tegelikult ei olegi Azure'is hetkel lahendust, mis oleks mõttekas väikeste andmehulkade sagedaseks lisamiseks. Aga tundkem rõõmu sellest, mis on.

SQL Azure: Database Manager

Olen kogu aeg kasutanud SQL Server Management Studiot, et oma SQL Azure'i andmebaasile ligi minna. See on täiesti piisav. Aga täna proovisin windows.azure.com uues Silverlighti liideses vajutada andmebaasi juures nuppu Manage. Avanes uus liides!
See on Database Manager, mis on tehtud samuti Silverlightiga. Ja sellel on eeliseid.

Tabelite disain

Nupus Design saab visuaalselt muuta SQL-tabelite koostist (Management Studio seda SQL Azure'is ei oska). Seejuures on liides hästi lihtne, linnukesed reas tulpades Is Required?, Is Primary Key? jne. Einoh, lahe. Mõnikord on tõesti kasulik minna ja üks linnuke teha, selle asemel, et püüda meelde tuletada, mis oli see õige SQL-käsk.

Andmete redigeerimine

Vajuta nuppu Data ja andmed avatakse tabelina. Neid on lihtne redigeerida, isegi selline nupp nagu Set to null on olemas. Ainuke tõrvatilk meepotis on see, et minu GUIDid (mis on kirjete identifikaatorid) näitavad ainult sellist teksti nagu <unsupported>. Aga ma usun, et see muutub peatselt.

SQL-päringud

See osa on samuti lihtne ja kergesti kasutatav. Vajutad nuppu Open Query, kirjutad oma SQLi sisse ja töötab!

Kokkuvõtteks asjalik vidin

Mulle see vidin väga meeldib. Ta on Management Studioga võrreldes lihtne ja odav, aga vahel ongi see suureks plussiks. Mul ei ole vaja midagi installida, sest see avaneb veebisaidil. Ja kui kiiresti vaja, saan ma oma muudatused kähku tehtud. Proovige ja veenduge ise ka!

SQL Azure

SQL Azure on Microsofti SQL Server, mis on kättesaadav Internetist. Server istub standardpordis (1433) ja sellele saab ligi tavaliste vahenditega (.NETi koodist, SQL Managament Studio ja Visual Studio abil).
SQL Azure'i konffimine on äärmiselt lihtne ja sama minimalistlik nagu muudegi Azure'i asjade puhul.

Raha

SQL Azure'i eest küsitakse eraldi raha (7 eurot/GB/kuu) ja see eksisteerib sõltumata Windows Azure'i pakettidest. Master-andmebaasi eest raha ei küsita, aga muude andmebaaside mahtusid pakutakse sammudega 1, 5, 10, 20, 30, 40 ja 50GB, kusjuures mahu kasvades jääb gigabaidi hind samaks. Lisaks tuleb maksta andmeliikumise eest.

Tabelite loomine

Praegu, artikli kirjutamise ajal, ei ole Microsofti vahendid veel võimelised SQL Azure'i tabeleid ja päringuid visuaalselt looma. Samuti ei ole võimalik tabelites sisalduvaid andmeid visuaalse tööriista abil redigeerida. Miks, ei tea, aga tabelite definitsioone ja tabelites sisalduvaid andmeid saab muuta vaid SQL-lausete abil.
Tavalisest SQL Serverist pärit SQL-skriptid tabelite loomiseks otse ei sobi, sest mõned valikud on keelatud. Need tuleb tabeleid luues käsitsi ära korjata. Üks juhis selle tegemiseks on siin ja ettevõtlikud inimesed on loonud ka viisardi.

Turva

Ülaltoodud illustratsioonil on näha järjehoidja "Firewall Settings".
Seal saad määratleda kahte asja: 1) lubada Azure'i rakendustel andmebaasile ligi saada (linnuke "Allow Microsoft Services access to this server" ette) ja 2) määrata IP-aadresside vahemik, kust sinu andmebaasile ligi saab.
Lisaks sellele kasutajatunnus ja salasõna.

Mõned omapärad

Tabelitel on nõutud kobarindeksi (clustered index) kasutamine. Ilmselt kasutab Microsoft seda andmete kopeerimisel ja varundamisel. Andmebaaside vahelisi päringuid ei saa teha (oled ühendatud sellesse andmebaasi millega alguses ühendusid ja teisi ei näe).
Täielik ülevaade SQL Azure'i võimalustest ja süntaksist on siin.

Taristu, platvorm ja elektri tootmine ehk mis on pilv

Räägime natuke teooriast. Pilveraalimine on internetipõhine raalimine, milles vastavalt vajadusele kasutatakse jagatud ressursse, tarkvara ja teavet. Seejuures on ressursid üldjuhul dünaamiliselt laiendatavad ja virtualiseeritud.
Pilveraalimise kliendile tähendab see maakeeli seda, et ta võib kasutada teenusepakkuja ressursse, tarkvara ja teavet, jättes nende kolme hankimise täielikult teenusepakkuja mureks. Ehk et mul ei ole vaja muret tunda selle pärast, milliseid litsentse, tarkvaraversioone, kõvakettaid ja varundust ma peaksin kasutama.
Ma võrdleksin pilveraalimist elektri tootmisega. Kui iga arvutikasutaja peab teadma kümmekonda parameetrit riistvara kohta ja hoidma end pidevalt kursis pidevalt uueneva tarkvaraga, siis ühe serveri ülalpidamiseks on neid teadmisi vaja ruudus. Aga elektri ostja ju tegelikult ei peaks sekkuma põlevkivi kaevandamise protsessi? Tema tahab oma rösteri seina torgata nii, et ta ei peaks elektrijaama selleks ümber konffima. Täpselt selle loogika järgi on ehitatud pilveraalimine. Minul on rakendus, mind ei huvita, mida läheb vaja selle jooksutamiseks, võtke see ja hoolitsege, et see jookseks.
Samas ei ole kõik pilved ühtmoodi pilved.
Pilveraalimise puhul eristatakse praegu kahte meetodit. Need on inglise keeles IaaS ja PaaS ehk Infrastructure as a Service ja Platfrom as a Service. Maakeeli taristuteenus ja platvormteenus.

Taristuteenus ehk IaaS

Taristuteenus on natuke lähemal vanale lähenemisele. Sulle antakse virtuaalne arvuti, millesse võid üles panna seda mida vajad. Näiteks vmware tarkvara võimaldab sellist pilve ka ise ehitada: mingi kogus füüsilisi arvuteid seotakse omavahel pilvekeseks, mille sisse saab tekitada suvalise koguse virtuaalseid arvuteid. Need võivad olla erinevate op-süsteemidega ja loomulikult erineva seadistusega. Kõige selle kasu on see, et ressursid on jagatud ja seega optimaalselt ära kasutatud, mis annab tuntava rahalise võidu.
Internetis pakub sellist pilveraalimisteenust näiteks Amazon.
Taristuteenus ehk IaaS on tore selle poolest, et kuigi sa oled pilves, on sul siiski üpris vabad käed. Miinuseks on seesama omadus: võimalus palju tuksi keerata ja kohustus palju teada.
Kui võrrelda taristuteenust elektri ostmisega, siis taristuteenus on elektrikilp sinu maja ees elektriposti küljes. Sul tuleb endal lisada majasisene kilp ja ehitada majasisene juhtmestik. Aga sa ei pea enam muretsema selle pärast, mismoodi põlevkivi kaevandatakse ja kas seda jätkub.

Platvormteenus ehk PaaS

Platvormteenus on pilveraalimise mugavaim variant. Sa paned üles koodijupi ja sind tegelikult ei huvita, mis seda jooksutab. Kas see on Windows või Linux? Pole minu asi. Ma tean lihtsalt seda, mis keeles ja mismoodi ma oma koodi kirjutan ja ma panen selle üles ja see jookseb.
Sellist teenust pakuvad Azure ja Google.
Kui rääkida Azure'ist, siis Azure pole ainult Windows Azure, vaid ka SQL Azure (kuhu sa paned üles oma andmebaasi samamoodi nagu koodijupi) ning ka Azure Storage (kuhu sa paned üles oma andmed). Windows Azure'i puhul ongi põnev, et operatsioonisüsteem on "Guest OS" ehk midagi müstilist ja see ongi nii mõeldud. Muidugi on see Windows aga mitte enam Aknad. See on koht, kuhu sa paned üles oma koodi ja see jookseb.
Platvormteenuse võrdlemisel elektri ostmisega võiks öelda, et platvormteenus on tepsel. Kui tahad, pane telekas, kui tahad, pane föön. Sinu jaoks on seinas kaks pisikest auku ja muu pärast sa ei muretse.

Elu läheb mugavamaks

Pilveraalimine on tehtud selleks, et teenuse ostja võiks tegeleda oma asjadega. Pilveraalimise teenus võib vastavalt tasemele maksta mõnevõrra rohkem, kuid lõppkokkuvõttes on see efektiivsem (igaüks teeb seda mida ta kõige paremini oskab) ja odavam (sest selle tegemiseks, mida oskad, kulub kõige vähem ressursse).
Raalimise tulevik on kindlasti pilves.

Tasuta Azure partneritele

Kui sa veel ei teadnud, siis http://partners.microsoft.com on saadaval üks tasuta Azure koos SQLi ja salvestiga. See on saadaval kõigile partneritele, sõltumata tasemest.
Otsi üles selline asi nagu Cloud Essentials.
Positiivne on see, et registreeruda lubatakse ka Eesti partneritel (riigi võib panna Estonia). Windows Azure on saadaval kõige väiksema instantsina, aga katsetamiseks sobib see suurepäraselt. Tasuta konto kehtib ühe aasta.
Sinult küsitakse krediitkaarti, kuid selleks, et katta võimalikud ülekulud (nagu ikka, võid sellegi paketiga teha lisainstantse -- aga nende eest makstatakse siis tavahinnakirja alusel).
Proovige järele, minu oma funkab juba mõnda aega.

Üks põhjus kasutada Azure'i

Pikemalt ei ole vaja seletada, vaadake seda igakuist raportit:

WikiBhasha jookseb Azure'il

WikiBhasha on Microsofti rakendus, mis on mõeldud Wikipediale mitmekeelse sisu loomiseks. See võimaldab sisu kiiret tõlkimist rohkem kui 30 keelde, sealhulgas eesti keelde (väga kena neist).
Microsoft ise ütleb, et WikiBhasha on esimene pääsuke pikas Azure'i rakenduste jadas, mis tulema hakkab. Ootame huviga.
Alljärgnevalt see, mida WikiBhasha ise inglise keelest enda kohta tõlkis (kui käänded ja pöörded üle käia, siis tehnilise sisu tõlkimiseks ei olegi päris paha):
WikiBhasha beeta on brauseripõhist tööriist, mis töötab Vikipeedia saitidel. See sisaldab intuitiivse ja lihtne kasutaja kasutajaliidese kiht, mis jääb kogu sisu loomise protsessi sihtkeele Vikipeedia. See UI kihi ühendab keelelise ja koostööd teenuste, kasutaja peamiselt keskendub sisu loomise eesmärgi Vikipeedia sisu tuvastamine. Lihtne kolme-etapiline protsess juhatab sisu avastamise ja ingliskeelne Vikipeedia artiklid lähteallikana, kohaliku keele Vikipeedia artikli koostamine ja publitseerimist eesmärgi Vikipeedia kasutaja. Kuigi tüüpiline seanss võib suurendada sihtkeele Vikipeedia artikli, uued artiklid võib luua ka pärast samalaadse protsessi. WikiBhasha beeta töötab praegu Windows Internet Explorer (7.0 ja 8.0) Windows XP, Windows Vista ja Windows 7 ja Firefox (3,5 või eespool nimetatud) Linux Fedora (11 ja 12), Windows XP, Windows Vista ja Windows 7.

Windows Azure SDK 1.4

Saadaval on uus Windows Azure SDK. See on alla laetav siit.
Põhiliselt on tegemist stabiilsuse tõstmisega (mitte et sellega oleks ennegi märkimisväärseid probleeme olnud):
Resolved an issue that caused full IIS fail when the web.config file was set to read-only.
Resolved an issue that caused full IIS packages to double in size when packaged.
Resolved an issue that caused a full IIS web role to recycle when the diagnostics store was full.
Resolved an IIS log file permission Issue which caused diagnostics to be unable to transfer IIS logs to Windows Azure storage.
Resolved an issue preventing csupload to run on x86 platforms.
User errors in the web.config are now more easily diagnosable.
Enhancements to improve the stability and robustness of Remote Desktop to Windows Azure Roles.

Windows Azure

Windows Azure on operatsioonisüsteem, kuhu kasutaja saab üles laadida rakenduste pakette. Pakette saab koostada Visual Studios ja sellise lahenduse nimi on Windows Azure Cloud Service. Paketti võib kuuluda üks kuni mitu rolli ehk rakendust. Põhilised rollid on Web Role ja Worker Role .

Siin näete projekti, mis sisaldab ühte rakendust nimega "Web". See sisaldub paketis "MinitaxCloud". Vaata ka alustamisõpetust.



Visual Studio annab samas võimaluse paketi ülespanemiseks ("Publish"). Pakettide haldus on ülimalt lihtne. Sul on võimalus panna pakett üles Stagingusse (testimine) või Productionisse (avalik). Testkeskonnale antakse ajutine aadress ja avaliku keskkonna aadress on see, mida kliendid teavad.



Sul on võimalus muuta konfifaili ja serverit maha võtta. Samuti on võimalik testkeskkonna rakendust avalikuks teha (misjärel senine avalik haihtub). Alguses selline millegi muutmise võimalus hirmutab. Seejärel hakkad mõistma, et see ongi asja võlu: ei ole midagi, mida tuksi keerata.

Mille eest raha küsitakse

Algul ma sain aru, et raha küsitakse iga töötava paketi eest. Siis selgus, et raha küsitakse ka mittetöötava paketi eest. Samal hetkel kui pakett on üles laetud, hakkab taksomeeter tiksuma. Seda ka juhul, kui see pakett on maas. Tasu tiksub nii testkeskkonnas kui avalikus keskkonnas ühtemoodi, tunnihinna alusel.

Ja siis tuli veel üks üllatus: iga paketis sisalduv rakendus (role) on üks ühik, mille eest küsitakse raha. See selgus siis, kui ma nägin, et kuu jooksul on ühe paketi eest kogunenud rohkem tunde kui kuus tunde üldse on.

Niisiis tuli pisut nuputada, kuidas ühe rakendusega hakkama saada.

Mis on rakenduse sees

Rakenduse sisse saab panna tavalist kaupa nagu ikka .NET veebilehe puhul. Ka on lubatud kataloogid.



Ma ise panin Handleri, mis võtab vastu kõik saabuvad päringud. Kui oled .NETi veebilehti varemgi teinud, on Hello World projekti käimasaamine Azure'is lihtne.

Paketi üleslaadimine on väga aeglane protsess. Mitte internetiühenduse kiiruse pärast, vaid seepärast, et iga paketi jaoks luuakse täiesti uus operatsioonisüsteemi instants koos kettaruumi ja muu vajalikuga. Minu kogemuste järgi tuleb arvestada umbes 15 minutiga.

Kui sa oled inimene, kes peab oma saidil sageli muudatusi tegema, tuleb tõsiselt kaaluda veebisaidi dünaamilist uuendamist, selle asemel et kogu vajalik kraam ühte paketti kokku panna.

Windows Live ID võtmena

Igaüks võib kasutada oma veebisaidil kasutaja võtmena Windows Live ID teenust. Just nimelt võtmena, mitte isiku tuvastamiseks. Lubage selgitada põhimõtet.
Kui inimene logib sinu veebisaidile sisse Live ID abil, siis sa tegelikult ei tea, kes ta on. Kuigi näiteks Messengeris on tal nimi, meiliaadress ja võib-olla ka pilt, saad sina tema kohta teada ainult ühe kordumatu baidijada. Seega on Live ID sarnane võtmega, mis on unikaalne, kuid mille omanikku sa ei tunne. See on kasulik.
Iga veebirakenduse jaoks, kuhu Live ID-ga sisse saab, annab Microsoft sulle eraldi Client ID ja sul võib neid olla kuni 100. Iga kasutaja võti on globaalselt unikaalne ja igal kasutajal on igas rakenduses erinev võti. Seega on tagatud see, et kasutaja võtit teades ei saa seda kasutada väljaspool antud rakendust. Samas on tagatud see, et kui sinu rakendus kohtab sama võtit, on järelikult tegemist sama inimesega.
Sinu enda ülesanne on nüüd sellele inimesele andmed külge panna (küsida näiteks nime, telefoni või meiliaadressi). Kasutaja jaoks on selline lahendus ääretult mugav, sest kasutajatunnust ja salasõna pole enam vaja. Ka pole enam vaja sellist linki nagu "registreeru", sest kõik Live ID kasutajad on juba registreerunud (ka sinu rakenduses), ainult et sa pole veel näinud nende võtit.

Rakenduse registreerimine

Oma rakenduse saad Windows Live ID jaoks registreerida siin. Loomulikult pead sisse logima oma Windows Live ID-ga :) Klõpsa Add an application, anna rakendusele nimi (seda nime näidatakse sisselogijatele), vali rakenduse tüübiks Web application. Sisesta domeeni nimi. See on oluline osa, sest pärast Login-nupu vajutamist suunatakse kasutaja sellele lehele, mis siin on antud.
Ja siis on selline väga oluline küsimus nagu Domain.

Tegelikult ei küsita mitte domeeninime vaid veebiaadressi, kuhu kasutaja suunatakse pärast sisselogimist. Kuna seda aadressi hiljem muuta ei saa, mõtle järele enne kui kirjutad.

Kuidas see töötab

Sinu veebilehel on link:

<a href="http://login.live.com/wlogin.srf?appid=0000000048040531&alg=wsignin1.0&appctx=midaiganes">Logi sisse Windows Live ID abil</a>


appid on sama mis sulle registreerumisel antud Client ID.
appctx on valikuline parameeter, mis edastatakse sulle sisselogimisel (kui on tarvis sisselogijat seostada mingi eelneva infoga).
Kui kasutaja logis Live ID-ga sisse, suunatakse ta sinu eelnevalt antud lehele, näiteks "http://cloud.minitax.net/". Sellele lehele tehakse POST päring, andes kaasa teatud parameetrid, mis kasutaja identifitseerivad.
Üks neist parameetritest on "action", mille olemasolu võid oma kodulehel kontrollida.

string action = Context.Request["action"];
if (action == "logout")
{
  //kasutaja logis Windows Live ID-st välja, logi ta välja ka oma rakendusest
}
else if (action == "clearcookie")
{
  //kui oled salvestanud küpsiseid, siis kasutaja palub need nüüd tühistada. Selle kinnituseks nõutakse suvalise pildi tagastamist
  byte[] bb = Convert.FromBase64String("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7");
  Context.Response.ContentType = "image/gif";
  Context.Response.OutputStream.Write(bb, 0, bb.Length);
  Context.Response.End();
}
else if (action == "login")
{
  //kasutaja logis sisse. Kasuta Microsofti tööriistu, et Secret Key abil kasutaja võti kätte saada
  WindowsLiveLogin.User user = new WindowsLiveLogin().ProcessLogin(Context.Request.Form);
  //user objekt ongi sisseloginud kasutaja
}


Registreerumisel antakse sulle Secret Key, mis võimaldab sisselogimisel tulnud parameetrid lahti krüptida. Selle abil tagatakse, et keegi ei saa kasutaja võtit vahepeal näppida. Microsoftilt on tasuta saadaval SDK, mis sisaldab koodi kasutaja võtme lahtikrüptimiseks.
Kasutaja võti salvesta oma andmebaasi ja küsi vajadusel kasutajalt lisainfot tema kohta. Sulle on garanteeritud, et sama võti tähistab alati sama kasutajat.
Anna kasutajale võimalus ennast tsentraalselt välja logida. Näiteks, kui kasutaja on avalikus arvutis ja logib end välja Windows Live ID-st kuid mitte kõigist rakendustest eraldi, saadetakse kõigile rakendustele laiali teated tema väljalogimisest. Päringu "clearcookie" korral oodatakse kinnituseks suvalist pilti. Kuni seda pole saadud, näidatakse kasutajale, et väljalogimine pole kõikjalt veel õnnestunud.

Lihtne ja mõnus

Pärast mõningast pusimist avastad sa, et Live ID kasutamine on lihtne ja mõnus. See on turvaline nii kasutajale kui ka arendajale.
Mõned eelised kasutajale:
* veebisaidile ei pea tingimata "registreeruma", et oma profiili luua
* oma identifitseerimiseks ei pea tingimata oma meiliaadressi andma
* veebisaidid ei saa teada sinu salasõna
* meelde jätta tuleb ainult üks salasõna
Mõned eelised teenusepakkujale:
* kuna kasutaja ei pea registreeruma, suurendab lihtsus püsiklientide arvu
* levinud tehnoloogia kasutamine suurendab rakenduse usaldusväärsust kasutajate silmis
* Microsoftilt saadud kasutaja võtit võib usaldada
MileMarx: An exciting new gadget for automating mileage reimbursement."
everyday.com: We helped in writing the kernel of this one-of-its-kind multilingual website."
MileMarx: FaceBook fan page."
DNS Azure: The DNS service for Windows Azure."
Regio: We helped this Estonia's leading cartography company to employ cutting-edge .NET and WMF technology."
Van Zoig produces LawTime, Estonia's best software for lawyers. We helped them to utilize the newest .NET and WMF technology."
We helped Raintree to become America's #1 health care software. We designed it's client-server architecture."
Estonian Ministry of Education and Research needed a new system for document handling and online publishing. We were happy to help."
minitax.net: A success story of an innovative way to reduce tax liability with a clever GPS. Owned by Semitar."
Semitar is Microsoft Partner and Microsoft Silverlight Partner Initiative member. We pioneer the new Windows Azure technology."
Track24: We wrote their innovative software for real-time vehicle tracking. By utilizing it, they have become one of the best in Eastern Europe."
The C# blog by Tan Silliksaar"
Parallel Programming Blog by Tan Silliksaar"