Üheksas praktikum - Mikroteenused
Selles praktikumis jagame oma varasema rakenduse kaheks väiksemaks mikroteenusteks loome juurde veel ühe mikroteenuse rakenduse kasutaja liidese jaoks (front-end) ja käivitame loodud mikroteenuse põhise rakenduse dockeri konteineritena.
Viited
- Docker'i ülevaade - https://docs.docker.com/get-started/overview/
- Docker käsurea käskude ülevaade - https://docs.docker.com/engine/reference/commandline/cli/
- Dockerfaili spetsifikatsioon - https://docs.docker.com/engine/reference/builder/
Probleemide korral kontrollige:
- Pinnitud sõnumeid
#praktikum-8-mikro
kanalis kursuse Slacki's. - Võimalikud probleemid ja nende potentsiaalsed lahendused osa praktikumi juhendi lõpus.
- Küsige otse
#praktikum-9-mikro
Slacki kanalis.- Ka siis kui soovite lihtsalt viheid.
Ülesanne 9.1: Flask rakenduse jagamine kaheks väisemaks mikroteenuseks.
Selles ülesandes jagame oma Azure Blob Storage't kasutava Python Flask API kaheks mikroteenuseks.
NB! Kui teil mingil põhjusel on vahele jäetud Azure REST API (mis salvestas raamatuid Azure Blob Store'i), siis võite kasutada mõnda oma teist varasemat REST API't, aga praktikumi õpetus võib olla natuke erinev.
Jagage oma Azure Flask API kaheks Python Flask Rakenduseks:
- hs9-flask-api-raamatud
- Sisaldab ainult API meetodeid:
- GET /raamatud/<book_id>
- DELETE /raamatud/<book_id>
- GET /raamatud
- POST /raamatud
- Sisaldab ainult API meetodeid:
- hs9-flask-api-raamatute-otsing
- Sisaldab ainult API meetodeid:
- POST /raamatu_otsing
- Sisaldab ainult API meetodeid:
- Peaks piisama sellest, kui teete projektidest koopiad, ning eemaldate koodi, mis kuulub teisele API'le.
- Testige, et mõlemad Flask API'd töötavad.
- Mõlemad ühenduvad samasse (teie poolt varasemalt üles seatud) Azure Blob Storage teenusesse, et raamatu failidele ligi pääseda.
Ülesanne 9.2: Mikroteenuste konteineriseerimine ja testimine Dockeris
Selles ülesandes konteineriseerime mõlemad mikroteenused. Kuna meil on vaja üles seada ühendus Azure Blob Storage teenusega, siis tuleb seda teha natukene erinevalt eelmise praktikumi sisuga.
Looge Docker pildid mõlema mikroteenuse jaoks. Docker Piltide/Image nimed peaksid olema:
- hs9-flask-api-raamatud
- hs9-flask-api-raamatute-otsing
Konteineriseerimise protsess:
- Saata kasutada sama lähenemist, kui eelmises praktikumis, aga on mõned erinevused:
- DockerFile'is kasutame
python:3-alpine
asemel Python slim Docker pilti:FROM python:3.8-slim
- requirements.txt faili peame lisama veel kaks teeki:
azure-storage-blob==12.11.0 flask-cors==3.0.10
- flask-cors'i kasutame selleks, et lubada API väljakutsumist teistest mikroteenustest hiljem, kui loome ka veebiliidese oma API'le.
- Peame sisse viima ka mõned muudatused Flask rakenduses:
- Lisage import käsk
from flask_cors import CORS
- Lisage flask-cors teegi konfiguratsioon programmi algusesse peale Flask app objekti loomist:
app = Flask(__name__) cors = CORS(app, resources={r"/raamatud/*": {"origins": "*"}, r"/raamatu_otsing/*": {"origins": "*"}})
- See lubab APIt välja kutsuda läbi teiste rakenduste, mis muidu keelatakse ära brauserite poolt (Cross Origin Resource Sharing limitatsioonide tõttu). Lisainfot selle kohta leiate siit: https://flask-cors.readthedocs.io/en/latest/
- PS! See ei ole otseselt vajalik, aga võite resources konfiguratsiooni seest eemaldada mikroteenusesse mitte kuuluvate teede kirje.
- Peame liigutama Azure ühenduse konfigureerimisega seotud koodi välja
if __name__ == _main_:
blokist.__main__
bloki sisu käivitatakse ainult siis, kui rakendus pannakse tööle tavalise Python rakendusena.- Aga meie (eelmise nädala) Docker conteiner käivitab rakenduse Flask mooduli kaudu, mis tähendab seda, et main plokki ei käivitata kunagi Docker konteineri sees.
- Liigutage Azure blob seadistamisega seotud kood main plokist väljaspoole (enne main plokki). See võiks välja näha "umbes" nii:
# Azure blob konfiguratsioon blob_connection_string = os.getenv('AZURE_BLOB_CONNECTION_STRING') blob_service_client = BlobServiceClient.from_connection_string(blob_connection_string) blob_container_name = "pellepraks7blob" if __name__ == '__main__': app.run(debug = True)
- NB! ärge ära unustage kontrollida et blob_container_name väärtus on teie blob konteineri oma!
- Lisage import käsk
- AZURE_BLOB_CONNECTION_STRING seadistame alles konteineri käivitamisel, et see ei oleks ühtegi faili salvestatud ning ei lekiks kogemata.
- Soovituslik on kopeerida AZURE_BLOB_CONNECTION_STRING väärtus Azure Pilvetehnloloogia praktikumi PyCharm projektist.
- Kõik
;
märgid peaksid selle sees olema asendatud\;
märkidega
- DockerFile'is kasutame
Docker konteinerite käivitamine:
- Paneme hs9-flask-api-raamatud tööle pordi 5000 peal ning hs9-flask-api-raamatute-otsing tööle pordi 5001 peal:
docker run -di -p 5000:5000 --env AZURE_BLOB_CONNECTION_STRING=DefaultEndpointsProtocol=https\;Account...=\;EndpointSuffix=core.windows.net hs9-flask-api-raamatud
docker run -di -p 5001:5000 --env AZURE_BLOB_CONNECTION_STRING=DefaultEndpointsProtocol=https\;Account...=\;EndpointSuffix=core.windows.net hs9-flask-api-raamatute-otsing
- Kindlasti asendage AZURE_BLOB_CONNECTION_STRING väärtus õige - oma Azure teenuse ühenduse konfiguratsiooni - väärtusega.
Ülesanne 9.3: Kasutajaliidese loomine
Selles ülesandes loome kolmanda mikroteenuse. Selleks om HTML-põhise kasutajaliides meie veebiteenuse API mikroteenustele, mis kasutab JavaScript'i, et päringuid saata API'de vastu. Samuti seame selle rakenduse üles eraldi Docker konteinerina.
- Looge uus projekt/kausta
hs9-front-end
. Saate vabalt valida failiredaktori (näiteks notepad++) või mõne HTML/JS IDE. - Loome sinna kaks faili:
front-end.html
- Sisaldab meie veebiliidese HTML koodi ja impodib JavaScrip faili- Faili sisu võtke siit: https://raw.githubusercontent.com/pjakovits/wsds/main/p09/front-end.html
apiparingud.js
- Sisaldab JavaScript koodi, mis suhtleb meie mikroteenustega.- Esialgne faili sisu võtke siit: https://raw.githubusercontent.com/pjakovits/wsds/main/p09/apiparingud.js
front-end.html
Faili me ei muuda. Selles failis on kaks vormi:- Raamatu loomine
- Raamatust sõne otsimine
- Lisaks on seal HTML plokk mille kaudu saab POST päringute tulemust näidata kasutajale
- Lisaks on seal HTML plokk raamatute nimekirja näitamiseks
- Lisaks imporditakse JavaScript fail:
<script type="text/javascript" src="apiparingud.js"></script>
- Lisaks pannakse eraldi scriptis tööle JavaScript meetod
listiraamatud()
, mis vastutab raamatute nimekirja pärimise eest API'lt, ning mille me implementeerime ise JavaScript failis hiljem. apiparingud.js
failis tuleb meil mõned muudatused teha.- Praegu sisaldab see ainult abimeetodeid POST, GET ja DELETE meetodite välja kutsumiseks.
- Lisaks on POST päringu välja kutsumise JavaScript meetod
handleFormSubmit
loodud kavalalt.- Kui see lisada HTML POST vormi kuulama, siis saab selle abil automaatselt saata vormi
target
aadressile POST päringu, millega pannakse kaasa JSON dokument, mis sisaldab kõiki selle HTML vormiinput
tüüpi sisendeid. - Samuti saab see JavaScript meetod kätte REST POST päringu vastuse JSON dokumendina.
- Ning seda ilma, et kasutaja brauseri kaudu edasi suunataks API aadressile. Mis võimaldab meil POST päringut taustal läbi viia kui kasutaja vajutab HTM vormi
submit
nupul - Mõlemale HTML vormi (raamatu loomine ning raamatust otsimine)
submit
nupule onhandleFormSubmit
juba HTML failis lisatud
- Kui see lisada HTML POST vormi kuulama, siis saab selle abil automaatselt saata vormi
Veebiliidest saab testida avades HTML faili brauseri kaudu (Näiteks Chrome).
- Raamatu loomine ja raamatust otsimine olemasolevate HTML vormide kaudu juba töötab (kui API'd on käima pandud), aga hetkel ei ole veel loodud JavaSCript funktsioonid, mis tulemust meile veebilehel näitaks.
- Implementeerime JavaScript failis
listiraamatud()
meetodi sisu:- Kutsume meetodi alguses välja GET päringu meie raamatute API vastu, mis kuulab päringuid localhost peal pordil 5000:
const responseData = await getDataAsJson("http://localhost:5000/raamatud");
- NB!
responseData
muutuja on JSON objekt, mille sees peaks olema REST API päringu vastus
- NB!
- Otsime üles HTML dokumendi elemendi ID väärtusega
raamatud_result
:const resultElement = document.getElementById("raamatud_result");
- Seame selle ploki väärtuseks tühja sõne:
resultElement.innerHTML = ""
- Loome tsükkli, mis iga vastuses tagastatud raamatu ID kohta lisab
raamatud_result
HTML plokki uue lingi, mille kaudus aab raamatut alla laadida API'st:resultElement.innerHTML = "" for (var raamat of responseData.raamatud){ resultElement.innerHTML += '<a href="http://localhost:5000/raamatud/'+raamat+'" download="'+raamat+'.txt" >' +raamat+".txt</a> " + '<a href="#" onclick="deleteObject(\'http://localhost:5000/raamatud/'+raamat+'\')" > [kustuta]</a>' + "<br />"; }
responseData.raamatud
on API vastuse JSON element, milles on raamatu ID'de list.- Lisaks raamatute alla tõmbamise lingile, lisatakse ka raamatu kustutamise link. Selles lingis on JavaScript
onClick
sündmuse kuulaja, mis lingile vajutamisel kutsub väljadeleteObject(raamatu_API_link)
meetodi, mis hoolitseb raamatu kustutamise eest.
- Kutsume meetodi alguses välja GET päringu meie raamatute API vastu, mis kuulab päringuid localhost peal pordil 5000:
Testige nüüd, kas raamatute alla tõmbamine ja kustutamine töötab!
- Vigade korral saate uurida Flask API rakenduste/konteinerite väljundeid ning brauseri arenduskonsoolis (F12) näidatavaid JavaScript veateateid.
- Selleks, et näha kas raamat kustutati või loodi, tuleb leheküljele refresh teha.
- Parandame kustutamisege seotud olukorra sellega, et kutsume
listiraamatud()
meetodi välja JavaScript meetodideleteObject
lõpus- Lisage sinna rida:
listiraamatud();
- Lisage sinna rida:
- Parandame raamatu loomisega seotud olukorra:
- Looge uus javaScript meetod
handleResponse
:function handleResponse(form, responseData) { }
- Lisage
handleResponse
meetodi väljakutsehandleFormSubmit(event)
funktsiooni sisse, enne rida} catch (error) {
. - Lisage sinna rida:
handleResponse(form, responseData);
- Selle tulemusena käivitatakse
handleResponse
peale iga POST päringu tegemist (HTML vormi kaudu) ning saame sellese meedodisse kirjutada mis peaks juhtuma, kui saame POST päringu tulemuse kätte.
- Selle tulemusena käivitatakse
- Implementeerime
handleResponse
meetodi sisu:- Lisame funktsiooni algusesse koodi mis otsin HTML dokumendist üles elemendi, kuhu saame kirjutada infot kasutajale, selle kohta kas POST päring õnnestus (raamatu loomine või raamatust otsimine):
- Lisage sinna:
const resultElement = document.getElementById("tulemus");
- Lisage sinna:
- Kui vormi (mis käivitati) id oli "frontform", siis loodi uus raamat. Siis kirjutame üle "tulemus" HTML ploki - paneme sinna vormi POST päringu JSON vastuse sisemise võtme "tulemus" väärtuse (API saadab sõnumi, et raamatu loomine õnnestus). Samuti uuendame raamatute nimekirja.
- Lisage:
if(form.id == "frontform"){ resultElement.innerHTML = responseData.tulemus; listiraamatud(); }
- Lisage:
- Kui vormi (mis käivitati) id oli "otsinguform", siis otsiti sõnet raamatu seest. Siis kirjutame üle "tulemus" HTML plokki - kirjutame sinna vormi POST päringu JSON vastuse sisemise võtme "tulemus väärtuse". Raamatute nimekirja ei ole vaja uuendada.
- Lisage:
if(form.id == "otsinguform"){ resultElement.innerHTML = "Raamatust " + responseData.raamatu_id + " leiti sõne '" + responseData.sone + "' " + responseData.leitud + " korda!"; }
- Lisage:
- Lisame funktsiooni algusesse koodi mis otsin HTML dokumendist üles elemendi, kuhu saame kirjutada infot kasutajale, selle kohta kas POST päring õnnestus (raamatu loomine või raamatust otsimine):
- Looge uus javaScript meetod
- Parandame kustutamisege seotud olukorra sellega, et kutsume
Ülesanne 9.4: Kasutajaliidese käivitamine konteineris.
Konteineriseerime meie poolt loodud kasutajaliidese.
- Looge samase kausta Dockerfile järgneva sisuga:
FROM nginx:alpine COPY apiparingud.js /usr/share/nginx/html/apiparingud.js COPY front-end.html /usr/share/nginx/html/index.html EXPOSE 80
- Ehitame Docker image
hs9-front-end
veebiliidese mikroteenuse jaoks:docker build -t hs9-front-end -f Dockerfile .
- Seda saab käima panna Dockeri konteinerina pordi 80 peal nii:
docker run -di -p 80:80 hs9-front-end
Testige, et õnnestub kõik kolm Docker conteinerit üles seada ning rakendust kasutada.
- hs9-front-end - port 80
- hs9-flask-api-raamatud - port 5000
- hs9-flask-api-raamatute-otsing - port 5001
Esitada: tehke ekraanivaated, mis näitavad et konteinerite jooksutamine õnnestus ning veebirakenduse kaudu õnnestub raamatuid luua, kustutada, nendest otsida ning neid alla laadida.
Bonus ülesanne: Docker compose kasutamine, et üles seada kõik kolm mikroteenust korraga Docker compose kaudu.
See ülesanne on täielikult iseseisev. Aga võite küsida vihjeid või abi vigade otsimisel.
Eesmärk: Looge docker compose fail, mis kirjeldab ära kõik kolm mikroteenust ning mis võimaldab docker compose
või docker-compose
käskude abil kõik mikroteenused korraga ja ühtse Docker teenuse komplektina üles seada.
NB! Ei ole lubatut Azure ühendus stringi docker compose faili sisse või dokeri failide sisse jätta!
Tuleb esitada:
- Docker compose fail
- Docker compose käsk mida kasutasite
Lahenduse esitamine
Praktikumi lahendusena tuleb esitada:
- Kõigi kolme mikroteenuse koodi projekti kaustad koos Dockerfailidega
- Ärge pange kaasa Python venv kaustasid!
- Ekraanivaated ülesandest 9.4