Välimuisti, Cloud functions, PostgreSQL, Avoin data - Pääteohjaus 6
Cloud Run Functions
Google tarjoamat pilvifunktiot (Cloud Run functions) ovat yksi mahdollisuus Cloud runin lisäksi rakentaa omia sovelluksia tai erityisesti sovelluksen osia. Jos on tarve yksittäiselle toiminnolle, voi sen hyvin toteuttaa cloud functiona. Cloud run soveltuu paremmin kokonaisille Flask-sovelluksille ja sovelluksille joiden pitää vastata pyyntöihin nopeammin. Aiemmin toteutettu alkulukulaskenta olisi sopiva pilvifunktio. Pilvifunktioina voi toteuttaa myös taustalla toimivia funktioita.
Pilvifunktiot ovat tilattomia. Periaatteessa pilvifunktion ympäristö käynnistetään tyhjästä (cold start) jokaisella funktion kutsukerralla. Tämä on myös hidasta eli funktio vastaa ensimmäisellä kutsukerralla hitaammin, kuin heti seuraavilla. Käytännössä sama toimintaympäristö (instanssi) on elossa jonkun aikaa funktion kutsumisen jälkeen. Samaa ympäristöä voidaan käyttää seuraavalla kutsulla tai sitten luodaan uusi. Saman instanssin vastatessa uudelleen tulee vastaus huomattavasti nopeammin. Kaikki mitä voi myöhemmin uudelleen käyttää kannattaa pitää instanssin muistissa tallessa globaaleina muuttujina. Lue Tips & Tricks.
- Lue Python Quickstart ja Your First Function: Python
- Siirrä edellä mainittujen dokumenttien ohjeiden avulla aiemmin kirjoitettu alkulukusovellus pilvifunktioksi
- Valitse käyttöön vain 128 megatavua muistia
- Katso mallia valmiista esimerkkifunktiosta. Funktiosi saa yhden parametrin (request), joka on Flaskin request-objekti
- Muista lisätä requirements.txt-tiedostoon käyttämäsi kirjastot
- Muista valita kirjoittamasi funktio sovelluksen lähtöpisteeksi (entry point)
- Sovelluksen on oltava main.py-tiedostossa
- Muista, että oletuksena Cloud Functions ei ole mikään laskentahirmu. Älä kokeile 10000 suurempaa lukua.
- Välimuisti täytyy tehdä cachetools-kirjaston
avulla, koska Flask ja Flask-Caching eivät toimi aivan tavalliseen tapaan pilvifunktiossa.
Cachetools toimii hyvin samalla tavalla kuin Flask-Caching.
- Käytä TTLCache
-
from cachetools.keys import hashkey from cachetools import cached, TTLCache cache = TTLCache(maxsize=32) @cached(cache, key=hashkey) def oma_funktio(n): ...
Kokeile mallia
from cachetools import cached, TTLCache
from cachetools.keys import hashkey
def main(request):
n = request.args.get("n", 1)
if n:
return prime(n)
else:
return prime(2)
cache = TTLCache(maxsize=100, ttl=6000)
@cached(cache, key=hashkey)
def prime(n):
if int(n) <= 1:
return "[]"
# hidas alkulukulaskenta-algoritmi
# https://medium.com/@GalarnykMichael/prime-numbers-using-python-824ff4b3ea19
primes = []
for possiblePrime in range(2, int(n)):
isPrime = True
for num in range(2, possiblePrime):
if possiblePrime % num == 0:
isPrime = False
if isPrime:
primes.append(possiblePrime)
return str(primes)
Cloud Run VS Cloud Functions: What’s the lowest cost?
Cloud functions vs App engine vs Cloud Run vs GKE
Cloud Run and Cloud Function: What do I use? And Why?
Cloud SQL
Otetaan käyttöön PostgreSQL-tietokanta Googlen pilvipalvelussa.
Tätä tietokantaa voisi periaatteessa käyttää myös users.jyu.fi:ssä olevalla sovelluksella, mutta it-palvelut on estänyt tämän.
- Valitse sama projekti kuin loit edellisellä viikolla
- Luo uusi Cloud SQL instanssi
- Valitse tietokantamoottoriksi PostgreSQL
- Valitse seuraavat asetukset. Huom! Älä missään tapauksessa paina Create-painiketta ennen kuin olet käynyt läpi kaikki lisäasetukset

