Scala-verkkokehittäjät usein jättää huomioimatta seuraukset, jos tuhannet käyttäjät käyttävät sovelluksiamme samanaikaisesti. Ehkä se johtuu siitä, että rakastamme nopeasti prototyyppiä; Ehkä se johtuu siitä, että tällaisten skenaarioiden testaaminen on yksinkertaisesti kovaa .
Tästä huolimatta aion väittää, että skaalautuvuuden huomiotta jättäminen ei ole niin huono kuin miltä se kuulostaa - jos käytät asianmukaisia työkaluja ja noudatat hyviä kehityskäytäntöjä.
Skaalautuvuuden huomiotta jättäminen ei ole niin huono kuin miltä se kuulostaa - jos käytät oikeita työkaluja.Jokin aika sitten aloitin Lojinha-projektin (joka tarkoittaa käännöksenä 'pieni myymälä' portugaliksi), yrityksenä rakentaa huutokauppasivusto. (Muuten, tämä projekti on avoin lähdekoodi ). Motivaationi olivat seuraavat:
Joten ilmeisesti, kuten edellä mainittiin, päätin käyttää Pelata! Kehys . Minulla ei ole tarkkaa laskua siitä, kuinka kauan rakentaminen kesti, mutta ei varmasti kulunut kauan, kun sivustoni oli toiminnassa yksinkertaisen järjestelmän ollessa käytössä http://lojinha.jcranky.com . Oikeastaan vietin ainakin puolet kehitysajasta suunnitteluun, joka käyttää Twitter Bootstrap (muista: en ole suunnittelija…).
Yllä olevan kappaleen pitäisi tehdä ainakin yksi asia selväksi: En huolissani suorituskyvystä liikaa, jos ollenkaan Lojinhaa luodessani.
Ja se on täsmälleen minun mielipiteeni: oikeiden työkalujen - työkalujen, jotka pitävät sinut oikealla tiellä, käyttämisessä on voimaa, jotka rohkaisevat sinua seuraamaan parhaita kehityskäytäntöjä rakenteeltaan.
Tässä tapauksessa nuo työkalut ovat Play! Kehys ja Scalan kieli , kanssa Akka tekemällä joitain 'vierailevia esiintymisiä'.
Anna minun näyttää sinulle mitä tarkoitan.
On yleisesti sovittu, että muutettavuuden minimointi on hyvä käytäntö. Lyhyesti sanottuna, muutettavuus vaikeuttaa koodistasi päättämistä, varsinkin kun yrität ottaa käyttöön rinnakkaisuutta tai samanaikaisuutta.
Näytelmä! Scala-kehys saa käyttämään muuttumattomuutta suuren osan ajasta, samoin itse Scala-kieli. Esimerkiksi ohjaimen tuottama tulos on muuttumaton. Joskus saatat pitää tätä muuttumattomuutta 'häiritsevänä' tai 'ärsyttävänä', mutta nämä 'hyvät käytännöt' ovat 'hyviä' syystä.
Tässä tapauksessa ohjaimen muuttumattomuus oli ehdottoman tärkeää, kun päätin lopulta suorittaa joitain suorituskykytestejä: Löysin pullonkaulan ja korjaan sen yksinkertaisesti välimuistiin tämän muuttumattoman vastauksen.
Tekijä välimuisti Tarkoitan vastausobjektin tallentamista ja samanlaisen ilmentymän tarjoamista uudelle asiakkaalle. Tämä vapauttaa palvelimen tarpeesta laskea tulos uudelleen. Ei ole mahdollista palvella samaa vastausta useille asiakkaille, jos tämä tulos on muutettavissa.
Haittapuoli: Asiakkaat voivat saada vanhentuneita tietoja lyhyeksi ajaksi (välimuisti vanhenee). Tämä on ongelma vain tilanteissa, joissa asiakkaan on ehdottomasti käytettävä uusimpia tietoja ilman viivettä.
Tässä on Scala-koodi aloitussivun lataamiseksi luetteloon tuotteista ilman välimuistia:
def index = Action { implicit request => Ok(html.index(body = html.body(Items.itemsHigherBids(itemDAO.all(false))), menu = mainMenu)) }
Lisää nyt välimuisti:
def index = Cached('index', 5) { Action { implicit request => Ok(html.index(body = html.body(Items.itemsHigherBids(itemDAO.all(false))), menu = mainMenu)) } }
Melko yksinkertainen, eikö olekin? Tässä, 'indeksi' on välimuistijärjestelmässä käytettävä avain ja 5 on viimeinen käyttöaika sekunteina.
Välimuistin jälkeen siirtonopeus nousi 800 pyyntöön sekunnissa. Se on parannus yli 4x alle kahdella rivillä koodia.Tämän muutoksen vaikutuksen testaamiseksi suoritin joitain JMeter-testejä (sisältyvät GitHub-repoon) paikallisesti. Ennen välimuistin lisäämistä saavutin noin 180 pyyntöä sekunnissa. Välimuistin jälkeen siirtonopeus nousi 800 pyyntöön sekunnissa. Se on parannus yli 4x alle kahdelle riville koodia.
Toinen alue, jolla oikeilla Scala-työkaluilla voi olla suuri ero, on muistin kulutus. Tässä taas, Pelaa! työntää sinut oikeaan (skaalautuvaan) suuntaan. vuonna Java , 'normaalille' verkkosovellukselle, joka on kirjoitettu servlet-sovellusliittymä (eli melkein kaikki siellä olevat Java- tai Scala-kehykset), on erittäin houkuttelevaa laittaa paljon roskaa käyttäjän istuntoon, koska sovellusliittymä tarjoaa helposti soittaa -menetelmiä, joiden avulla voit tehdä niin:
session.setAttribute('attrName', attrValue);
Koska tietojen lisääminen käyttäjäistuntoon on niin helppoa, niitä käytetään usein väärin. Tämän seurauksena riski käyttää liikaa muistia mahdollisesti ilman syytä on yhtä suuri.
Pelaa! kehys, tämä ei ole vaihtoehto - kehyksessä ei yksinkertaisesti ole palvelinpuolen istuntotilaa. Näytelmä! kehyksen käyttäjäistunto pidetään selainevästeessä, ja sinun on elettävä sen kanssa. Tämä tarkoittaa, että istuntotilan koko ja tyyppi on rajoitettu: voit tallentaa vain merkkijonoja. Jos haluat tallentaa esineitä, sinun on käytettävä välimuistimekanismia, josta keskustelimme aiemmin. Voit esimerkiksi tallentaa nykyisen käyttäjän sähköpostiosoitteen tai käyttäjänimen istuntoon, mutta joudut käyttämään välimuistia, jos sinun on tallennettava koko käyttäjäobjekti verkkotunnusmallistasi.
Pelata! pitää sinut oikealla tiellä ja pakottaa sinut harkitsemaan huolellisesti muistisi käyttöä, mikä tuottaa käytännössä klusterivalmiita ensikierroskoodeja.Jälleen tämä saattaa tuntua aluksi tuskalta, mutta todellisuudessa Play! pitää sinut oikealla tiellä ja pakottaa sinut harkitsemaan huolellisesti muistisi käyttöä, mikä tuottaa käytännössä klusterivalmiita ensikierroskoodeja - varsinkin kun otetaan huomioon, että ei ole palvelinpuolen istuntoa, joka olisi levitettävä koko klusterissasi, mikä elävöittää äärettömän helpompaa.
Seuraava tässä näytelmässä! tarkastelemme, kuinka Play! loistaa myös asynkronisessa (kroonisessa) tuessa. Ja sen alkuperäisten ominaisuuksien lisäksi Play! avulla voit upottaa Akka , tehokas työkalu asynkronointiin.
Altough Lojinha ei vielä hyödynnä Akkaa, sen yksinkertaista integraatiota Playen! teki siitä todella helppoa:
Lyhyesti sanottuna Akka on Näyttelijämalli jonka teki tunnetuksi Erlang . Jos et tunne Akka Actor -mallia, kuvittele sitä pienenä yksikkönä, joka kommunikoi vain viestien kautta.
Lähettääksesi sähköpostia asynkronisesti, luon ensin oikean viestin ja näyttelijä . Sitten tarvitsen vain jotain:
EMail.actor ! BidToppedMessage(item.name, itemUrl, bidderEmail)
Sähköpostin lähetyslogiikka toteutetaan näyttelijän sisällä, ja viesti kertoo näyttelijälle, minkä sähköpostin haluamme lähettää. Tämä tapahtuu tulipalo ja unohda -menetelmässä, mikä tarkoittaa, että yllä oleva rivi lähettää pyynnön ja jatkaa sitten kaiken sen jälkeen, mitä meillä on (eli se ei estä).
Lisätietoja Play!: N alkuperäisestä Asyncistä saat katsomalla viralliset asiakirjat .
Yhteenvetona: Kehitin nopeasti pienen sovelluksen, Myymälä , joka pystyy skaalautumaan hyvin ja hyvin. Kun törmäsin ongelmiin tai löysin pullonkauloja, korjaukset olivat nopeita ja helppoja, ja niillä oli paljon kiitosta käytetyistä työkaluista (Play !, Scala, Akka ja niin edelleen), mikä pakotti minut noudattamaan parhaita käytäntöjä tehokkuuden ja skaalautuvuus. Huolimatta suorituskyvystä, pystyin skaalautumaan tuhansiin samanaikaisiin pyyntöihin.
Harkitse työkalusi huolellisesti kehittäessäsi seuraavaa sovellustasi.