One last chapter to go

This commit is contained in:
Pünkösd Marcell 2021-12-18 18:16:15 +01:00
parent f859303a65
commit 762bffe668
3 changed files with 108 additions and 10 deletions

View File

@ -463,3 +463,13 @@
%note = "",
}
@misc{timeseries_basics,
author = {Eric Clower},
year = {2019},
title = {Introduction to the Fundamentals of Time Series Data and Analysis},
howpublished = {\url{https://www.aptech.com/blog/introduction-to-the-fundamentals-of-time-series-data-and-analysis/}},
note = {Megtekintve: 2021-12-18}
}

View File

@ -155,4 +155,5 @@
\newacronym{cpu}{CPU}{Central Processing Unit}
\newacronym{oci}{OCI}{Open Container Initiative}
\newacronym{raid}{RAID}{Redundant Array of Independent Disks}
\newacronym{ssd}{SSD}{Solid State Drive}
\newacronym{ssd}{SSD}{Solid State Drive}
\newacronym{icmp}{ICMP}{Internet Control Message Protocol}

View File

@ -103,28 +103,115 @@ Az áthelyezés így jelentősen leegyszerűsödik, hiszen csak arra van szüks
A vezérlést megvalósító szolgáltatás komponensek indításáért ebben az alkalmazásban külön szolgáltatás felel, ezért ez az a szoftverkomponens, amelynek támogatnia kell a dinamikus ütemezési döntések alkalmazását.
\section{Ütemező rendszer}
Bár a két alkalmazás működése és igényei jelentősen eltérnek, szerettem volna egy olyan rendszert megalkotni, aminek segítségével mindkét alkalmazás ütemezése megoldható.
Bár a két alkalmazás működése és igényei jelentősen eltérnek, szerettem volna egy olyan rendszert megalkotni, aminek segítségével mindkét alkalmazás ütemezése megoldható. A szoftver tervezése során figyelembe vettem azokat a közös funkcionalitásokat, amelyeket mindkét alkalmazás egyformán használ. Emellett szétválasztottam azokat a komponenseket, amelyek alkalmazás specifikus funkciót valósítanak meg.
\subsection{Metrikák gyűjtése és felhasználása}
\subsection{Metrikák gyűjtése és kiértékelése}
% bele van tolva influx db-be
% Az infulxdbj nagyon jó mert tud egy csomó midnent például deriválni
Mindkét alkalmazásban közös, hogy az ütemezési döntéseket az alakhamzásból gyűjtött metrikákra. Ezek a metrikák bár eltérő tulajdonságokat írnak le, gyűjtésük és kiértékelésük szempontjából nem különböznek egymástól.
\subsection{Algoritmus}
A gyűjtött metrikák minden esetben idősoros adatként kezelhetőek. Az idősoros adatok olyan mérések, amelyek meghatározott időközönként rögzítésre kerülnek. Egy rögzített adatpont mindig időhöz kötötten reprezentálja a megfigyelt pillanatnyi állapotot \cite{timeseries_basics}. Az alkalmazásaink állapotát idősoros adatként gyűjtve képesek vagyunk a döntési logika felépítésénél többfajta statisztikai kiértékelést is a döntések alapjául venni.
A metrikák gyűjtésére és kiértékelésére így egy központi megoldást terveztem. Gyűjtés során az egyes alkalmazás komponensek vagy mérő szoftverek elküldik a központi rendszerbe, amely idősorosan tárolja az adatokat. Ha egy ütemezési döntést végző szolgáltatásnak szüksége van arra, hogy a rögzített adatokon készített kiértékelést használja (például átlagolt értéket egy meghatározott idősávra), akkor innen le tudja kérni.
%Egy ilyen algoritmusnak fel kell tudnia mérni azokat
Ezt a szolgáltatás mindkét alkalmazás egyformán tudja használni.
\subsection{Megvalósítás}
\subsection{Ütemezési algoritmus}
\label{sec:scheduling-algo}
Bár a robotkarokat vezérlő alkalmazásnál az ütemezést megvalósító algoritmus meghatározott fix időpontokban egy egyszerű minimum keresés a madárhang felismerő rendszer esetén ennél összetettebb megoldásra van szükség.
Ebben az esetben nem csak a konténerek ütemezésére van szükség az egyes adatközpontok között, hanem arra is, hogy az \acrshort{iot} eszközök konfigurációját is frissítsük. Emellett az ütemezési események generálása sem előre meghatározott. Az algoritmusnak folyamatosan figyelnie kell a rendszer állapotát és szükség esetén be kell tudnia avatkozni.
Egy ilyen viselkedést megvalósító naiv algoritmust terveztem, amely a próbálgatás módszerével keres egy megfelelő eloszlást a szolgáltatásoknak a peremhálózati adatközpontok és a felhő között és az ezekhez kapcsolódó \acrshort{iot} eszközök között.
Ahhoz, hogy a folyamatos felügyelet megvalósuljon, egy periodikusan futó algoritmust terveztem, amely rögzített időközönként felméri a rendszer állapotát és szükség esetén képes szolgáltatásokat mozgatni és konfigurációt frissíteni az eszközökön.
Az algoritmus periodikus futása során fel kell tudnia mérni, ha kedvezőtlen rendszer állapot áll fenn és döntést kell hoznia annak megoldása érdekében. A madárhang elemző rendszer esetében ilyen kedvezőtlen állapot ha a komponensek belső sorhossza monoton növekedésnek indul. Ilyen helyzetben a rendszer működése instabil. Stabilnak azt az állapotot tekinthetjük ha a sorhossz csökken, vagy konstans értékhez közelít.
A sorhossz növekedésének detektálásához kihasználtam az idősoros adatokon végezhető kiértékelési lehetőségeket. Az algoritmus periodikus futása során az elmúlt időszak (konfigurálható időre visszamenően) deriváltját kérdezi le. Ebből adódóan, ha a derivált értéke nagyobb mint 0 akkor feltételezhető az instabil állapot, 0 és annál kisebb értékek esetén a rendszer stabilnak mondható.
Ha az algoritmus többszöri futás esetén is nullánál nagyobb értéket kap a sorhossz deriváltjára, akkor megkezdi a javító folyamatot. Ez a folyamat egy eszköz által küldött adatokat irányítja át másik felhőbe. Mielőtt frissíti az eszköz konfigurációját ellenőrzi hogy az új cél-adatközpontban fut-e a szolgáltatás egy példánya. Ha nem akkor előbb elindítja azt és miután az készen áll az adatok fogadására csak akkor ütemezi át a a küldést.
Ez a viselkedés hasonlít a korában ismertetett átterheléses mozgatásra. Azaz ha mozgatni kell, akkor csak azután teszi meg, hogy az \enquote{új} szolgáltatás készen áll, ez idő alatt a \enquote{régi} szolgáltatás dolgozza fel a kéréseket, így kiesés nélkül vihető véghez a szolgáltatások mozgatása.
Annak eldöntése, hogy melyik adatközpontba kezdje el átütemezni a terhelést az algoritmus jelenlegi megoldásomban egy fix rangsort használ. Ahol egy előre rögzített listán minden egyes lehetőséget megvizsgál stabilitás szerint és ez alapján választja ki az ideális jelöltet.
Ilyen szintű naiv megoldás szuboptimális eredményt hozhat. Hiszen könnyen belátható, hogy hajlamos a vibrációra, azaz amikor egy terhelést folyamatosan oda-vissza ütemez két adatközpont között. Ez akkor fordulhat elő ha egy adatközpont működése stabil, de egy egységnyi terhelés (esetünkben egy \acrshort{iot} eszköz által küldött hangminták) már instabillá teszik.
Ennek a jelenségnek az elkerülésére az algoritmus megjelöli, ha egy adatközpontban instabil működés miatt el kellett mozgatnia onnan terhelést. Ez a jelölés egy idő után lejár, ideális esetben azután, hogy a rendszer ismét elérte a stabil állapotot. Mivel a stabil állapot nem vezet átütemezéshez, ezért itt már nincs jelentősége a jelölésnek.
Átütemezés után az újonnan indított szolgáltatás is automatikusan elkezdi küldeni a belső állapot információit, az ütemező algoritmus pedig automatikusan elkezdi figyelemmel kísérni a változásokat. Ezek után kezdődik elölről az algoritmus futása.
\subsection{Kommunikációs interfész}
Úgy terveztem, hogy az ütemező rendszerrel kívülről \acrshort{http} \acrshort{api} segítségével lehessen kommunikálni. A rendszer megvalósít interfészeket a metrikák beküldésére és kiértékelésére. Emellett az \acrshort{iot} eszközök esetében egy táblázatot tart fenn arról, hogy melyik eszközt melyik adatközponthoz rendeli.
Azt, hogy ennek a táblázatnak a tartalmát hogyan szinkronizáljam az eszközök beállításaival, két megoldást vizsgáltam meg. Ez a két megoldás a \textit{push} (amikor az algoritmus direktben értesíti az eszközöket) és a \textit{pull} (amikor az eszközök periodikusan kérdeznek le információt).
Míg a \textit{push} alapú megoldás megoldás esetén a rendszer azonnal képes lehet értesíteni az eszközöket, sokkal komplexebb megoldást igényel, hiszen kezelni kell azokat a hiba lehetőségeket, amelyek felmerülhetnek a kommunikáció során és biztosítani, hogy ezeknek ellenáll az információ továbbítás.
Ezzel szemben \textit{pull} alapú megoldás esetén az eszközök ezt az információt működésük során periodikusan lekérhetik, és ennek megfelelően állíthatják át küldésük célját. Ebben az esetben a két lekérdezés között eltelt idő miatt nagyobb késleltetéssel értesülnek a változásról az eszközök, hiszen a táblában változott bejegyzésről csak a következő lekérésben tudnak értesülni. Emellett a folyamatos periodikus lekérdezés felesleges terhelést is jelent az ütemező rendszer számára, hiszen akkor is teljesítenie kell a kéréseket, ha nem változott semmi a konfigurációban. Cserében ebben az esetben nem okoz nagy problémát ha egy frissítés nem jut el az eszközhöz, vagy a frissítés pillanatában éppen nem elérhető az eszköz. A folyamatos lekérdezés miatt idővel konvergálni fog a helyes konfigurációhoz.
A konfiguráció leküldéséhez a periodikus lekérdezést választottam. Ennek oka az, hogy implementációja jelentősen könnyebb, mint az értesítési mechanizmus esetén. Emellett a konfiguráció változtatás nem időérzékeny: az átterheléses mozgatás miatt bizonyos mértékű késleltetés nem okoz problémát.
\subsection{Rendszer implementáció}
Az ütemező rendszerem megvalósítását \textit{Kubernetes} környezetben futtatható mikroszolgáltatás architektúrára terveztem. A rendszer vázlatos felépítése \aref{fig:turbomemer}.\ ábrán látható. Az egyes szolgáltatások és egyéb szoftver komponensek implementációját a következő szekciókban részletezem.
\begin{figure}[h!]
\centering
\includegraphics[width=0.5\textwidth]{figures/turbomemer-legit}
\caption{asd}
\caption{Ütemező rendszer szolgáltatásainak áttekintése}
\label{fig:turbomemer}
\end{figure}
\subsubsection{Mérés kezelő}
\label{sec:birb-latency-collector}
Ez a szolgáltatás egy kívülről is elérhető interfészt valósít meg. Feladata a rendszer állapotát leíró mért adatok gyűjtése és azokról kiértékelések szolgáltatása. Ennek megvalósítására egy idősoros adatbázist használ. Az általam választott idősoros adatbázis az \textit{InfluxDB}.
Azért választottam az \textit{InfluxDB}-t, mert egy hatékonyan működő adatbázis sok hasznos funkcióval. Ilyen például a 2-es verzió óta beépített adatvizualizáció, így közvetlenül lehet a szoftvert arra használni, hogy a rögzített méréseket megtekintsük. Saját lekérdező nyelvén pedig sokféle adat aggregáció, transzformáció és kiértékelő funkcionalitás érhető el.
Új mérések érkezésekor a szolgáltatás eltárolja az információkat az adatbázisban. Ha szükség van kiértékelésre, akkor az \textit{InfluxDB} saját lekérdezőnyelvére fordítja a kérést és az adatbázis szoftverben futtatja azt le, így hatékonyan és egyszerűen tudja megkapni a kiértékelt adatokat, amelyeket válaszul ad a kérésre.
Ezt a szolgáltatást a robotkarok vezérlését megvalósító alkalmazás közvetlenül tudja használni az ütemezési döntés meghozatalára.
\subsubsection{Ütemezés nyilvántartó}
\label{sec:birb-scheduler-teller}
Ezt a szolgáltatás kizárólag az intelligens madárhang elemző alkalmazás használja.
Ennek a szolgáltatásnak a feladata, hogy számontartsa az egyes eszközök jelenlétét illetve kiszolgálja számukra, hogy pillanatnyilag melyik adatközponthoz vannak rendelve. Az eszközök futásuk során ettől a szolgáltatástól tudják lekérni az ütemezési információikat.
Ha a szolgáltatásból egy eddig ismeretlen eszköz kéri le az ütemezését, akkor azt egy dinamikusan megválasztott \enquote{alapértelmezett} adatközponthoz rendeli. Ezután ezt az ütemezési döntést elmenti és innentől kezdve ugyanúgy van kezelve az új eszköz is, mint az összes többi.
A kiszolgált adatokat egy kulcs-érték adatbázisban tárolja. Ehhez \textit{Redis} adatbázist használtam, ennek oka az, hogy a \textit{Redis} támogatja az értékekhez lejárati idő rendelését. A lejárai idő leteltével az értékeket automatikusan törli. Ennek a segítségével számos funkcionalitást könnyebb volt implementálni. A \textit{Redis} támogatja továbbá az osztott memóriaként való funkcionalitást, amelyet kihasználva \aref{sec:birb-scheduler}.\ szekcióban ismertetett szolgáltatással való kommunikációt megoldottam.
\subsubsection{Dinamikus újra-ütemező}
\label{sec:birb-scheduler}
\Aref{sec:birb-scheduler-teller}.\ szekcióban ismertetett szolgáltatás csak egy statikus hozzárendelést valósít meg az új eszközök és az adatközpontok között. Viszont ezek után nem változtatja meg a döntését. Ezeknek a döntéseknek a felülvizsgálatára és az \enquote{alapértelmezett} adatközpont dinamikus megváltoztatására szolgál ez a szolgáltatás.
Ez a szolgáltatás valósítja meg \aref{sec:scheduling-algo}.\ szekcióban vázolt periodikusan futó ütemező algoritmust.
Futása során a kiértékelt metrikákat lekérdezi a \textit{Mérés kezelő} szolgáltatásból. Majd ezek alapján és az osztott \textit{Redis} adatbázisban tárolt információk alapján meghozza az ütemezési döntést. Szükség esetén \textit{Kubernetes} \acrshort{api} hívásokkal elindítja a \textit{KubeFed} által kezelt szolgáltatást a megfelelő adatközpontban majd ezek után az ütemezési döntést rögzíti a az adatbázisban. így legközelebb amikor az eszköz frissíti a konfigurációját már az újonnan indított szolgáltatáshoz küldi az információkat, ezzel megvalósítva a dinamikus átütemezést.
A szolgáltatás azt is ellenőrzi, hogy a kijelölt \enquote{alapértelmezett} adatközpont stabilnak számít-e. Ha nem, akkor ezt a beállítást is frissíti, így az új eszközök már másik adatközpontba kezdik el küldeni az adatokat.
Értelem szerűen ezt a szolgáltatást is csak az intelligens madárhang elemző alkalmazás használja.
\subsection{Link késleltetés mérése}
A robotkarokat vezérlő alkalmazás számára szükség van arra az információra, hogy az egyes adatközpontokkal milyen minőségű a link összeköttetése.
Ennek a megvalósítására egy egyszerű szkriptet készítettem, amely leméri az összes adatközponttal szembeni késleltetést, majd ezeket elküldi \aref{sec:birb-latency-collector}.\ szekcióban ismertetett szolgáltatás számára, amely így képes arról kiértékelést készíteni.
A késleltetés mérésére kézenfekvő megoldás lehet a hagyományos \acrfull{icmp} által biztosított \textit{Ping} kérésekkel mérni a körülfordulási időt. De ez csak egy nagyon limitált eredményt ad egy konkrét végponthoz.
Szerettem volna egy olyan megoldást készíteni, amely nem csak az adatközpont határán lévő, publikus címmel rendelkező végponthoz tudja mérni a késleltetést, hanem közvetlenül az ott futó szolgáltatások és a végpont közti kapcsolatot tudja mérni. Ennek hála a késleltetés nem csak a publikus hálózat állapotát, de az egyes adatközpontok belső hálózatáról is képet tud adni. Ezzel átfogóbb és pontosabb információt kapunk arról, hogy melyik adatközpontot érdemes használnunk.
Ezt úgy oldottam meg, hogy felkonfiguráltam egy egyszerű webszerver konténert, amely minden kérésre egyből egy üres válasszal válaszol. Ezt a konténert \textit{KubeFed} segítségével úgy futtattam, mint bármelyik másik szolgáltatást minden adatközpontban. Ezt a szolgáltatást kiajánlottam minden adatközpont publikus címére. A szkriptem pedig a \acrshort{http} kérés körülfordulási idejét méri.
Az így mért értékeket az ütemező fel tudja használni arra, hogy eldöntse, hogy melyik adatközpontra ütemezze be a robotkarok vezérléséhez szükséges szolgáltatást.