- Valitse tyypiksi Enterprise (99.95% availability). Presetiksi kannattaa valita Sandbox, jota sitten vielä kuitenkin kustomoidaan
-
Valitse tietokannan versioksi uusin Postgresql eli PostgreSQL 18.

- Keksi sopiva Instance Id esim. ties4080. Tätä ei voi myöhemmin vaihtaa.
- Keksi tietokannan ylläpitäjän salasana
- Valitse sijainniksi europe-north1 (Finland) Valitse Single zone. Useamman zonen versiota tarvitset vain erityisen tärkeille palveluille.
- Valitse Customize your instance

- Valitse Machine configuration.
- Google tarjoaa oletuksena koneen tyypiksi 2 vcpu + 3.75 GB muistia. Tämä on aivan liian kallis konfiguraatio pelkkään testikäyttöön. Valitse Shared core ja 1 vCPU, 0.614 GB. Tämä riittää aivan mainiosti pienille tietokannoille joille ei ole valtavasti yhtäaikaisia käyttäjiä eikä ole kallis.
-
Valitse Storage. Valitse Storage typeksi HDD ja kapasiteetiksi pienin 10 GB. Valitaan siis halvimmat mahdolliset. Poista ruksi kohdasta Enable automatic storage increases, koska emme sitä nyt tarvitse. 10 gigaa riittää enemmän kuin hyvin.


- Automaattiset varmuuskopioita ei harjoitellessa tarvita, mutta tärkeämmissä tietokannoissa varmuuskopiointi on ehdottomasti valittava.
-
Tarkista vielä, että asetuksesi vastaavat vieressä olevaa yhteenvetoa. Tarkista erityisesti, että käyttökustannukset ovat vain 0.01 dollaria tunnilta. Jos hintayhteenveto näyttää suurempia kustannuksia, niin tarkista vielä kaikki edellämainitut asetukset.

- Valitse nyt Create instance
Tarkempi ohje: Quickstart for Cloud SQL for PostgreSQL
- Odota instanssin valmistumista. Valitse sen jälkeen valmistunut instanssi.
- Kopioi talteen instanssisi ip-osoite ja yhteysnimi

- Kokeile ottaa yhteys tietokantaan Cloud Shellin avulla. Valitse linkki Connect using Cloud Shell
- Saat Cloud Shelliin valmiin komennon jolla voit avata yhteyden tietokantaasi
Tarvitset aiemmin antamaasi ylläpitäjän salasanaa
- Nyt sinulla on käytössä psql-komentotyökalu, joka toimii samaan tapaan kuin sqlite3-tietokannan vastaava työkalu. Jos jonkun merkin syöttäminen suoraan näppäimistöltä ei onnistu, niin kokeile vasemman ylänurkan näppäimistökuvakkeesta aukeavaa valikkoa ja sieltä send key combination-valintaa.
- Oletuksena sinulla ei ole palvelimessa vielä mitään tietokantaa. Luo nyt uusi tietokanta seuraavalla komennolla:
CREATE DATABASE ohjaus6 ENCODING='UTF8' LC_COLLATE='fi_FI.utf8' LC_CTYPE='fi_FI.utf8' TEMPLATE template0;
psql-työkalusta poistutaan komennolla \quit - psql-työkalua on helpompi käyttää omalta koneelta. Sama työkalu löytyy myös halava/jalava-koneista, mutta niistä on estetty yhteydet yliopiston verkon ulkopuolelle. Omaan linux-koneeseen saman työkalun saa, jos asentaa omaan koneeseen postgresql-tietokannan. Windows-koneeseen on psql-työkalu saatavilla suoraan zip-paketissa. Pura paketti esim. C:\mytemp-kansioon. Voit myös asentaa koko Postgresql-palvelimen omalle koneellesi.
- Sallitaan yhteydet postgresql-tietokantaan omalta tietokoneelta. Siirry Connections-välilehdelle. Valitse Add network ja lisää oman koneesi ip-osoite

Jos tietokoneesi on läppäri ja siirtelet sitä verkosta toiseen, niin myös ip-osoite vaihtuu ja joudut lisäämään jokaisen osoitteen erikseen tai lisäämään sallituksi isomman verkkoalueen.
- Ota nyt yhteys tietokantaasi. Käynnistä command prompt. Käynnistä edellä lataamasi psql-työkalu seuraavalla tavalla:
psql -U postgres -h oman.postgresql-palvelimen.ip.osoite -d ohjaus6
Tarvittava ip-osoite näkyy tietokantapalvelininstanssisi overview-sivulla
- Tallenna itsellesi resepti.sql-tiedosto. Lataa tämä tiedosto
psql-työkalussa komennolla:
\i resepti.sql
Nyt sinulla pitäisi olla reseptitietokanta luotuna. Käytetty sql-koodi on lähes sama kuin sqlite-tietokannan kanssa. Vain autoincrement-tyyppiset kentät on täytynyt muuttaa serial-tyyppisiksi ja triggerit on voitu jättää pois. - Jos haluat käyttää
Cloud Run -sovelluksessa postgresql-tietokantaasi, joudut käyttämään samaa tietokantaa
myös omalla koneella testatessa. PostgreSQL-tietokantaa varten ei ole lokaalia emulaattoria.
Toki voit myös asentaa omalle koneellesi PostgreSQL-palvelimen, jota voit käyttää testaamiseen.
Cloud runissa pyörivän sovelluksen tietokantayhteys vaatii, että teet Googlen oman ohjeen mukaiset säädöt. Toinen vaihtoehto on sallia yhteydet kaikista ip-osoitteista, mutta se ei ole järkevää, koska tietokantasi on sitten alttiimpi väärinkäytöksille.
- Silloin kun et käytä CloudSQL-tietokantaasi, niin sammuta (stop) se. Cloud SQL -tietokanta on
normaalisti jatkuvasti päällä ja kuluttaa koko ajan krediittejä. Jos et oikeasti
käytä tietokantaa, niin poista (delete) se kokonaan.

Tietokantayhteys
Voit käsitellä tietokantaasi aivan samalla tavalla kuin sqlite3-tietokantaa. Joudut vain avaamaan tietokantayhteyden Googlen ohjeiden mukaan.
- Asenna psycopg-kirjasto
pip install psycopg2-binary - Tietokantayhteys kannattaa muodostaa psycopg2-kirjastolla.
import psycopg2 #yhteystiedot kannattaa lukea ympäristömuuttujista tai tiedostosta eikä tallentaa suoraan ohjelmakoodiin conn = psycopg2.connect("dbname=tietokannannimi user=käyttäjä host=ip-osoite password=salasana") cur = conn.cursor() cur.execute("SELECT * FROM Weather") print(cur.fetchone()) # muista myös tarvittaessa commit() tai rollback() cur.close() conn.close()- Haluatko kyselyn tulokset dict-muodossa?
import psycopg2 import psycopg2.extras conn = ... cursor = conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor) - Yhteyspoolia tarvitaan lähes aina web-sovelluksissa. Lue
Connections pooling.
import psycopg2.pool #luodaan yhteyspooli, jossa on vähintään 1 yhteys, mutta enintään 10 pool = psycopg2.pool.SimpleConnectionPool( 1, 10, user='ohjaus6', password='123456', host='localhost', port='5432', database='malli') #pyydetään poolista yhteys connection = pool.getconn() cursor = connection.cursor() cursor.execute('SELECT * FROM foo') results = cursor.fetchall() #palautetaan yhtyes pooliin pool.putconn(connection) - Passing parameters to SQL queries
- Psycop2 FAQ
- Advanced topics
Jos et käytä postgresql-tietokantaasi, niin sammuta se ja poista kokonaan siihen liittyvä projekti ja tiedostot Googlen pilvestä.
Avoin data
Käytetään muiden tekemiä XML-dokumentteja ja WWW-sivuja tiedonlähteenä.
DOM-rajapinta on tuttu jo TIEA2120 WEb-käyttöliittymien ohjelmointi -kurssilta. Jos olet unohtanut, niin kertaa Document Object Model (DOM) ja Javascript ja DOM. Tässä pääteohjauksessa opetellaan DOM-rajapinnan käyttäminen Python-ohjelmointikielellä.
Ulkoisen XML-datan sisällyttäminen omalle sivulle
- Aloita uusi python-ohjelma. Pyritään hakemaan ja parsimaan https://appro.mit.jyu.fi/ties4080/ohjaus/ohjaus6/data.xml- tiedosto ja sisällyttämään siitä tärkeimmät osat omalle sivulle. Käsiteltävän tiedoston rakenne on sama kuin aiemmin käytetyissä json-versioissa. Katso malliohjelman tuloste (Mallin lähdekoodi).
- Haetaan XML-dokumentti käyttäen Pythonin xml.dom.minidom ja urllib-kirjastoja.
- Tee ensin pelkästään komentoriviltä toimiva versio.
from xml.dom.minidom import parse import urllib doc = parse( urllib.urlopen("tähän sivun osoite")) print doc.toxml('UTF-8')Kokeile tulostuuko komentoriviltä ajettaessa sivun sisältö - Kaivellaan dokumentista yksittäisiä osia. Haetaan ensimmäiseksi yleistietoja:
# Haetaan kilpailun tiedot eli ensimmäiset esiintymät nimi, kesto, alkuaika ja loppuaika elementeistä nimi = doc.getElementsByTagName("nimi")[0] kesto = doc.getElementsByTagName("kesto")[0] alkuaika = doc.getElementsByTagName("alkuaika")[0] loppuaika = doc.getElementsByTagName("loppuaika")[0] - Tulosta kaikkien hakemiesi elementtien tekstisisältö. Muista kokeilla komentorivillä, että ohjelma toimii.
textContent-ominaisuus ei toimi minidomissa joten joudut käyttämään:
nimi.firstChild.nodeValue
- Tee samaan tapaan listaus joukkueiden nimistä. Hae kaikki joukkueet-elementit, käy ne silmukassa läpi, hae jokaisen joukkueet-elementin alta ensimmäinen nimi-elementti ja tulosta sen sisältö.
- Mitäs jos haluat tulostaa joukkueiden nimet sarjoittain? Kokeile tehdä tämä ja tulosta aina ensin sarjan nimi ja sen alle sisennettynä kaikkien sarjaan kuuluvien joukkueiden nimet
- Tee nyt sovelluksestasi web-sovellus (CGI-ohjelma, Flask-sovellus tai appengine-sovellus) ja luo XML-tiedoston sisällöstä järkevä html-dokumentti. Vrt. mallisovellus ((Mallin lähdekoodi)).
XML ja nimiavaruudet
XML-dokumenttiin voi olla sisällytetty elementtejä useasta eri nimiavaruudesta (namespace). Tämä täytyy osata huomioida dokumentin sisältöä käsiteltäessä. Käytetystä kirjastosta riippuen voi joutua käyttämään getElementsByTagNameNS-funktiota tavallisen getElementsByTagName-funktion sijaan. Esim.
mi = doc.getElementsByTagNameNS("http://www.w3.org/1998/Math/MathML", "mi")
Käyttämällä nimiavaruuden osaavaa versiota varmistaa, että ei ainakaan saa vahingossa tulokseen vääriä elementtejä. Eri nimiavaruuksissa voi olla samannimisiä elementtejä.
Joskus XML-dokumenteissa on myös CDATA-osioita, joiden parsiminen täytyy joillakin kirjastoilla tehdä poikkeavasti:
if node.firstChild.nodeName == "#cdata-section":
print node.firstChild.data
else:
print node.firstChild.nodeValue
- Katso esimerkki, joka parsii ylen rss-feediä. Esimerkin Lähdekoodi.
- Tee sovellus, joka tulostaa https://www.w3.org/TR/XHTMLplusMathMLplusSVG/sample.xhtml-dokumentista kaikkien h2-tason otsikoiden tekstit
- Tulosta myös kaikkien mathml-osioiden mi-elementtien sisältö
- Tulosta myös kaikkien svg-polygonien pisteet (points)
ElementTree
Voit halutessasi opetella käyttämään myös ElementTree XML API-rajapintaa. ElementTree-rajapinnan käyttäminen on hieman yksinkertaisempaa kuin DOM-rajapinnan. ElementTree-rajapintaa tarvitset, jos joudut parsimaan rakenteeltaan rikkinäisiä html-dokumentteja (tagsoup...). Tällöin käytetään esimerkiksi BeautifulSoup-kirjastoa, joka toteuttaa ElementTree-rajapinnan.
Käyttäjien kommentit