Sistem De Monitorizare Si Gestiune A Unei Flote Auto Cosmin Seceleanu.docx [610542]
Universitatea Politehnica București
Facultatea de Automatica și Calculatoare
Departamentul Automatică și Informatică Industrială
LUCRARE DE DIS ERTAȚIE
Sistem de monitorizare și gestiune în timp real a
unei flote auto
Masterand: [anonimizat] 2017
1
Cuprins
Introducere ………………………….. ………………………….. ………………………….. ………………………….. ……………… 3
Descrierea sistemelor similare de monitor izare auto ………………………….. ………………………….. …………… 5
Instrumente și tehnologii utilizate în dezvoltare ………………………….. ………………………….. …………………. 7
Brokerul de mesaje RabbitMQ ………………………….. ………………………….. ………………………….. ………….. 7
Mesaje sincron ………………………….. ………………………….. ………………………….. ………………………….. ….. 7
Mesaje asincron ………………………….. ………………………….. ………………………….. ………………………….. … 8
Topologii de mesaje ………………………….. ………………………….. ………………………….. ……………………….. 8
Modele de mesagerie ………………………….. ………………………….. ………………………….. ……………………. 10
Modelul Publish -Subscribe ………………………….. ………………………….. ………………………….. ………….. 11
Brokeri de mesaje ………………………….. ………………………….. ………………………….. ……………………….. 14
RabbitMQ ………………………….. ………………………….. ………………………….. ………………………….. ………. 15
Protocolul AMQP ………………………….. ………………………….. ………………………….. ………………………….. .. 17
Protocolul WebSocket ………………………….. ………………………….. ………………………….. …………………….. 26
WebSocket vs HTTP ………………………….. ………………………….. ………………………….. ……………………. 28
Baza de date NoSQL Cassandra ………………………….. ………………………….. ………………………….. ………. 30
NoSQL ………………………….. ………………………….. ………………………….. ………………………….. ……………. 31
Tipuri de baze de date NoSQL ………………………….. ………………………….. ………………………….. ……… 32
ACID ………………………….. ………………………….. ………………………….. ………………………….. ……………… 34
Teorema CAP ………………………….. ………………………….. ………………………….. ………………………….. …. 35
Arhitectura de nivel înalt a Cassandrei ………………………….. ………………………….. …………………….. 36
Modelarea Datelor ………………………….. ………………………….. ………………………….. ………………………. 43
Considerente legate de dezvoltarea sistemului ………………………….. ………………………….. ………………….. 49
Cerințele sistemului ………………………….. ………………………….. ………………………….. ………………………… 49
Componentele sistemului ………………………….. ………………………….. ………………………….. ……………… 49
Tipuri de utili zatori ………………………….. ………………………….. ………………………….. ……………………… 50
Lista de cerințe ………………………….. ………………………….. ………………………….. ………………………….. .. 51
Arhitectura Sistemului ………………………….. ………………………….. ………………………….. ……………………. 52
Prezenta rea implementării funcționalităților sistemului ………………………….. ………………………….. …… 54
Transmiterea mesajelor ………………………….. ………………………….. ………………………….. …………………… 54
Serviciul Web ………………………….. ………………………….. ………………………….. ………………………….. …….. 57
Structura bazei de date MySQL ………………………….. ………………………….. ………………………….. …… 58
Api-ul REST ………………………….. ………………………….. ………………………….. ………………………….. …… 59
2
Salvarea coordonatelor în Cassandra ………………………….. ………………………….. ………………………….. . 65
Aplicația Web ………………………….. ………………………….. ………………………….. ………………………….. …….. 68
Autentificare ………………………….. ………………………….. ………………………….. ………………………….. …… 68
Monitorizare ………………………….. ………………………….. ………………………….. ………………………….. …… 69
Primirea și af ișarea alertelor ………………………….. ………………………….. ………………………….. ……….. 71
Gestiunea resurselor flotei ………………………….. ………………………….. ………………………….. ……………. 72
Aplicația Android ………………………….. ………………………….. ………………………….. ………………………….. .. 74
Concluzii ………………………….. ………………………….. ………………………….. ………………………….. ……………….. 78
Anexe ………………………….. ………………………….. ………………………….. ………………………….. …………………….. 80
Anexa 1 ………………………….. ………………………….. ………………………….. ………………………….. ………………. 80
Anexa 2 ………………………….. ………………………….. ………………………….. ………………………….. ………………. 82
Anexa 3 ………………………….. ………………………….. ………………………….. ………………………….. ………………. 85
Anexa 4 ………………………….. ………………………….. ………………………….. ………………………….. ………………. 86
Bibliografie ………………………….. ………………………….. ………………………….. ………………………….. ……………. 92
3
Introducere
Monitorizare a este un termen asociat de multe ori cu ideea de securitate, de protejare a
bunurilor. Primele sisteme de monitorizare al e flotelor auto au apărut la mijlocul anilor 1990 pentru
a proteja vehiculele împotriva furturilor. Ulterior, domeniul sistemelor de protecție a vehiculelor
și mărfurilor a luat amploare exploziv, în paralel cu evoluția tehnologiilor din domeniul GPS,
hardware și software.
Spre finalul anilor 1990 a început să fie foarte clar separarea domeniilor de securitate a uto
și cel de monitorizare , ale cărei cerințe pot fi rezolvate chiar cu tehnologia și sistemele gândite
inițial pentru protecție. Primele sisteme dezvoltate erau destul de greu de instalat, menținu t iar
costurile erau foarte mari drept urmare numărul de cl ienți era foarte redus. E voluția expone nțială
a tehnologiei a făcut ca în numai câțiva ani sistemele de monitorizare auto să devină mult mai
accesibile.
În acest moment există mai multe companii care comercializează soluții de monitorizare
acceptabile din punct de vedere financiar și oferă informații de bază precum poziționarea
vechiului, distanța parcursă dar și informații mai evoluate, cum ar fi consumul de combustibil sau
viteza medie. Mai nou aceste informații sunt accesibile de oriunde atâta timp cât există o conexiune
la internet.
Din punct de vedere tehnic localizarea GPS este relativ ușor de realizat , iar din perspectiva
financiară oferă un randament foarte bun. In general sistemele de monitorizarea a unei flote auto
sunt realizat e prin combinare a tehnologiilor GPS, GPRS /GSM , electronică ș i IT.
Sistemele de monitorizare ș i gestiune a unei flote auto au următoarele avantaje:
• Costuri mai mici la consumul de combustibil
• Creșterea profitului
• Creșterea eficienței în utilizarea vehicule lor din flota auto
• Simplificare procesului de distribuție a sarcinilor de lucru
• Managementul flotei într -o singură platformă
4
Scopul studiului realizat este dezvoltarea unui sistem de monitorizarea în timp real și
gestiune a unei flote aut o. Sistemul își propune înregistrarea coordonatelor GPS a unui vehicul
asociat unui angajat și transmiterea acestor coordonate către un broker de mesaje. Broker -ul de
mesaje va distribui datele în timp real serviciului web unde vor fi afișate dacă un manag er de flota
este conectat la aplicația web și în paralel distribuite către o aplicație Java pentru fi salvate pentru
a putea fi vizualizate ulterior.
Înregistrarea datelor se face utilizând o aplicație pentru dispozitive mobile cu sistemul de
operare Andr oid. Aplicația utiliz ează GPS –ul dispozitivul mobil ș i transmite datele folosind
accesul acestuia la internet.
În cadrul primului capitol al acestei lucrări sa realizat un studiu asupra sistemele de
monitorizare auto similare din domeniu în care se prez intă principalele funcționalități ale acestora
pe baza cărora au fost dezvoltate și cerințele funcționale ale sistemului dezvoltat. În continuare
sunt prezentate principalele tehnologii și protocoale de comunicație folosite în realizarea
sistemului.
În cel de -al treilea capitol este prezentată lista de cerințe a sistemului, tipurile de utilizatorii
din sistem și arhitectura sistemului. Apoi în următorul capitol sunt prezentate în detaliu
funcționalitățile sistemului și cum au fost implementate. În cadrul acestui capitol vor fi detaliate:
Transmiterea mesajelor între componentele sistemului
Prezentarea serviciului web și detaliile despre baza de date
Salvarea mesajelor transmise în bazele de date
Prezentarea interfeței grafice a aplicației web
Prezentarea i nterfeței grafice a aplicației Android și înregistrarea apoi transmiterea
coordonatelor .
5
Descrierea sistemelor similare de monitorizare auto
Un sistem de monitorizare al unei flote auto este superGPS ce oferă soluții complete de
monitorizare în tim p real și gestionare a flotei. Așa cum este prezentat în [33] sistemul superGPS
folosește aparate GPS specializate pentru înregistrarea coordonatelor, aceste aparate sunt montate
pe vehicule și pot oferi conectivitate cu senzori de temperatură, umiditate, proximitate etc. Datele
înregistrate de către aparate sunt transmise către un server utilizând o cartelă GSM pentru a se
conecta la internet.
Sistemul pot fi folosit cu mai multe tipuri de aparate, unul dintre ele este FM -500 Light.
Acest aparat este un u rmăritor GPS cu conectivitate GSM special conceput pentru monitorizarea
de bază: poziția vehiculului, viteză, direcția de mers, etc. Intrările digitale și analogice pot fi
folosite pentru a conecta diverși senzori (temperatură, umiditate). Ieșirile se folo sesc pentru a
controla diverse echipamente de la distanță.
Specificații tehnice FM -500 Light:
Antenă GPS externă cu sensitivitate 162 dBm
Antenă GSM internă
4 intrări digitale
2 intrări analogice
3 ieșiri digitale
4 MB memorie internă
Alimentare 8-36V
Temperatură de funcționare între -40 și 85 C
Datele înregistrate pot fi folosite din cadrul unei interfețe grafice unde administratorii pot
vedea pe hartă traseul parcurs și grafice le cu valorile înregistrate de senzori.
Un alt sistem de monitorizare al une i flote auto disponibil pe piață este SmartFleet care
oferă de asemenea soluț ii și pentru gestionarea flotei. SmartFleet are următoarele caracteristici:
Nu necesită costuri cu infrastructura hardware , datele fiind salvate într -o aplicație
Web deja existent ă
Acces din browser la aplicație
Instalare rapidă
6
Sistemul utilizează tehnologii precum Java și Oracle pentru stocarea și gestionarea
datelor .
Din punct de vedere al funcționalităților sistemul SmartFleet oferă posibilități
managementul conducătorilor auto , managementul vehiculelor și managementul operațiunilor.
Aceste funcționalități conform [29] sunt:
1. Funcționalități management conducători auto
1.1. Managementul complet al personalului flotei
1.2. Pentru fiecare conducător se pot atașa 5 documente(permis auto, adev erință medicală, etc)
1.3. Monitorizarea numărului de kilometri efectuați zilnic
1.4. Monitorizarea consumului de combustibil
1.5. Urmărirea grafică a curselor
2. Funcționalități management vehicule
2.1. Managementul complet al vehiculelor
2.2. Documente atașate precum: RCA, ITP, Ca rte Vehicul
2.3. Alertele definite ca blocante (exemplu: Expirare RCA) – nu mai permit ca vehiculul sa fie
alocat la noi curse
3. Funcționalități management operațiuni
3.1. Gestionarea comenzilor de lucru
3.2. Gestionarea categoriilor de comenzi și costuri unitare ale acest ora
3.3. Gestionarea vehiculelor disponibile
3.4. Sistemul permite definirea și urmărirea unor puncte de interes
3.5. Monitorizare flotă în timp real
SmartFleet poate oferi și opțiuni suplimentare pentru monitorizare utilizând:
Montarea unor senzori în anumite puncte de interes
Utilizarea unor RFID -uri pentru conducătorii auto
Senzori suplimentari montați pe vehicule și instalații: nivel combustibil, senzor prezență
pe scaun
Senzori de greutate
Senzori de temperatură .
7
Instrumente și tehnologii utilizate în dezvolta re
Brokerul de mesaje RabbitMQ
În arhitecturile software, un model de mesaje este un model arhitectural orientat pe rețea
care descrie modul în care cele două părți diferite ale unui sistem ce schimbă mesaje se conectează
și comunică unul cu celălalt. În informatică, un sistem ce schimbă mesaje trimite un mesaj către
un proces și se bazează pe proces și pe infrastructura de sprijin pentru a selecta și invoca codul
actual pentru a rula.
În telecomunicații, un model de schimb de mesaje descrie modelul de m esaje necesare unui
protocol de comunicații pentru a stabili sau de a folosi un canal de comunicare. Există două modele
majore pentru schimbul de mesaje:
Un model cerere – răspuns, de exemplu protocolul HTTP
Un model cu un singur sens, de exemplu protocolu l UDP
Mesaje sincron
Mesajele sincrone sunt tranzacții care blochează procesul ulterioare până când termină
tranzacția. Pentru dezvoltatorii de software conceptul de sincronicitate este bine cunoscut d in
paradigme orientate obiect care sunt executate în ordine, exceptând cazul în care se specifică altfel.
Din punct de vedere istoric World Wide Web a fost în mare parte sin cron, până la recenta
schimbare de la site-uri la aplicații web în care proces area si afișare a datelor transportate sincron
utilizând HTTP sa trecut într -un mod asincron .
Figura 1 – Cronologie cu mesaje sincrone
Sursa: https://www.ibm.com/developerworks/cn/webservices/ws –
designpattern/index.html
8
Mesaje asincron
În contrast față de m esajele sincrone, cele asincrone nu necesită răspuns imediat din partea
celui care a recepționat mesajul. Utilizarea mesajelor asincrone poate oferi scalabilitate prin
întârzie rea transferului de date, capabilități de post -procesare, prin furnizarea de conducte de
filtrare și rezistență la problemele de conectivitatea prin salvarea mesajelor până ce un consumator
este capabil de a primi mesajul. Ca și dezavantaj al mesajelor asi ncrone este reprezentată de
implementarea complexă pentru validarea stărilor tranzacțiilor.
Topologii de mesaje
În domeniul mesajelor informatice, o topologie descrie modul de implementarea a
conexiunilor între noduri. Înțelegerea acestor diferențe ope raționale pot ajuta în alegerea unei
soluții de mesagerie în funcție de diferite subiecte și scenarii conform [ 11].
Client – Server este o topologie frecvent utilizată în rutarea datelor de la un singur server
la abonați conform cu „Figura 3 Topologia Cli ent – Server ”, de asemenea, cunoscut sub numele
de modelul de stocare și înainte „store -and-forward” . Aceasta topologie este piatra de temelie
pentru modelul „publish-subscribe” conform [12] , atunci când scalabilitatea este o cerință.
Figura 2 – Cronologie cu Mesaje Asincrone
Sursa: http://wiki.ihe.n et/index.php/Asynchronous_Messaging
9
Topologiile de tip magistrală de servicii sunt utilizate, de exemplu în aplicații asincrone în
care mesajele sunt lăsate pe o magistrală/culoar astfel încât consumatorii de aceste mesaje pot
primi și răspunde la ele la un moment ulterior conform cu „Figura 4 ”.
Figura 4 – Editori și abonați conectați la magistrală
Sursa: http://www.patrick -gotthard.de/ereignisorientierte –
programmierung -mit-spring -und-guavas -eventbus Figura 3 – Topologia Client – Server
Sursa: http://www.howtonetwork.org/wp -content/uploads/2014/03/17.10.jpg
10
Arhitectura magistrala de serviciu oferă o mare flexibilitate și d ecuplare a capacității sub
forma de mesaje stocate și întârziate așa cum este cerut de exemplu, în cazul sistemelor de email.
O topologie de tip conductă este folosită în sistemele în care un mesaj po ate trece prin mai
multe servere intermediare de mesaje și toate execută acțiune asupra mesajului fie îl consumă,
redistrib uie sau filtrare conform cu „Figura 5 Topologia de tip conductă ”. Acest tip de sistem este
menționat uneori ca sistem plat.
Conductel e sunt o modalitate eficientă de a distribui o sarcină în mici sub sarcini de
procesare independente și bine organizate.
Modele de mesagerie
Modele sunt regulile, modele comportamentale ale brokerilor de mesaje. Ele descriu
modul în care funcționează b rokerul de mesaj:
cine poate primi mesaje
cine și ce primește
formatul în care se primește mesajul și când se primește mesajul
ce se întâmplă înainte, după și în timpul când un mesaj este transportat
Figu ra 5 – Topologia de tip conductă
Sursa: https://msdn.microsoft.com/en -us/library/aa480027.aspx
11
Modele de tip mesaj și canal descriu diferite variante de mesaje și atribute ale sistemelor de
livrare mesaje. Serviciu de rutare și modelul de consumatori descriu mecanisme de abordare și
comportamente pentru servere și clienți. Modele de contract definesc specificațiile pentru
interacț iunea între servere și clienți și modele de construcție și transformare , descriu formatul
mesajelor la intrare și la ieșirea din sistem.
Cele mai cunoscute modele de mesagerie sunt:
Publish –Subscribe: în acest model cei care publică mesajele pot fi comparați cu furnizori
de se rvicii ce trimit mesajele tuturor consumatorilor interesați care sunt conectați la
magistrală sau canal. Modelul publish -subscribe se bazează pe modelul observator și poate
fi util pentru testare, gestionarea și rezolvarea erorilor.
Cerere -răspuns: este un ul din modele de bază ale schimbului de mesaje între sistemele
informaționale. Un client trimite o cerere, și serverul trimite înapoi un răspuns bazat pe
cerea primită conform cu [ 1]. Acest lucru este în mare măsură modul în care serviciile web
funcționează prin protocol ul HTTP.
Fără abonați: din punct de vedere tehnic, este posibil să se utilizeze cozile ca destinație
finală fără tradiționalii consumatorii care le sunt atașate, de exemplu, în scopul
monitorizării și statisticile de colectare.
Modelul Publish -Subscribe
În arhitectura software, publish -subscribe este un model de mesagerie unde expeditorii de
mesaje, numiți editori nu programează mesajele să fie trimise direct către la receptori specifici,
numiți abonați, dar în schimb clasifică mesajele în anumite clase fără a cunoaște abonații. În mod
similar, abonații pot exprima interesul în una sau mai multe clase de mesaje și primesc doar
mesajele care sunt de interes, fără a cunoaște editorii.
Arhitectura publish -subscribe este un frate al paradigmei coadă de mesaj e, și în mod uzual
fac parte dintr -un sistem orientate spre mesaje. Cele mai multe sisteme de mesagerie oferă suport
atât pentru modelele publish -subscribe cât și pentru modelul coadă de mesaje.
12
Coadă de mesaje
Modelul cozii de mesaje oferă un protoc ol de comunicare asincron, ceea ce înseamnă că
expeditorul și destinatarul mesajului nu au nevoie pentru a interacționa cu coada d e mesaje în
același timp.
Mesaje le plasate în coada de mesaje sunt stoca te până destinatarul le preia. C ozile de
mesaje au limite implicite sau explicite cu privire la dimensiunea de date care pot fi transmise într –
un singur mesaj, iar numărul de mesaje care pot rămâne restante în coadă .
Figura 6 – Sistem de mesagerie cu modelul Publish -Subscribe
Sursa:
http://www.novell.com/documentation/extend52/D ocs/help/MP/jms/concepts/images/pubsub.gif
Figura 7 – Coadă de mesaje
Sursa: http://www.feltex.com.br/felix/exemplo -completo -jsf-primefaces –
ejb-hibernate -mysql -jms/
13
Filtrarea mesajelor
În modelul publish -subscribe, abonații primesc de obicei doar un s ubset din totalul
mesajelor publicate. Procesul de selectare a mesajelor pentru recepție și procesare se numește
filtrare. Există două forme comune de filtrare:
1. Bazate pe conținut
2. Bazate pe subiect
Într-un sistem bazat pe subiect mesajele sunt publicate p entru anumite subiecte, cunoscute
ca și canale logice. Abonații într -un sistem bazat pe subiect va primi toate mesajele publicate șa
subiectele la care se abonează și toți abonații la un subiect vor primi aceleași mesaje. Cel care
publică mesajele este res ponsabil cu definirea claselor de mesaje la care abonații se pot abona.
Într-un sistem bazat pe conținut, mesajele sunt livrate către un abonat în cazul în care
atributele sau conținutul mesajelor se potrivesc constrângerilor definite de către abonat. Abo natul
este responsabil pentru clasificarea mesajelor.
Unele sisteme hibride pot suporta ambele metode de filtrare a mesajelor astfel editorii pot
publica mesaje la un subiect în timp ce abonații înregistrați pe abonamente bazate pe conținut pe
unul sau ma i multe subiecte(canale).
Topologii
În multe sisteme publish -subscribe editorii publică mesaje către un sistem intermediar
precum un broker de mesaje sau o magistrală de evenimente , iar abonații sunt înregistrați la
brokerul de mesaje, lăsând brokerul s ă se ocupe cu filtrarea mesajelor. Brokerul în mod normal are
sarcina doar de a stoca mesajele și de a ruta mesajele de la editori la abonați. În plus brokerul poate
acorda prioritate mesajelor într -o coadă înainte de rutare.
Sistemul Data Distribution Se rvice (DDS) nu folosește un broker ca și intermediar. În
schimb fiecare editor și abonat din sistemul publish -subscribe distribuie metadate despre ele prin
intermediul IP multicast. Editorii și abonații salvează aceste informații local și rutele mesajelor
bazate pe descoperirea reciprocă în schimbul reciproc de date.
14
Brokeri de mesaje
Un broker de mesaje este un program intermediar, care traduce un mesaj de la protocolul
de transmitere a mesajului asociat expeditorului la protocolul de mesaje al receptor ului. B rokerii
de mesaj sunt elemente în rețelele de telecomunicații în cazul în care aplicațiile software comunica
prin schimbul de mesaje în mod formal -definite.
Un broker de mesaj este un model arhitectural pentru validarea mesajului, transformarea și
rutare a acestuia . Mediază comunicarea între aplicații, și comunicarea între acestea se poate realiza
fără ca aplicațiile să știe una de cealaltă, fiind total decuplate. Scopul unui broker este de a prelua
mesajele primite de la aplicații și de a efectua o acțiune asupra lor. Următoarele sunt exemple de
acțiuni care ar putea fi luate de către broker , conform [13]:
Rutarea mesajelor către una sau mai multe destinații
Transformarea mesajelor într -o reprezentare alternativă
Efectuează agregarea de mesaje, descompunerea unu i mesaj în mai multe mesaje și
transmiterea lor la destinații, apoi recompunerea răspunsurilor într -un mesaj pentru a reveni
la un utilizator
Răspunsul la erori sau evenimente
Salvarea mesajelor într -o coadă
Oferă conținut și mesaje în funcție de subiect ș i rutarea folosind modelul publish -subscribe
Cele mai cunoscute aplicații software ca brokeri de mesaje sunt:
RabbitMQ
Apache ActiveMQ
Apache Kafka
IBM Integration Bus
Microsoft Azure Service Bus
15
RabbitMQ
RabbitMQ este un broker de mesaje o pen-source care pune în aplicare protocolul AMQP(
Advanced Message Queuing Protocol). AMQP este mai deg rabă un protocol binar decât o
specificație pentru interfață. Standardul permite trimiterea de mesaje ca și serviciu ”cloud”, un
model avansat de publish -subscribe, rutarea bazată pe antet personalizat și limbaj de programare
independent. Serverul RabbitMQ conform [ 14] este scris în limbajul de programare Erlang și este
construit pe platforma Open Telecom Platform pentru ”clustering și failover”
Modelul RabbitMQ este compus din diverse componente. Acestea sunt conform [ 17]:
„producător (expeditor), receptor, schimb ( exchange ), legături și cozi de mesaje ”. Aceste
componente lucrează împreună așa cum se explică mai jos conform [ 13]:
1. Expeditorul trimite un mesaj către un schimb
2. Schimbul transmite m esajul către cozi în funcție de legăturile mesaje
3. Receptorii primesc mesajele de la cozile lor de mesaje
Figura 8 – Modelul RabbitMQ
Sursa: https://www.cloudamqp.com/blog/2015 -09-03-part4 -rabbitmq -for-beginners –
exchan ges-routing -keys-bindings.html
16
Schimburile sunt cea mai importantă componentă ale brokerului RabbitMQ. Producătorul
trimite mesaje către schimburi pentru a le transmite către con sumatorii potriviți. Schimburile
realizează decizia de expediere în funcție de tipul de schimb, cheia de rutare din mesaj, câmpuri
specifice din antetul mesajului, și de cheia de rutare asociată de coadă cu schimbul.
Schimburile pot fi configurate ca fiin d durabile, astfel încât acestea vor supraviețui reporniri
serverului RabbitMQ. Schimburile pot fi interne, astfel încât să poată fi publicate de către alte
schimburi din interiorul serverului. Schimburile mai pot fi configurate pentru ștergerea automată
dacă nu mai există cozi unde să fie stocat.
Cozile sunt folosite pentru a transmite mesajele către consumatori specifici și să asigure
livrarea ordonată a mesajelor. Un consumator este conectat la o coadă, cu o funcție de apel invers,
astfel încât consumat orul va fi informat la primirea unui mesaj. Cozile pot fi durabile, astfel încât
acestea vor supraviețui reporniri serverului RabbitMQ . O coadă poate fi configurată exclusiv la o
conexiune, odată ce conexiunea este închisă mesajele din coadă vor fi șterse . Cozile cu ștergere
automată sunt șterse atunci când nu mai există nici un consumator abonat la coadă .
Legăturile sunt utilizate de către schimburi de a lua decizia de rutare pentru un mesaj. Practic
legăturile conectează schimburile cu cozile și foloseșt e tipul de schimb bazat pe cheia de rutare
stabilită de coadă, câmpuri personalizate în antetul mesajului și cheia de rutare din mesaj trimis de
către producător. În cazul în care nu există suficiente legături pentru a face o decizie de expediere
pentru un mesaj, mesajul poate fi abandonat sau trimis înapoi la producător, pe baza proprietăților
stabilite în mesaj.
În cadrul modelului RabbitMQ, producătorul trimite un mesaj la un schimb. Comportamentul
schimbului este definit prin tipul de schimb, cheia de rutare și legăturile cu cozile de mesaje.
Consumatorul este destinația mesajelor trimise . Consumatorul trebuie să se înregistreze la o
coadă și să lege cu schimbul. În cazul în care există mai mulți consumatori înregistrați la o coadă,
RabbitMQ trimite m esaje către toți consumatori .
17
Caracteristici
1. Fiabilitate: RabbitMQ oferă o varietate de caracteristici ce pot fi folosite pentru a ajunge la
un compromis între performanță și fiabilitate inclusiv persistența, confirmări de livrare,
confirmarea producăt orului și înalta disponibilitate
2. Flexibilitatea transportării mesajelor: mesajele sunt transportarea prin schimburi înainte de
a ajunge la cozi
3. Clustering: mai multe servere RabbitMQ dintr -o rețea locală pot fi grupate împreună,
formând un singur broker
4. Suport pentru mai multe protocoale: RabbitMQ oferă suport pentru schimbul de mesaje
utilizând mai multe protocoale precum: AMQP, STOMP, MQTT
5. Suport pentru mai multe limbaje de programare:
a. Java
b. PHP
c. NodeJs
d. Python
e. Scala
f. Ruby
6. Interfață grafică pentru management
Protocolul AMQP
AMQP așa cum este prezentat in [19] este un protocol de comunicație dezvoltat de AMQP
Working Group , un consorțiu non -profit care are la bază convingerea că interoperabilitatea este o
caracteristică de bază în asigurarea interconectării sistemelor eterogene, în anul 20 06 de către
câteva dintre cele mai importante firme financiare mondiale și are un rol bine definit în domenii
ca infrastructură, integrare de aplicații, realizare de tranzacții și comunicații.
AMQP (Advanced Message Queuing Protocol) este un protocol de t ransfer binar care a
fost dezvoltat pentru aplicații de tip enterprise și pentru comunicația dintre servere (cum ar fi în
domeniul financiar), însă astăzi este foarte folositor în contextul Internet of Things, datorită
caracteristicilor sale.
Principalele avantaje ale acestui protocol sunt următoarele:
18
– este binar, ceea ce îi permite să folosească un nivel minim de date pentru comunicare,
pentru folosirea unui protocol ca HTTP pentru a trimite mesajele;
– are o natură ce permite multiplexarea, astfel, folosind o singură conexiune, se pot
transmite mesaje între două obiecte în ambele sensuri;
– este simetric, oferind atât posibilitatea de comunicare între client și server, cât și între
două sau mai multe servere.
Protocolul AMQP a fost standardizat din anul 2012 d e către OASIS și din anul 2014 de
către ISO/IEC , fiind concentrat pe modul in care datele sunt transferate pe calea de comunicație,
și nu pe partea software sau hardware a comunicației.
AMQP este un protocol bazat pe nivele ale modelului ISO/OSI, dar spr e deosebire de
acesta, AMQP conform [ 2] are în componență doar trei nivele: nivelul de mesaje, nivelul de
transport, nivelul de rețea.
Figura 9 AMQP modelul OSI
La nivelul de rețea , protocolul AMQP este bazat pe protocolul TCP, putând fi folosit astfel
împreună cu orice alt protocol de transport, cum ar fi SCTP (Stream Control Transmission
Protocol).
La nivelul de transport sunt definite comportamentul conexiunii și nivelele de securitate
dintre membrii activi ai conexiunii bazată pe protocolul de transport (TCP – Transmission Control
Protocol ). La acest nivel este prezentat și protocolul de formare a structurii în care este încadrat
mesajul, împreună cu modul de formatare și codare a datelor.
Obiectele care formează membrii unei rețele în care se comunică folosind protocolul
AMQP sunt:
19
– Noduri : entități responsabile pentru stocarea și livrarea mesajelor. În interiorul rețelei
un nod poate fi, de exemplu o coadă, sau un client care face o cerere. Un nod este
adresabil și poate fi organizat împreună cu celelalte noduri într -un model uniform,
ierarhic, sau grafic.
– Containere: de obicei un container este reprezentat de o aplicație. Nodurile se află de
obicei într -un container.
Așadar , la nivelul de transport , comunicația se realizează conform [16] astfel: se creează o
conexiune pe baza protoc olului TCP între containere, cu sau fără partea de securitate, realizată cu
ajutorul protocolului SSL/TSL. Apoi este creată o conexiune AMPQ peste conexiunea TCP, acest
lucru fiind realizat prin trimiterea unor pachete de date care conțin informații legate de versiunea
protocolului; la inițierea conexiunii se negociază protocolul de securitate utilizat, dacă este folosit
unul, folosind protocolul SASL ( Simple Authentication Security Layer). O astfel de conexiune
oferă o comunicație full -duplex, care are o s ecvență ordonată de cadre, a căror mărime este
negociată, oferind astfel un prim nivel de control al fluxului de date. Aceiași conexiune este
împărțită în canale unidirecționale, multiplexate, iar cadrele circulă prin conexiune având în
componență un ident ificator de canal.
După realizarea conexiunii, este stabilită o sesiune AMQP între două obiecte, care leagă
două canale unidirecționale, formând astfel un canal bidirecțional cu un mecanism de con trol al
fluxului de date bazat p e numărul de cadre trimise , respectiv primite.
Container
A
B
C
D
Calea către
nod: A
Calea către
nod: D
Conta iner
A
B
C
D
/
B1
Q
B2
B3
B4
Calea către
nod: /D
Calea către
nod: /B/B4
Topologia Uniformă Topologia Ierarhică Figura 10 – Topologia Uniformă Figura 11 Topologia Ierarhică
20
O conexiune poate suporta mai multe sesiuni. In final, pentru a realiza un schimb de mesaje
între două noduri, se creează o legătură AMQP între cele două noduri, care este o rută
unidirecțională atașată pentru fiecare nod, al unui te rminal care ar putea juca rolul de sursă sau de
țintă. Legătura oferă un al treilea nivel de control al fluxului de date pe baza unor credite.
În cazul în care conexiunea sau ses iunea se pierde, trebuie sc reinițiate, întrucât acestea nu
se păstrează în cazul unei întreruperi apărute între două noduri. În ceea ce privește informațiile
tranzacționate în timpul unei conexiuni realizate cu protocolul AMQP, acestea sunt formatate în
cadre.
Un cadru are trei părți principale : antetul cadrului – are o mări me fixă (8 bytes) și este
obligatoriu, acesta conținând informațiile necesare pentru procesarea întregului cadru, antetul
extins – este un antet variabil care depinde de tipul cadrului și corpul cadrului – o secve nță de
bytes care are un anumit format în f uncție de tipul cadrului.
Container
A
B
Noduri
Conta iner
A
B
Noduri
Conexiune
Session
Legătură
Legătură
Figura 12 Conexiunea, sesiunea și legătura
Figura 13 – Cadru AMQP
21
La nivelul de mesaje , aplicațiile care se bazează pe protocolul AMQP nu transmit
informații doar prin cadre; acestea conțin mesaje care sunt încorporate în aceste cadre. Structura
mesajului este bine definită, fiind compusă din d ouă părți principale:
– Mesajul original – reprezintă o parte a mesajului care nu poate fi schimbat de către părți
terțe odată ce mesajul a fost trimis, până când acesta ajunge la destinatar;
– Mesajul adnotat – care este reprezentat de mesajul original la car e se adaugă anumite
adnotări care pot fi folosite și schimbate de intermediarii dintre expeditor și destinatar.
Mesajul original conține corpul mesajului și două tipuri de grupuri de proprietăți: primul
grup este rezervat proprietăților care sunt stan dard și bine definite de către specificațiile AMQP,
iar cel de -al doilea grup este rezervat proprietăților specifice, definite de utilizator, care pot fi
adăugate și modificate de către aplicație.
Proprietățile de sistem definite de specificația protocolu lui conform [ 16] sunt:
– ID MESAJ: un identificator unic asignat mesajului de către producător;
– CĂTRE: identifică nodul destinatar pentru conținutul mesajului;
– SUBIECT: conține informații sumare în legătură cu conținutul mesajului;
– RĂSPUNDE LA: adresa nodului către care se pot trimite răspunsurile;
– ID CORELARE: folosit pentru corelarea dintre un mesaj de tip cerere și un mesaj de
tip răspuns;
– TIP CONȚINUT: folosit pentru a specifica tipul conținutului pentru datele ce nu pot fi
citite decât de destinatar;
– TIMP ABSOLUT DE EXPIRARE: timpul după care mesajul este considerat expirat.
Nivelul de mesaje definește un set de stări de livrare care au ca scop descrierea stării
mesajului in momentul livrării către destinatar. O stare de livrare poate fi terminală, ceea ce
înseamnă c ă mesajul nu mai poate fi schimbat, alungându -se astfel la ceea ce se numește rezultat,
sau non -terminală, ceea ce indică o stare intermediară folosită pentru recuperarea legăturilor
pierdute.
Mesaj adnotat
Antet
Adnotări
de livrare
Adnotări
de mesaj
Subsol
Proprietăți
de sistem
Proprietăți
de aplicație
Corpul
mesajului
Mesaj original
Figura 14 – Formatul mesajului
22
Stările terminale definite de protocol sunt:
– ACCEPTAT: mesajul a fost acceptat și procesat cu succes de către destinatar;
– REJECTAT: destinatarul a rejectat mesajul deoarece acesta este invalid sau nu poate fi
procesat;
– ELIBERAT: mesajul nu a fost procesat deși a fost valid și ar trebui retrimis;
– MODIFICAT: indică fap tul că mesajul a fost modificat dar nu procesat.
Există o singura stare non -terminală, numită PRIMIT care indică primirea unor date
parțiale ale unui mesaj sau punctul de pornire pentru un mesaj recuperat după pierderea
comunicației.
Toate conceptele AMQP (conexiune, sesiune, legătură, mesaje) sunt folosite împreună pentru a
defini protocolul AMQP de comunicație între două obiecte (aplicații, cozi, clienți). Principalii pași
care sunt folosiți în comunicație AMPQ sunt:
– DESCHIDE/INCHIDE: deschiderea, re spectiv închiderea unei conexiuni folosind
proprietățile ” open ” și ” close ”;
– ÎNCEPE/TERMINĂ: începerea, respectiv terminarea unei sesiuni în interiorul unei
conexiuni, folosind proprietățile ” Begin ” și ” end”;
– ATAȘARE/DETAȘARE: atașarea, respectiv detașarea unei legături către o sesiune
folosind proprietățile ” atach ” și ”detach ”;
– TRIMITE/PRIMEȘTE: trimiterea, respectiv primirea de mesaje cu controlul fluxului
de date prin folosirea proprietăților ” transfer ”, ”disposition ”, ”flow”.
Exemple de folosire a pro prietăților pentru realizarea comunicație i conform [ 16]:
– Deschide comunicația : pentru a se deschide o conexiune între două obiecte, se
realizează întâi o ”strângere de mână” folosind doar conexiunea TCP pentru a se stabili
protocolul de securitate utilizat, apoi propri etatea ” open ” este trimisă prin mesaj pentru
a defini dimensiunea maximă a cadrului mesajului (controlul fluxului), numărul maxim
de canale șamd. În interiorul conexiunii este creată o sesiune folosind proprietatea
”begin ” specificându -se numărul de cadre (controlul fluxului), ulterior fiind folosită
proprietatea ” attach ” pentru a atașa o legătură:
23
Figura 15 Deschiderea conexiunii
Sursa: https://dzone.com/refcardz/amqp -essentials
– Trimite mesaje : După ce linkul este atașat, destinatarul poate trimite o proprietate
”flow” către expeditor, specificând num ărul creditelor, pentru a limita numărul de
mesaje pe care le poate primi. Expeditorul trimite apoi datele folosind proprietatea
”transfer ” care este urmată de o proprietate de tipul ” disposition ” de la destinatar, dacă
și numai dacă nivelul dorit de calit ate este atins:
24
Figura 16 – Trimiterea de mesaje
Sursa: https://dzone.com/refcardz/amqp -essentials
– Primește mesaje : este opusul fluxului de mesaje de la SEND. Destinatarul trimite
proprietatea ” flow” pentru a seta fluxul de date pe bază de credite și numărul maxim de
mesaje pe care le poate primi înain te de a le procesa, apoi după ” transfer ” răspunde cu
un ”disposition ” pentru a verifica calitatea trimiterii:
25
Figur a 17 – Primirea de mesaje
Sursa: https://dzone.com/refcardz/amqp -essentials
– Închide comunicația: închiderea comunicației înseamnă detașarea de la toate
legăturile active folosind proprietat ea ”detach ”, apoi sunt închise sesiunile , folosind
proprietatea ” end” și conexiunea la nivel de socket folosind proprietatea ” close ”:
Figura 18 – Închiderea conexiunii
Sursa: https://dzone.com/refcardz/amqp -essentials
Protocolul AMQP oferă diferite căi de a controla fluxul de date la diferite nivele. Î n primul
rând, în timpul procesului de deschidere a conexiunii, cele două obiecte care vor comunica între
ele, negociază, o dimensiune maximă a cadrului, care conține mesajele.
Primul nivel de control al fluxului de date este oferit de sesiune. Fiecare obiect are la nivel
de sesiune o anumită fereastră de intrare, respectiv de ieșire care este limitată, astfel la fiecare
mesaj primit sau trimis, fereastra este decrementată, iar dacă fereastra ajunge la zero, transferul de
mesaje este oprit.
Ultimul ni vel de control al fluxului este cel de la nivelul mesajelor, unde fiecare legătură
are un anumit număr de credite, stabilit la începutul conexiunii, care reprezintă numărul maxim de
mesaje pe care un destinatar le poate primi de la un expeditor. Pentru fie care mesaj primit,
26
numărătorul de credite este decrementat, iar dacă acesta ajunge la valoarea zero, transferul de
mesaje este oprit.
Acest control al fluxului de date, bazat pe două nivel e este foarte util î n cazul platformelor
de Cloud, care pot avea mi lioane de conexiuni concomitent sau în cazul dispozitivelor care fac
parte din Internet of Things care au memorie mică în buffer.
Protocolul WebSocket
WebSocket conform [ 15] este o nouă caracteristică revoluționară în specificațiile HTML5,
ce definește un canal de com unicare full -duplex care funcționează pe Web printr -un singur socket.
Reprezintă un progres major pentru aplicațiile în timp real și aplicații web bazate pe evenimente.
WebSocket poate reduce traficul și latenț a din rețea pentru aplicațiile î n timp real în
comparație cu protocolul HTTP. În mod normal, atunci când un browser accesează o pagină web,
o solicitare HTTP este trimis ă către serverul web care găzduiește acea pagină. Server -ul web
recunoaște cererea și trimite înapoi un răspuns.
În multe cazu ri, de exemplu, pentru prețurile de vânzare, rapoarte de știri, vânzări de bilete,
modele de trafic răspunsul poate fi învechit în momentul în care browser -ul face pagina. În cazul
în care doriți să obțineți informațiile cele mai actualizate în timp real, puteți reîmprospăta continuu
pagina manual, dar asta nu e în mod evident o soluție.
Încercările anterioare de a furniza aplicații web în timp real gravitează în mare parte în jurul
soluțiilor de ”polling”, ”long polling”, precum și alte tehnologii de ”pus h” server -side, denumit în
mod obișnuit ca "Comet" , conform [ 15] . În cele din urmă, toate aceste metode pentru furnizarea
de date în timp real implică o cerere HTTP și de răspuns cu antete, care conțin o mulțime de date
suplimentare, care nu sunt necesare și introduc l atență.
Mai mult decât atât, conectivitate full -duplex necesită mai mult decât doar conexiunea
downstream de la server la client. Într -un efort de a simula comunicarea full -duplex peste jumătate
de duplex HTTP, multe dintre soluțiile de azi folosesc dou ă conexiuni: una pentru downstream și
una pentru upstream. Întreținerea și coordonarea acestor două conexiuni cresc semnificativ
consumul de resurse și se adaugă o mulțime de complexitate mărită.
27
WebSocket reprezintă cea mai bună soluție pentru aplicați i în timp real, deoarece acesta
este un nou protocol de transport pentru aplicații web care furnizează un flux bidirecțional de date
care sosește în ordine, la fel ca TCP. Ca și în cazul TCP, protocoalele de nivel superior pot rula
peste WebSocket.
Pentru a stabili o conexiune Web Socket, clientul și serverul actualizează de la protocolul
HTTP la protocolul WebSocket în timpul ”handshake inițial ” conform [ 18], așa cum se arată în
„Figura 19 Conexiune WebSocket ” de mai jos . De reținut că această descrier ea a conexiun ii
reprezintă cea mai recen tă versiune a protocolului, așa c um este definit în [ 20].
După handshake , clientul și serverul pot trimite mesaje în orice moment. Client și serverul
construi esc mesaje în conformitate cu protocolul WebSocket. Octeții care preced sarcina util ă de
date marchează lungimea cadrului și tipul. Cadrele de text sunt codificat e UTF -8.
Figura 19 – Conexiune WebSocket
Sursa : https://dzone. com/refcardz/html5 -websocket
28
Datele trimise din browser la server sunt mascat e, ceea ce reprezintă o caracteristică
neobișnuită a protocolului WebSocket. Fiecare octet de date sarcină utilă este X OR cu o mască
aleatoarea pentru a se asigura că traficul WebSocket nu arata ca si alte protocoale. La fel ca hash –
ul Sec-WebSocket -Key, acest a are menirea de a redu ce o formă de arcane de atac cross -protocol
împotriva unei infrastructuri de rețea care nu respectă cerințele.
WebSocket vs HTTP
Totalul antetului cererii și răspunsului HTTP fără datele din cookie conține 871 și asta e
doar antetul antetului , de obicei datele din antet depășesc 2000 de o cteți. Pentru o aplicație ce
folosește frecvent HTTP polling pentru actualizări în timp real pentru un număr mare de utilizatori
traficul pe rețea crește considerabil.
În „Figura 21 HTTP polling vs WebSocket ” compară reducerea dramatică a traficului inutil
de rețea, care se obține pentru soluția de polling, cu 1.000, 10.000 și 100.000 de clienți conectați
concurent și o compară cu ceea ce ar arata cu WebSocket in loc.
Figura 20 – Cadru WebSocket
Sursa : https://dzone. com/refcardz/html5 -websocket
29
În „Figura 22 Compararea latenței intre polling si WebSocket ” în jumătatea de sus, veți
vedea o latență a soluției semi -duplex de polling . Dacă presupunem pentru acest exemplu, că este
nevoie de 50 de milisecunde pentru un mesaj pentru a căl ători de la server la browser , atunci
cererea de polling introduce o mulțime de latență în plus, deoarece o no uă cerere trebuie să fie
trimisă la server atu nci când răspunsul este complet . Această nouă cerere ia alt e 50ms, timp în care
serverul nu poate trimite mesaje către browser , ceea ce duce la un consum suplimentar de memorie
de server .
Figura 21 – HTTP polling vs WebSocket
30
În jumătatea inferioară a figurii, se observă reducerea latenței furnizate de soluția
WebSocket. Odată ce conexiunea este actualizat ă la WebSocket, mesajele pot curge de la server
la browser în momentul în care ajung. Este încă nevoie de 50 ms pentru ca mesajele să călătorească
de la server la browser , dar con exiunea WebSocket rămâne deschisă, astfel încât nu este necesar
să se trimită o altă cerere la server.
WebSocket oferă un pas enorm înainte în scalabilitate a plicațiilor web în timp real. După
cum tocmai am arătat, WebSocket poate oferi 500: 1 sau în func ție de mărimea antetelor chiar și –
HTTP 1000: reducerea 1 în trafic inutil antet HTTP și 3: 1 reducere în latență conform cu [ 15].
Baza de date NoSQL Cassandra
Apache Cassandra este o bază de date NoSQL puternică și scalabilă. Este construită
pentru a gestiona sarcinile de lucru mari în timp real în mai multe centre de date fără niciun
punct de eșec conform cu [3]. Funcționează pe hardware normal și poate fi ușor implementat
într-o infrastructură cloud -based.
Cassandra are acum 5 ani. Este un proiect open sou rce activ în Fundația Software Apache
și, prin urmare, este cunoscută și ca Ap ache Cassandra. Cassandra poate g estiona un volum
Figura 22 – Compararea latenței intre polling si WebSocket
31
imens de date structurate, semi -structurate și nestructurate într -un volum mare distribuit în mai
multe centre de date. Ofer ă scalabilitate liniară, înal tă performanță, toleranță la erori și suportă
un model de date foarte flexibil.
NoSQL
Nu există o singură definiție pentru NoSQL. Pentru unii, aceasta înseamnă "Nu numai SQL",
la alții înseamnă "Nu SQL" conform [6] . Oricum, se referă la plecarea de la tradiționalel e
tehnologii de baze de date relaționale care au dominat peisajul de dezvoltare pentru ultimele
decenii.
Ce se crede a fi cel mai mare motor al mișcării NoSQL este de fapt o credință comună că
bazele de date relaționale nu sunt adecvate pentru canti tăți m ari de date și nu scalează . Baz ele de
date NoSQL cuprind o varieta te mare de tehnologii diferite ș i Cassandra este una dintre cele mai
populare. Alte baze de date NoSQL sunt:
MongoDb
Redis
Riak
Neo4j
HBase
Deci, ce fel de beneficii sunt oferite de NoSQL? În comparație cu modelul relațional de baze
de date, NoSQL depășește punctele slabe pe care modelul de date relațional nu îl are
implementează bine, care sunt următoarele:
Volum mare de date structurate, semi – structurate si nestructurate
Model flexibil (s chema) si ușor de schimbat
Scalabilitate si performanta pentru aplicațiile la scara larga
Cost redus
Replicare built -in
Scalabilitatea și performanța pentru aplicațiile la scară largă se referă la capacitatea sistem de
a fi mărit (scalat), de preferință o rizontal, pentru a susține volumul de lucru la scară largă fără
deteriorarea considerabilă a performanțelor sistemului. Bazele de date relaționale pot fi scalate
numai pentru a forma un cluster format dintr -un număr foarte mic de noduri , iar pentru aplica țiile
la scara larga nu este de ajuns. În plus, schimbarea schemei într -o bază de date relațională bazată
pe cluster este o sarcină importantă si complexă . Puterea de procesare pentru a face acest lucru
32
este foarte semnificativa ș i trebuie realizat ă fără a fectarea performantelor sistemului. Cele mai
multe baze de date NoSQL au fost create pentru a servi aplicații lor la scară largă. Ele susțin nativ
scalarea fără degradarea performanței prea mult.
Tipuri de baze de date NoSQL
Tipurile de baze de date NoSQ L pot fi împărțite î n patru mari categorii:
1. Pereche cheie -valoare
2. Familii de coloane
3. Bazate pe document
4. Baze de date pentru graf -uri
Baze de date de tip cheie -valoare
Perechea cheie / valoare este cel mai simplu tip de bază de date NoSQL. Memoria de tip
cheie / valoare este similară conceptului de registru Windows, sau în Java sau C #, o hartă, un
hash, o pereche cheie / valoare . Fiecare element de date este reprezentat ca un nume de atribut,
de asemenea o cheie, împreună cu valoarea sa. Este, de asemene a, unitatea de bază stocată în
baza de date. Exemple de baze de date de tip cheie / valoare:
Amazon Dynamo
Redis
Riak
Pe plan intern, perechile chei / valori sunt stocate într -o structură de date chemată la
hashmap. HashMap este popular deoarece oferă per formanțe foarte bune în ceea ce privește
accesarea datelor. Cheia lui dintr -o pereche cheie / valoare este unică și poate fi căutată foarte
rapid.
Perechea cheie / valoare poate fi stocată și distribuită în spațiul de stocare a discului, precum
și în memo rie. Când este folosit în memorie, poate fi folosit ca o memorie cache, care depinde de
algoritmul de cache, poate reduce considerabil discul I / O și prin urmare, crește performanța
semnificativ.
Pe de altă parte, perechea de cheie / valoare are unele ne ajunsuri, cum ar fi lipsa suportului
pentru interogări mai complexe, nici o modalitate de a funcționa simultan pe mai multe chei și
posibil probleme cu balansarea încărcării.
33
Baze de date de tip familii de coloane
O coloană în acest context nu este egală cu o coloană dintr -o tabelă relațională. În lumea
NoSQL o coloană este o structură de date care conține o cheie, o valoare și o marcă de timp. Prin
urmare, aceasta poate fi privită ca o combinație de perechi cheie / valoare și o marcă de timp.
Exemple sunt Google Big Table, Apache Cassandra și Apache HBase. Aceste baze de date
furnizează o performanță optimizată pentru interogări pe seturi de date foarte mari.
Bazele de date de tip familii de coloane sunt în esență o harta multidimensionala. Se
stochează c oloane de date împreună ca un rând, care este asociat cu o cheie rând. Acest lucru
contrastează cu rânduri de date într -o bază de date relațională. Bazele de date de tip familii de
coloane nu au nevoie pentru a stoca coloane null, ca în cazul unei baze de date relaționale și
astfel consumă mult mai puțin spațiu pe disc. Mai mult, coloanele nu sunt legate de o schemă
rigidă și nu este necesar pentru a defini schema în avans.
Componenta cheie a unei coloane este denumită de obicei cheia primară sau cheia de
rând. Coloanele sunt stocate într -un mod sortat de cheia rândului. Toate datele aparținând unei
chei de rând sunt stocate împreună. Ca atare, operațiile de citire și scriere a datelor pot fi limitate
la un nod local, evitând traficul de rețea inter -nod inu til într -un cluster. Acest mecanism face ca
căutarea și extragerea datelor să fie extrem de eficiente.
Evident, o baza de date de tip familii de coloane nu este cea mai bună soluție pentru
sistemele care necesită ACID și nu are suport pentru interogările agregate furnizate de baze de
date relaționale, cum ar fi SUM ().
Baze de date orientate pe documente
Aceste baze de date sunt concepute pentru documente sau date semi -structurate. Unitatea
de bază a unei baze de date bazata pe documente asociază fiecare cheie, un identificator primar,
cu o structură complexă de date numită document. Un document poate conține multe diferite
perechi de chei -valoare sau perechi de chei -matrice sau chiar documente imbricate. Prin urmare
,o baze de date orientată pe documente nu aderă la o schemă. Exemple sunt MongoDB si
CouchDB.
În practică, un document este, de obicei, un set slab structurat de perechi cheie / valoare
în formă de notație de obiect JavaScript (JSON). Aceste baze de date gestionează un document
34
ca un întreg ș i evită ruperea unui document în fragmente de perechi cheie / valoare. De
asemenea, permite ca proprietățile documentelor să fie asociate unui document.
Întrucât baza de date pentru documente nu aderă la o schemă fixă, performanța căutării
nu este garant ată. Există, în general, două abordări pentru interog area unei baze de date orientată
pe documente. Primul este de a utiliza vizualizări materializate (cum ar fi CouchDB) care sunt
pregătite în avans. Al doilea este de a folosi indecși definiți pe valorile documentului (cum ar fi
MongoDB) care se comportă în același mod ca un index de bază de date relațională.
Baze de date pentru graf -uri
Bazele de date pentru graf -uri sunt concepute pentru a stoca informații despre rețele, cum
ar fi o rețea socială. Un g raf este utilizat pentru a reprezenta rețeaua fo arte conectată care este
compusă din noduri și relațiile lor. Nodurile și relațiile pot avea proprietăți individuale. Bazele de
date pentru graf -uri proeminente sunt: Neo4J si FlockDB.
Datorită caracteristic ilor unice ale unui graf, bazele de date pentru graf -uri oferă în mod
obișnuit un API pentru traversarea rapidă a graf -urilor.
Bazele de date pentru graf -uri sunt deosebit de dificil de a fi scalate cu distribuirea
datelor , deoarece traversând un graf cu noduri pe mașini dife rite nu oferă o performanta bună . De
asemenea, nu este o operație simplă de actualizare a tuturor sau a unui subset de noduri în același
timp.
ACID
ACID înseamnă „Atomicitate, Consistență, Izolare și Durabilitate ”[7]. Pentru a înțelege
ACID și cum se referă la bazele de date, trebuie să vorbim d espre tranzacții. Când se referă la
baze de date, o tranzacție este definită ca o singură operație logică. De exemplu, dacă cumpărați
online, de fiecare dată când adăugați un articol în coșul dvs. d e cumpărături, articolul respectiv și
cantitatea acestuia constituie baza tranzacției a bazei de date. Chiar dacă adăugați mai multe
elemente sau mai multe cantități din același articol, cu un singur clic, coșul de cumpărături este
complet adăugat într-o tranzacție unică.
Atomicitatea înseamnă că fiecare tranzacție funcționează sau nu. Asta înseamnă că dacă
orice parte a tranzacției nu reușește, întreaga tranzacție nu reușește. Acest lucru ar trebui să fie
35
valabil pentru toate situațiile legate de o tranza cție care ar putea provoca un eșec. Eroarea rețelei,
întreruperea alimentării sau chiar o întrerupere a nodului care apare la timpul de tranzacționare ar
trebui să provoace eșecul complet al tranzacției într -un sistem atomic.
Consistența asigură că atunc i când o tranzacție este finalizată, fie că este sau nu reușită,
baza de date este încă într -o stare validă. Aceasta înseamnă că toate datele scrise în baza de date
trebuie să fie de asemenea valabile . Când scrieți date în baza de date, trebuie să in cludeț i și orice
regula definită la nivel de aplicație în baza de date, cum ar fi constrângerile, cascadele,
declanșatoarele sau procedurile stocate. Aplicarea acestor reguli ar trebui, de asemenea, să lase
datele într -o stare valabilă.
Izolarea este o propriet ate care asigură că toate tranzacțiile care se execută concomitent
apar ca și cum ar fi fost executate în serie (unul după altul). Fiecare tran zacție trebuie executată
într-un vid (izolare). Aceasta înseamnă că dacă două tranzacții sunt executate în acelaș i timp, ele
rămân independente una de cealaltă în timpul tranzacției. Câteva exemple de izolare sunt „locks”
(tabele, rând, coloană etc.),”dirty reads and deadlocks”. Motivul pentru care acestea sunt
relevante este concurența. Pot fi încercate mai multe mo dificări pe aceleași date sau seturi de
date. Știind ce versiune a datelor este cea corectă este importantă pentru păstrarea întregului
sistem într-o stare validă .
Durabilitatea înseamnă că după încheierea tranzacției va rămâne în acest fel. În altele
cuvinte, schimbarea datelor care este generată de tranzacție este stocată permanent, indiferent de
evenimente externe (cum ar fi o întrerupere a alimentării cu energie electrică).
Teorema CAP
Teorema CAP, cunoscută și ca teorema lui Brewer, afirmă că este imposibil pentru ca
sistem distribuit pentru a satisface toate cele trei garanții ale CAP. CAP reprezintă toleranța
pentru „consistență(C), disponibilitate(A) și partiționare(P). De notat despre teorema CAP este
că toate cele trei părți ale acesteia nu pot f i satisfăcute în același timp ” [5].
Deși C în CAP înseamnă de asemenea consistență (similară cu C în ACID), sensul este
diferit. Consistența înseamnă că toate nodurile dintr -un cluster văd aceleași date la același timp.
Cu alte cuvinte, orice interogare partic ulară care lovește orice nod din sistem va returna același
rezultat pentru acea interogare specifică. Conform cu [24] „consistenta implică, de asemenea, că
atunci când o interogare actualizează o valoare într -un singur nod, datele vor fi actualizate pentru
a reflecta noua valoare înainte de următoarea interogare ”.
36
Disponibilitatea unui sistem se referă la garanția că, indiferent de succes sau eșecul unei
cereri, solicitantul va primi un răspuns. Acest lucru înseamnă că operațiile asupra sistemului vor
putea continua chiar da că o parte a sistemului este nefuncțională, oricare ar fi motiv -ul.
Disponibilitatea este ceea ce permite software -ului să încerce să facă față și să compenseze
factori externi precum ar fi defecțiunile hardware, întreruperile rețelei, defecțiunile de alim entare
și altele asemenea.
Toleranța partiționării se referă la capacitatea unui sistem distribuit de a distribui eficient
sarcinile de lucru pe noduri multiple. Sarcinile ar putea fi date sau interogări. Asta implică că
chiar dacă câteva noduri sunt în j os, sistemul va continua să funcționeze. „Sharding” este o
tehnica de management utilizată frecvent pentru distribuirea încărcării într -un cluster. Sharding,
este similar cu partiționarea orizontală, este o modalitate de divizare a datelor în părți separat e si
deplasarea acestora către un alt server sau o locație fizică, în general pentru performanță
îmbunătățita.
Există diferite motive pentru care toate cele trei parți ale teoremei nu pot fi satisfăcute
simultan î n sisteme distribuite. CAP este adesea fol osită pentru a justifica utilizarea modelelor de
consistență mai slabe.
Arhitectura de nivel înalt a Cassandrei
Cassandra rulează pe o „arhitectură peer -to-peer, ceea ce înseamnă că toate nodurile din
cluster au responsabilități egale, cu excepția faptulu i că unele dintre acestea sunt noduri de seed
pentru alte noduri non -seed pentru a obține informații despre cluster în timpul puneri în
funcțiune ” [27]. Fiecare nod deține o partiție a bazei de date. Cassandra asigură distribuirea
automată a datelor si replicare a în toate nodurile din cluster. Sunt oferiți parametri pentru a
personaliza comportamentele de distribuție și replicare. Odată configurate, aceste operațiuni sunt
prelucrate în fundal și sunt pe deplin transparente pentru dezvoltatorii de aplicații.
Cass andra este o baza de date de tip familii de coloane și oferă o flexibilitate excelentă
pentru dezvoltatorii de aplicații. Acesta este conceputa pentru a gestiona un volum mare de date
într-un cluster fără un singur punct de eșec. Deoarece mai multe copii a le acelorași date (Replici)
sunt replicate în cluster, ori de câte ori un nod eșuează din orice motiv, celelalte replici sunt încă
disponibile. Replicarea poate fi configurată pentru a răspunde diferite setări de cluster fizic,
inclusiv locații de centre d e date și rack.
37
Orice nod din cluster poate accepta citirea sau scrierea cererilor de la un client. Nodul
care este conectat la un client cu o cerere servește ca coordonator al acelei particulare cere ri.
Coordonatorul determină ce noduri sunt responsabile pentru menținerea datele pentru cerere și
acționează ca un proxy între client și noduri.
Cassandra împrumută mecanismul „commitlog” de la Google Big Table pentru a asigura
datelor durabilitate. Ori de câte ori o cerere de scriere de date este primită de un nod, ea este
scrisă în commitlog. Datele care sunt actualizate sunt apoi scrise la o structură de memorie,
cunoscut sub numele de „memtable”. Când tabelul din memorie este plin, datele din interiorul
acestuia sunt reduse la o structură de stocare pe dis c, „SSTable”. Scrierile sunt împărțite automat
de către cheia de rând și replicate la celelalte noduri care dețin aceeași partiție de date.
Cassandra oferă scalabilitate liniară, ceea ce înseamnă că performanța și capacitatea
clusterului este proporțio nală cu numărul de noduri din acesta.
Partiționarea
Abilitatea de a scala orizontal și incremental este o caracteristică de design pentru
Cassandra. Pentru a realiza acest lucru, Cassandra trebuie să distribuie dinamic datele de pe set -ul
de noduri din cluster.
Un cluster este structura cea mai exterioară care este compusă din noduri din Cassandra.
Este, de asemenea, un container al spațiului de chei (keyspace). Un keyspace în Cassandra este
similar cu o schema într -o bază de date relațională. Fiecare c luster Cassandra are un keyspace al
sistemului pentru a păstra metadatele la nivel de sistem. Acesta conține setările de replicare care
controlează modul în care datele sunt distribuite și replicate într -un cluster. Fiecare nod din cluster
Figura 22 – Scalabilitatea unui cluster
Sursa: http://docs.datastax.com/en/cassandra/2.1/cassandra/gettingStartedCassandraIntro.html
38
are o replică pe ntru un interval diferit de date în partiții și schimbă informații în cadrul clusterului
la fiecare secunda.
Un client emite citiri sau scrie cereri către orice nod. Nodul care primește cererea devine
un coordonator care acționează ca proxy al clientulu i. Datele sunt distribuite de -a lungul clusterului
și mecanismul de adresarea a nodului este numit „consistent hashing”. Prin urmare, un cluster
poate fi privit ca un inel din hash ca fiecare nod din cluster sau inel este atribuit un singur token
unic astf el că fiecare nod este responsabil pentru datele din intervalul de la token -ul atribuit la
acestui la nodul anterior. De exemplu, în figura următoare, un cluster conține patru noduri cu
token -uri unice:
Fiecare rând are o cheie de rând folosită de compon enta de partiționare pentru a calcula
valoarea hash. Valoarea hash determină nodul care stochează prima replică a rândului.
Componenta de partiționare este doar o funcție hash utilizată pentru a calcula valoarea hash -ului
unei chei de rând și afectează de asemenea modul în care sunt distribuite datele sau echilibrarea
datelor în cluster.
Figura 22 – Cassandra consistent has hing
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
39
De exemplu, valoarea hash pentru cheia „ORACLE” este „6DE7” care se încadrează în
intervalul de 4.000 și 8.000 și astfel rândul merge mai întâi la nodul inferior(nodul v erde din
imagine). Toate replicile rămase sunt distribuite în funcție de strategia de replicare.
Replicarea
Cassandra utilizează replicarea pentru a obține o disponibilitate ridicată și durabilitatea
datelor. Toate datele sunt reproduse la un număr de nod uri care sunt configurate de un parametru
numit factor de replicare. Coordonatorul comandă replicarea datelor în cadrul acestuia si replică
datele la celelalte noduri din ring. Cassandra furnizează clienților diverse opțiuni configurabile
pentru a vedea cu m trebuie replicate datele, care se numește strategie de replicare.
Strategia de replicare este metoda de determinare a nodurilor unde replicile sunt plasate.
Acesta oferă multe opțiuni, cum ar fi rack -aware, rack -unware, rețeaua de topologie -aware și a șa
mai departe.
Figura 23 – Replicarea
Sursa: https://www.slideshare.net/patrickmcfadin/apache -cassandra -apache -spark-for-time-series -data
40
Fluxul scrierilor
„Figura 24 Fluxul scrierilor în Cassandra ” prezintă componentele și succesiunea lor de
execuții formate pentru o scriere î n Cassandra:
Când apare o scriere, datele vor fi imediat atașate î n commitlog de p e disc pentru a asigura
durabilitatea scrierii. Apoi Cassandra stochează datele în memtable, o stocare în memorie a datelor
recent utilizate. Când memtable este plin, datele vor fi salvate pe un fișier de disc, numit SSTable,
folosind o scriere secvențială pe disk . Acesta este motivul pentru care performanța de scriere este
atât de mare. Commitlog -ul este curățat după salvarea datelor pe disk.
„Datorită adoptării intenționate de scriere secvențială pe disk , un rând este de obicei stocat
în mai multe fișiere SSTable. În afară de datele sale, SSTable are, de as emenea, un indice primar
și un Bloom filter” [4]. Un indice primar este o listă cu cheile de rând și poziția de start a rândurilor
în fișierul de date. Bloom filter este un algoritm nedeterminist pentru a v erifica daca un e lement
este membru al unui set și este folosit î n Cas sandra pentru a spori performanț a.
Figura 24 – Fluxul scrierilor în Cassandra
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
41
Pentru operațiile de scriere, Cassandra susține consistența reglabilă prin setarea diverselor
nivelurile de consistență la scriere. Nivelul de consist ență de scriere este numărul de replici care
sunt folosite pentru a confirma o scriere ca fiind reușită. Este reglabil pe un spectru de consistență
de scriere pe diferite niveluri, după cum se arată în „Figura 25 – Niveluri de consistenta la scriere ”
Următoarele descriu termenii din figură conform [ 4]:
ANY – cea mai scăzută consistenta, ce mai mare disponibilitate
ALL – cea mai mare consistenta, toate replicile trebuie sa confirme scrierea
ONE – cel puțin o replica trebuie sa confirme scrierea
TWO – cel puțin doua replici
THREE – cel puțin trei r eplici
QUORUM – Acest lucru asigură o consistenta puternică prin tolerarea unui anumit nivel
eșec, care este determinat de (factorul de replicare / 2) + 1 (rotunjit în jos la cel mai apropiat
număr întreg)
LOCAL_QUORUM – Acest lucru se întâmplă pentru mai multe centre de date și rack –
aware fără trafic intre centre de date
EACH_QUORUM – folosit pentru mai multe centre de date
Fluxul citirilor
Figura 25 – Niveluri de consistenta la scriere
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
Figura 26 – Fluxul citirilor
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
42
„ Figura 26 – Fluxul citirilor ” prezintă componentele și secvența acestor execuții care
formează o cale de citire. Când o cere re de citire intră într -un nod, datele care urmează să fie
returnate sunt fuzionate de la toate SSTable -uri asociate și a oricăror memtable neînchise. Valoarea
fuzionată este, de asemenea, stocată într -o memorie cache pentru a îmbunătăți performanța la cit iri
în viitor.
Similar cu nivelurile de consistență de scriere, Cassandra oferă, de asemenea, nivelurile de
consistență reglabile, după cum se arată în figura următoare:
Figura 27 – Niveluri de consistenta la citire
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
Nivelul de consistență la citire est e numărul de replici contactat pentru o citire cu succes.
Nivelurile de consistență la citire sunt aproape identice cu nivelurile de consistență la scriere, cu
excepția faptului că ANY nu este o opțiune aici.
Caracteristicile Cassandrei
Următoarea list ă cuprinde marile caracteristici furnizate de Cassandra conform [26]:
Scrisa in Java si oferă suport pentru aplicațiile Java
Un amestec intre Google BigTable si Amazon Dynamo
Model de date de tip familii de coloane si flexibilă fără schema
Suport pentru date structurat e si nestructurate
Descentralizata, distribuita pe o arhitectură peer -to-peer
Replicare pe mai multe centre de date
Transparenta la locație
Optimizata pentru scrieri
Furnizarea limbajului Cassandra Query Language(CQL), un limbaj asemănător SQL cu
INSERT, U PDATE, DELETE, SELECT
Niveluri reglabile de consistenta
Toleranta la erori si fără nici un punct de eșec
43
Modelarea Datelor
În lumea relațională, modelarea datelor se realizează creând entități și asociându -le cu
relații în conformitate cu orientările g uvernate de teoriile relaționale. Aceasta înseamnă că vă puteți
concentra doar asupra vizualizării logice sau a structurii datelor fără a lua în considerare modul în
care aplicația accesează și manipulează datele. Obiectivul este de a avea un model de date stabil,
care să respecte modelul de date relațional. Designul aplicației poate fi realizat separat. De
exemplu, se pot răspunde la diferite interogări prin construirea de diferite instrucțiuni SQL, care
nu sunt un motiv de îngrijora re în timpul modelarii datelor.
Dimpotrivă, în Cassandra, inversați pașii de mai sus și întotdeauna începeți de la ce i în care
se stabilesc interogările la nivelul aplicației. Interogările exercită o influență considerabilă asupra
modelului de date. Trebuie, de asemenea , luat in calcul stocarea fizică și topologia clusterului.
Modelarea datelor î n Cassandra este orientată spre rezultate pe baza înțelegeri clare a modului în
care o interogare funcționează intern în Cassandra.
Datorită arhitecturii unice a Cassandrei, multe lucr uri simple într -o baza de date relațională,
cum ar fi secvența și sortarea, nu pot fi realizate.
Structura logică a datelor
Modelu l intern de stocare al datelor î n Cassandra este ba zat pe modelul „column or iented
din BigTable ”[4]. Un model orientat pe co loane este un „Map” multidimensional. Mai exact, este
o structură de date cunoscută sub numele de Map. Un exemplu din declarația de structură a datelor
de Map este după cum urmează:
Structura de date de tip Map oferă o căutare cheie eficientă și natura sortată oferă scanări
eficiente. RowKey este o cheie unică și poate deține o valoare. Structura de date interioară
SortedMap permite un număr variabil de valori cu cheia ColumnKey. Acesta este trucul
Cassandre i, nu utilizează o schema și permite modelul ui de date să evolueze natural în timp.
Figura 28 – Declarația unui Map
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
44
Trebuie notat ca fiecare colo ană are o marcă de timp asociată furnizată de client, dar poate fi
ignorat în timpul modelarii datelor. Cassandra utilizează marca de timp inte rn pentru a rezolva
conflictele legate de tranzacție.
Coloana
Coloana este cel mai mic element de model de date și unitate de stocare din Cassandra.
Deși există, de asemenea, într -o bază de date relațională, este un lucru diferit în Cassandra. Așa
cum se arată î n figura următoare, o coloană est e o pereche de nume -valoare cu un marcaj de timp
și un Timp -de-viață (TTL) opțional:
Rând
Un nivel mai sus fat ă de col oană este un rând, așa cum este reprezentat în figura de mai
jos. Este un set de coloane ordo nate cu o cheie de rând unică, cunoscută și ca o cheie primară.
Cheia de rând poate fi oricare dintre aceleași tipuri de date încorporate ca cele pentru coloane.
Coloanele ordonate înseamnă că coloanele sunt stocate în ordine ordonată după numele coloanelo r.
Diferite nume în coloane sunt posibile în diferite rânduri. De aceea, Cassandra este orientat
atât pe rând, cât și pe coloană. Trebuie remarcat că nu există marcaj de timp pentru rânduri. Mai
mult, un rând nu poate fi divizat pentru a fi stocat în două noduri din cluster. Aceasta înseamnă că
dacă un rând există pe un nod, întregul rând există pe acel nod.
Figura 29 – Elementele unei coloane
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
45
Familia de coloane
Următorul nivel este o familie de coloane. După cum se arată în „Figura 30 – Structura unei
familii de coloane ”, este un spațiu de stocare pentru un set de rânduri cu un nume:
Figura 30 – Elementele unui rând
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
Figura 30 – Structura unei familii de coloane
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
46
Cheile de rând dintr -o familie de coloane trebuie să fie unice și sunt folosite pentru a ordona
rânduri. O familie de coloane este similară cu o tabelă într -o bază de date relațională, dar nu ar
trebui să mergeți prea departe cu aceas tă idee. O familie de coloane oferă o flexibilitate mai mare
permițând diferite coloane în diferite rânduri. Orice coloană poate fi adăugată în mod liber în orice
familie de coloane în orice moment. Coloanele dintr -o familie de coloane sunt sortate de un
comparator. Comparatorul determină modul în care coloanele sunt sortate și ordonate când
Cassandra returnează coloanele î n urma unei interogări.
Din punct de vedere fizic, familiile de coloane sunt stocate în fișiere individuale de pe un
disc. Prin urmare , este important să păstrați coloanele asociate în aceeași familie de coloane pentru
a salva operațiile cu diskul și se poate îmbunătăți performanța.
Keyspace
Modelul de date ultra periferice este keyspace, după cum se arată în figura următoare:
Keysp ace este un set de familii de coloane și familii de super -coloane. Este similar cu o
schemă sau o bază de date în lumea relațională. Fiecare instanță Cassandra are un keyspace pentru
sistem pentru salva meta date la nivel de sistem.
Figura 31 – Elementele unui keyspace
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
47
Un keyspace conține se tări de replicare care controlează modul în care sunt distribuite
datele și replicate în cluster.
Cheia Primar ă
Cassandra este o bază de date bazată pe coloane. Fiecare rând poate avea un număr diferit
de coloane. O celulă este deținătorul valorii și a m ărcii de timp sunt identificate printr -un rând și
o coloană. „Fiecare celulă poate stoca valori mai mici de 2 GB. Râ ndurile sunt grupate pe partiții .
Numărul maxim de celule pe partiție este limitat la condiția că numărul de rânduri de ori numărul
de coloane este mai mic de 2 miliarde ” [26]. Fiecare rând este identificat printr -o cheie de rând
care determină ce mașină stochează rândul. În alte cuvinte, cheia de rând determină locația nodului
rândului. O listă cu cheile de rând dintr -un tabel este cunoscut ă ca o che ie primară. Un index primar
este creat doar pe cheia primară.
O cheie primară poate fi definită pe o singură col oană sau pe mai multe coloane. Î n orice
caz, prima componentă a cheii primare a unui tabel este cheia de partiție. Fiecare nod stochează o
partiție de date a tabelului și își păstrează propria cheie prima ră pentru datele pe care le
gestionează. Prin urmare, fiecare nod știe ce rânduri de cheie de rând poate gestiona si rândurile
pot fi apoi localizate prin scanarea indecșilor de rând doar pe re plicile relevante. Gama de chei
primare pe care un nod le gestionează este determinată de cheia de partiție și un parametru de
configurație la nivel de cluster denumit „partitioner”.
Figura 32 – Partiționare
Sursa: https://blog.knoldus.com/2016/10/18/cassandra -data-modeling -primary –
clustering -partition -compound -keys/
48
O cheie primară poate fi definită de cuvintele c heie CQL PRIMARY KEY, cu coloană
(coloanele) pentru a fi indexat ă.
O ch eie primară compusă este formată din mai mult de o coloană. Ordinea coloanele este
importantă. Structura unei chei primare compuse este descrisă în „Figura 33 – Structura unei chei
primare ”.
Figura 33 – Structura unei chei primare
Sursa: C.Y. Kan Cassandra Data Modelling and Analysis
Coloanele de la 1 la A sunt utilizate ca cheie de partiție pentru Cassandra pentru a
determina nodul locație pentru partiție. Coloanele rămase, coloanele B până la N, sunt denumite
coloanele de grupare pentru ordonarea datelor. Coloanele de grupare sunt ut ilizate pentru a
localiza o înregistrare unică în nodul de date. Ele sunt ordonate, în mod implicit, și au capacitatea
de a utiliza clauza ORDER BY [DESC] în operațiile de regăsire a datelor. Mai mult, se pot
obține valorile minime sau maxime pentru cheile de grupare cu clauza „LIMIT 1”.
49
Considerente legate de dezvoltare a sistemului
Cerințele sistemului
Sistemul oferă utilizatorilor funcționalităț i care pot fi împărțite î n patru categorii principale:
monitorizarea locației, gestiunea resur selor flotei, gestiunea sarcinilor de lucru ș i alertarea
utilizatorilor la diferite evenimente din sistem.
Monitorizarea locației presupune determinarea coordonatelor GPS apoi transmiterea
acestora către un broker de mesaje pentru a fi procesate. Procesa rea datelor rep rezintă afișarea
coordonatelor în timp real pe harta ș i salvarea lor într -o baza de date pentru a putea apoi vizualiza
traseul unui angajat.
Resursele flotei s unt reprezentate prin angajați ș i autovehicule iar gestionarea lor
reprezintă: ad ăugarea, editarea si afișarea acestora într -o aplicație web.
O sarcină de lucru reprezintă un transport de diferi te obiecte de la o locație sursă la o
destinație, poate fi interpretat ca un transport de marfă de la o sursă la o destinație.
Gestiunea sarc inilor de lucru reprezintă adăugarea acestora pentru diferiți angajați , iar
aceștia să poată actualiza starea sarcinii. Stările unei sarcini de lucru pot fi: sarcina nouă, sarcina
în curs de finalizare și sarcina finalizată .
Alertarea utilizatorilor este o funcționalitate foarte importantă a sistemului deoarece atât
angajați dar ș i administratori d e flote auto pot fi notificați î n timp real cu noile evenimente din
sistem. De exemplu un eveniment î n sistem este reprezentat prin adăugare unei sarcini de luc ru iar
angajatul responsabil va fi alertat imediat daca este conectat la internet.
Componentele sistemului
Sistemul de monitorizare si gestiune al unei flote este format din 3 componente:
50
1. O aplicație we b ce oferă localizare pe hartă î n timp real, gestion area resurselor flotei ș i a
sarcinilor de lucru
2. O aplicație pentru dispozitive mobile cu sist emul de operare Android folosită de către
angajați ș i este responsabil ă cu determinarea și transmiterea coordonatelor î n timp real
3. Un serviciu Web dezvoltat utili zând limbajul de prog ramare JAVA ce oferă o interfață
programabila REST pentru celelalte componente ale sistemului dar și punct de comunicație
utilizând protocolul WebS ocket pentru primire și trimiterea de mesaje î n timp real din
aplicația Web .
Tipuri de utilizatori
Sistemul poate avea 2 tipuri de utilizatori:
1. Administratori de flote auto
2. Angajați
Pentru administratori sistemul oferă o aplicație web ce poate fi utiliza tă pentru monitorizarea
în timp real pe hartă a angajaților dar ș i pentru gestiunea res urselor flotei auto. Administratori sunt
cei care pot da acces angajaților î n sistem.
Angajații au acces limitat în sistem fată de administratori ș i pot folosi doar aplicația Andro id.
Din aplicație putând doar să vadă sarcinile de lucru pentru care sun t responsabili și de asemenea
să modifice starea unei sarcini de lucru.
Figura 34 – Componentele si utilizatori sistemului
51
Lista de cerințe
Sistemul a fost construit pe baza următoarelor cerințe:
1. Monitorizarea locației
1.1. Administratori – Aplicația Web
1.1.1. Afișarea in timp real a coordonatelor GPS pe o harta a u nui angajat
responsabil pentru o sarcina de lucru specificata
1.1.2. Afișarea in timp real a coordonatelor GPS pe o harta a tuturor angajaților
gestionați de un administrator de flota
1.1.3. Vizualizarea detaliilor pentru fiecare sarcina de lucru si afișarea pe harta a
coordonatelor sursa si destinație
1.2. Angajați – Aplicația Android
1.2.1. Înregistrarea coordonatelor GPS si transmiterea lor pentru a fi procesate
1.2.2. In cazul in care datele înregistrate nu sau putut transmite sa se salveze pentru
a fi reîncercat ulterior
2. Gestiunea res urselor flotei
2.1. Adăugarea unui vehicul nou in flota si asignarea unui angajat responsabil
2.2. Listarea tuturor vehiculelor unui administrator cu detalii despre acestea si numele
angajatului responsabil
2.3. Modificarea datelor unui vehicul
2.4. Afișarea unei liste cu det alii despre toți angajați unui administrator
2.5. Adăugarea de noi angajați
2.6. Modificarea datelor unui angajat
3. Gestiunea sarcinilor de lucru
3.1. Angajați – Aplicația web
3.1.1. Listarea sarcinilor de lucru pentru angajați cu opțiune de filtrare după stare
3.1.2. Modificare stării unei sarcini de lucru din sarcina noua in sarcina in curs de
finalizare si din sarcina in curs de finalizare in sarcina finalizata
3.2. Administratori – Aplicația Web
3.2.1. Adăugarea de sarcini de lucru pentru un angajat cu specificare
coordonatelor pentru sursa si d estinația transportului
3.2.2. Afișarea detaliilor despre o sarcina de lucru specificata. Detaliile conțin date
despre angajatul responsabil, sursa si destinația afișate pe harta si de asemenea
toate coordonatele înregistrate de la începutul pana la finalizarea s arcinii de lucru.
3.2.3. Listarea tuturor sarcinilor pentru un administrator si opțiune de căutare in
starea sarcinilor si după angajatul responsabil pentru transport
4. Componenta de alertare
4.1. Primirea de alerte in timp real pe aplicația Android
4.2. Afișarea in timp re al a alertelor in aplicația Web
4.3. Listarea tuturor alertelor cu detalii despre fiecare in parte pentru administratori
52
Arhitectura Sistemului
Cele 3 componente ale sistemului: ap licația Web, aplicația Android ș i componenta centrală
(aplicația JAVA), sunt co nstruite pe baza arhitecturii din Figura 35 Arhitectura Sistemului de mai
jos.
Sistemul are ca și componentă principală o aplicație Software construită utilizând limba jul
de programare JAVA folosită ca ș i un servic iu Web. Este componenta centrală deoarec e
interacționează cu toate celelalte componentele ale sistemului.
Din aplicația Android se fac cereri HTTP către API -ul REST al serviciului Web pentru a
selecta și modifica date în baza de date. Aplicația se mai conectează la brokerul de mesaje
RabbitMQ u tilizând protocolul MQTT, prin această conexiune se transmit coordonatele
înregistrate dar și primirea de notificare la diferite evenimente din cadrul sistemului. Conexiune
MQTT către RabbitMQ fiind „full -duplex” la fel ca și conexiunea prin WebSocket din aplicația
Web.
Datele transmise de aplicația Android către RabbitMQ prin MQTT sunt transmise apoi
către aplicația JAVA utilizând protocolul AMQP pentru a fi salvate în baza de date NoSQL
Cassandra dar și prin STOMP către aplicația WEB dacă este conec tat vreun utilizator care ar trebui
să primească mesajul. STOMP (Simple Text Oriented Message Protocol) este un protocol suportat
de către mai mulți brokeri de mesaje inclusiv de RabbitMQ și poate fi folosit peste protocolul
WebSocket.
Aplicația Web c omunică cu aplicația centrală utilizând protocoalele HTTP și WebSocket.
Prin HTTP se fac diferite cereri pentru a selecta, modifica și însera date în bazele de date. Prin
WebSocket aplicația poate primi și afișa diferite mesaje în timp real dar și pentru a trimite mesaje
către alți utilizatori ai sistemului. Conexiunea prin WebSocket se realizează utilizând serviciul
Web dar se face și o conexiune cu brokerul de mesaje RabbitMQ, serviciul acționând că și un
„proxy server”. De exemplu la trimiterea unui mesa j aceasta se trimite către punctul de
comunicație ale serviciului Web și aceasta trimițând mai departe către RabbitMQ că apoi să fie
transmis tuturor utilizatorilor eligibili pentru a primi mesajul.
Clusterul de Cassandra este folosit pentru a salva toat e datele înregistrare de către
aplicațiile folosite de angajați iar baza de date relațională MySQL este folosite pentru a stoca date
precum: utilizatorii sistemului, sarcinile de lucru, flota de vehicule.
53
Figura 35 – Arhitectura sistemului
54
Prezentarea implementării funcționalităților sistemului
Transmiterea mesajelor
În transmiterea mesajelor broker -ul mesaje RabbitMQ deține un rol central urmat de o
aplicație Java ce funcționează ca un proxy între client și RabbitMQ, clientul fiind reprezentat de o
aplicație Web. Mesajele sunt transmise între componentele sistemului prin trei protocoale:
1. MQTT pentru comunicația între aplicația Android și RabbitMQ .
2. STOMP peste WebSocket între aplicația Web și RabbitMQ
3. AMQP între aplicația Java și RabbitMQ
Broke r-ul de mesaje RabbitMQ deține mai multe responsabilități în transmiterea mesajelor
precum:
1. Rutarea mesajelor către diferite cozi de mesaje
Figura 66 – Arhitectura transmiterii de mesaje
55
2. Stocarea mesajelor în cozi care pot fi configurate să fie persistente astfel la repornirea
brokerului mesajele să nu se piardă
3. Transformarea mesajele între cele trei protocoale
Rutarea mesajelor se realizează după modelul publish -subscribe și filtrarea mesajelor este
realizată după subiect. În cadrul sistemului se transmit mesaje pentru două subiecte:
„user. *.employee.* .task.logs ” – subiectul pentru mesajele ce conțin coordonatele GPS
înregistrate
„user.*.alerts ” – subiectul pentru alertele trimise la diferite evenimente din sistem
Mesajele cu coordonatele GPS înregistrate de către aplicația Android sunt transmise prin
MQTT către RabbitMQ cu un subiect de forma : user.admin_id.employee.angajat_id.task.logs
unde admin_id reprezintă identificatorul unic al administratorului de flotă pentru angajatul
autentificat și angajat_id reprezintă identificatorul angajatului.
Odată a junse mesajele în RabbitMQ aceste vor fi transmise către cozile de mesaje ale
clienților ce se potrivesc subiectului trimis în antetul mesajului. Aplicația Java se conectează la
RabbitMQ cu interes pentru topicul user. *.employee.*.task.logs ceea ce însemnă că toate
mesajele trimise indiferent de identificatorul administratorului și al angajatului vor ajunge să fie
procesate de către aplicație.
Administratori de flotă în cadrul aplicației Web se înscriu prin WebSocket și STOMP
pentru două tipuri de subiect e: user.admin_id.employee.*.task.logs unde admin_id reprezintă
identificatorul administra torul autentificat în aplicație, pentru acest tip de subiect se vor primi toate
mesajele angajaților administratorului autentificat. Al doilea tip de subiect este de f orma
user.admin_id.employee. angajat_id .task.logs pentru care se vor primi mesaje de la un singur
angajat.
56
Figur a 37 – Rutare mesajelor cu coordonate GPS
În „figura 37 Rutarea mesajelor cu coordonate GPS ” de mai sus este prezentată rutarea
mesajelor trimi se de trei angajați: A, B și C și doi administratori D și E cu precizarea că
administratorul D este conectat de pe două dispozitive. Fiecare angajat va trimite un mesaj cu un
subiect folosind identificatori specifici și se poate vizualiza pe imagine. În ur ma rutării mesajelor
de către RabbitMQ coada de mesaje asociată aplicație i Java va conține mesajele A,B,C deoarece
toate subiectele din mesaje se potrivesc cu user. *.employee.*.task.logs . Administratorul D de
conectat pe primul dispozitiv va primi mesajele A și B iar pe cel de al doilea dispozitiv va primi
doar mesajul B deoarece subiectul pentru care este interesat se potrivește doar cu mesajele trimise
de angajatul B. Administratorul E va primi doar mesajul C deoarece există doar un angajat ce
trimite mes aje cu subiectul ce conține identificatorul acestuia.
Toate mesajele sunt transmise către toți utilizatori imediat ce sunt rece pționate fără ca
utilizatorii să facă vreo acțiune în aplicații. Toate cozile de mesaje pentru utilizatorii din figura de
mai su s nu sunt persistente ceea ce însemnă că dacă nu există un utilizator conectat acesta nu se
stochează în coadă. În schimb coada de mesaje pentru aplicația Java este persistentă și înseamnă
ca chiar dacă nu există nici un proces conectat la coadă aceste a vor fi stocate până când vor
procesate.
57
Cel de al doilea tip de subiect folosit în cadrul sistemului de alertare funcționează pe
aceleași principiu de rutare folosind subiecte de tipul user.*.alerts .
Serviciul Web
Componenta centrala din cadrul sistemul ui este un serviciu Web realizat cu Java si framework –
ul Spring. Spring este una dintre cele mai populare librarii Java, cu sursa deschisă sub o licență
Apache, cu o comunitate foarte mare și reprezintă o alternativă pentru platforma Java EE (Java
Enterpri se Edition). Spring conform [ 22] are o construcție m odulară, iar modulele folosite în
construcția aplicației centrale a sistemului sunt:
Spring Core Container ce reprezintă modulul de baza al framework -ului
Inversion of control container pentru injectarea dependintelor
Spring Web pe modelul MVC(Model -View -Controller) folosit pentru a expune un REST
API
Data Acess pentru accesul la bazele de date MySQL si Cassandra și de asemenea folosește
ORM(Object -Relational Mapping)
Security folosit pentru securizarea accesului la d ate
Spring AMQP folosit pentru conectarea la RabbitMQ prin protocolul AMQP
Spring WebSocket este modulul ce oferă suport pentru folosirea protocolului STOMP peste
WebSocket si poate fi configurat sa funcționeze cu RabbitMQ conform [ 23]
Aceasta componentă critică a sistemului îndeplinește următoarele funcționalități:
Oferă un API pentru manipularea datelor de către celelalte componente
Folosește MySQL pentru stocarea datelor esențiale ale sistemului. Date precum: utilizatori,
vehicule
Acționează ca un Proxy intre apli cația Web si RabbitMQ
Figura 38 – Rutarea alertelor
58
Procesează și s alvează toate coordonatele transmise de către aplicațiile angajaților în baza
de date NoSQL Cassandra.
Structura bazei de date MySQL
Baza de date relațională MySQL este folosită pentru stocarea datelor precum: utili zatorii
sistemului, vehiculele flotei, sarcinile de lucru. Structura tabelelor și relațiile între acestea sunt
prezentate î n figura de mai jos.
Tabela users reprezintă utilizatorii sistemului ș i conține date precum: identificatorul unic,
numele, adresa d e email și parola folosite pentru autentificare în sistem. Coloana admin_id este
folosită pentru a crea o relație 1 la 1 cu ea însăși. Înregistrările din tabelă cu coloana admin_id n e
setată reprezintă un administrator de flotă , iar înregistrările c e au o valoare sunt angajați.
Administratorul lor se poate afla din aceeași tabelă căutând după câmpul id cu valoare din
admin_id.
Figura 39 – Structura bazei de date MySQL
59
Tabela users are o relație de tip ”Many To Many” cu tabela roles folosind tabela de legătură
user_roles. În cadrul tabelei roles se regăsesc rolurile care le pot avea utilizatorii în sistem folosite
pentru a restricționa accesul utilizatorilor la diferite resurse ale sistemului. Momentan în sistem
sunt doar două roluri ș i anume: ROLE_USER pentru angajați și ROLE_ADMIN pentru
administr atori de flote auto. Tabela user_roles conține doar identifica torii unici din tabelele roles
și users având rol de legătură între cele două tabele.
Cars este tabela ce conține datele despre vehicule având următoarele coloane: num ărul de
înmatriculare, mod elul ș i marca vehiculului, owner_id reprezentând identificatorul unic al unui
administrator și coloana driver pentru angajatul ce folosește vehiculul. Tabela având o asociere de
tipul „Many To One” pentru coloa na owner_id ceea ce semnifică că un administra tor poate avea
mai multe vehicule și o asociere de tip „One To One” pentru angajați.
Tasks reprezintă tabela cu sarcinile de lucru pentru angajați, având o asociere „Many To
One” cu tabe la users. Coloanele source_lat ș i source_lon respectiv destination_l at și
destination_lon reprezintă coordonatele GPS de unde un transport începe și unde trebuie livrat iar
start_date și end_date reprezintă datele la care o sarcină de lucru a fost preluată de un angajat și
data la care a fost finalizată. Coloană status est e folosită pentru a stoca starea unei sarci ni de lucru
și poate fi: nouă, î n curs de finalizare și finalizată.
Tabela alerts conține alertele la diferite evenimente din sistem ș i conține un titlu, un mesaj
și data la care sa creat alerta. Există și o asoc iere de tipul „Many To One” cu tabela users, un
utilizator având mai multe alerte.
Api-ul REST
REST( Representational State T ransfer ) este o modalitate de a asigura interoperabilitatea
între sistemele informatice de pe Internet. Serviciile Web compatibile cu REST permit sistemelor
solicitante să acceseze și să manipuleze reprezentările textuale ale resurselor web folosind un set
uniform și predefinit de operații fără stare . Alte forme de serviciu Web există, care expun propriile
seturi de operații arbitrar e, cum ar fi WSDL și SOAP.
Într-un serviciu Web REST , „solicitările făcute către un URI al unei resurse vor genera un
răspuns care ar putea fi în XML, HTML, JSON sau în alt format definit ” conform [ 8]. Răspunsul
poate confirma că s -a făcut o modificare a resursei stoca te și poate furniza legături hipertext la alte
resurse sau colecții de resurse conexe. Folosind HTTP, după cum este cel mai frecvent, „tipul de
60
operațiuni disponibile include cele predefinite de verbele HTTP GET, POST, PUT, DELETE și
așa mai departe ” [1].
„Exist ă șase constrângeri car e definesc un sistem REST . Aceste constrângeri
restricționează modurile în care serverul poate procesa și răspunde solicitărilor clientului, astfel
încât, prin operarea în cadrul acestor constrângeri, serviciul câștigă proprietăți ne funcționale
dorite, cum ar fi performanța, scalabilitatea, simplitatea, modificabilitatea, vizibilitatea,
portabilitatea și fiabilitatea ” [9] . Dacă un serviciu încalcă oricare dintre constrângerile necesare ,
nu poate fi considerat REST .
Constrângerile oficiale REST sunt după cum urmează:
1. Client – server
2. Stateless: fără stare
3. Cacheable
4. Layered system: folosit pentru balansarea cererilor
5. Uniform Interface – identificarea resurselor prin URI
6. Code on demand (optional) – folosit pentru executa pe server cod trimis d e către client.
API-urile de servicii web care respectă constrângerile arhitectural e REST sunt denumite API
REST. API -urile REST bazate pe HTTP sunt definite cu următoarele aspecte :
Un URL de bază precum http://a pi.car -tracking.com
Verbe HTTP standard: GET, PUT, POST, DELETE
În următorul tabel se arată modul în care metodele HTTP sunt utilizate în mod obișnuit într -un
API REST :
URL GET PUT POST DELETE
http://api .car-
tracking.com/users Returnează lista
de utilizatori Înlocuiește
toate colecția de
utilizatori cu o
alta colecție Creează un nou
utilizator Șterge toți
utilizatorii
http://api.car –
tracking.com /users/1 Return ează
utilizatorul cu
identificatorul 1 Înlocuiește
utilizatorul
adresat sau dacă
nu există este
creat În general nu
este folosit Șterge
utilizatorul
adresat
61
Serviciul REST implementat cu ajutorul Java folosește protocolul HTTP pentru
comunicație și retur nează în urma cererilor primite un răspuns sub formă de JSON. Pentru cererile
de tip POST sau PUT în care clientul transmite date către server acestea sunt transmise tot în
format JSON. Serviciul expune funcționalități pentru celelalte componente ale siste mului în
principal pentru manipularea datelor din bazele de date și acestea sunt prezentate în tabelul de mai
jos.
În cadrul tabelului de mai jos se face următoarea convenție, datele între acolade din cadrul
URL -lui reprezintă variabile și reprezintă id entificatorii unici din baza de date pentru fiecare
resursă.
Metoda HTTP URL Detalii
GET /api/users/{userid} Returnează detalii pentru utilizatorul
specificat in URL prin variabila userid
DELETE /api/users/{userid} Șterge utilizatorul specificat
GET /api/users/{userid}/cars Returnează o lista cu toate vehiculele
utilizatorului cu id -ul specificat in URL
GET /api/cars/{car -id} Returnează detaliile despre un vehicul
POST /api/users/{userid}/cars Creează o noua înregistrare pentru
vehicule asociate util izatorului
specificat. Datele pentru noul vehicul
sunt trimise sub format JSON in
conținutul cererii POST
PUT /api/users/{userid}/cars/{car -id} Modifica datele vehiculului identificat
prin id -ul specificat in URL.
GET /api/alerts/search Returnează o lis tă de alerte cu detalii
despre fiecare in parte. În cadrul URL –
ului se pot transmite diferiți parametrii
pentru filtrarea alertelor
GET /api/users/{userid}/employees Rezultatul cererii este o listă de
angajații pentru administratorul
specificat în URL
POST /api/users/{userid}/employees Adaugă un nou angajat pentru un
administrator. Datele angajatului sunt
trimise în conținutul cererii.
62
POST /api/employees/{employeeId}/tasks Adaugă o nouă sarcină de lucru pentru
un angajat. Datele pentru sarcina de
lucru sunt trimise în conținutul cererii.
GET /api/tasks/search Returnează o listă de sarcinii de lucru
cu detalii despre fiecare. În cadrul URL –
ului se pot transmite diferiți parametrii
pentru filtrare
GET /api/tasks/{id} Returnează detaliile despre o sarcină
de lucru identificată prin parametrul
transmis în URL
PUT /api/employees/{employeeId}/tasks/{taskId} Modifica datele unei sarcini de lucru
GET /api/tasks/{id}/logs Returnează o listă cu toate
coordonatele înregistrate pentru un
transport de la începere până la
finalizare
De exemplu pentru URL -ul /api/users/{userid}/cars cu variabila userid egală cu 6 o cerere
HTTP de tip GET are ca rezultat un JSON ce conține o listă de vehicule asociate utilizatorului
identificat prin identificatorul unic 6, în cad rul imaginii de mai jos se poate vedea răspunsul.
Figura 40 – Cerere GET pentru listă vehicule
63
Pentru cererile de tip POST sau PUT în care se adăugă sau se modifică înregistrări din baza
de date, datele transmise sunt în format JSON și se regăsesc în conținutul cererii trimise. În figura
5 de mai jos este o cerere de tip POST către URL -ul /api/users/ 6/employees și adaugă un angajat
nou pentru administratorul identificat prin id -ul 6.
Figura 41 – Cerere POST pentru creare unui nou angajat
Fiecare tabelă din MySQL ș i Cassandra are corespondent un obi ect în Java, conversia
dintre datele din baza de date ș i obiectele Java fiind realizată de către Spring prin modulul de
ORM. Serviciul REST comunică prin date în format JSON , acestea sunt transformate în obiecte
de Java cu ajutoru l unei librării specifice din ea integrată în Spring, conversia este bidi recțională
funcționând ș i din obiect Java în JSON.
64
Implementarea este bazată pe modelul MVC iar schem a simplificată este prezentată î n
figura 6 în care pentru o cerere HTTP datele sunt transformate din JSON î n obiect Java după care
este invocat controller -ul în conformitate cu cererea HTTP. În cadrul controller -ului se procesează
date primite, interacționează cu bazele de date și întoarce un obiect Java care apoi este transformat
în JSON si transmis clientului .
Figur a 42 – Arhitectură cereri HTTP
Toate cererile către serviciul REST sunt securizate utilizând o teh nologie bazată pe token.
Dacă o cerere nu conține î n antet -ul HTTP un token aceasta este refuzată și clientul primește un
răspuns de eroare și un status precum că nu are acces. Tehnologia folosită pentru securizarea api –
ului este JWT(JSON Web Tokens), „JWT este un standard deschis care definește un mod compact
și autonom pentru transmiterea sigură a informațiilor între diferite părți ca obiect JSON ” [28].
Aceste informații pot fi verificate și pot fi sigure deoarece sunt semnate digital.
Un token JWT este alcătuit dintre părți separate prin caracterul „ . ” și conține conform
[21]:
1. Antet ce conține token -ul și algoritmul de hashing
2. Conținut ce poate conține diferite da te despre utilizatori
3. Semnătură reprezentând aplicarea algoritmului de hashing pentru conținut
împreună cu antetul
În procesul de autentificare, atunci când administratorul sau angajatul se autentifică cu
succes prin utilizarea adresei de email si a parol ei, un JWT va fi returnat și va salvat în spațiul de
memorie al browser -ului pentru aplicația Web respectiv în spațiul de stocare al telefonului pentru
aplicația Android. Această abordare o înlocuiește pe cea tradițională a creării unei sesiune pe server
și returna re unui cookie care semnifică că starea este ținută pe server și încalcă principiile unui
serviciu REST și de asemenea nu ar funcționa pe aplicația android unde nu se pot folosii cookie –
urile.
65
Cu token -ul salvat la orice c erere HTTP trimisă se ata șează î n antet și o parte cu token -ul
JWT. Acesta este un mec anism de autentificare fără stare, deoarece starea utilizatorului nu este
salvat ă niciodată în memoria serverului. Resursele protejate ale serverului vor verifica dacă un
JWT valabil se găsește î n antetul Autorizare și dacă este prezent, utilizatorul va avea acces la
resurse protejate. Deoarece JWT -urile sunt autonome, toate informațiile necesare sunt acolo,
reducând necesitatea de a interoga baza de date de mai multe ori.
Figura 43 – Procesul de autentificare utilizând JWT
Sursa: https://jwt.io/introduction/
Salvarea coordonatelor în Cassandra
Toate coordonatele GPS transmise de aplicațiile angajaților sunt salvate într -un cluster de
trei noduri de Cassandra . Cassandra a fost aleasă ca modalitatea de stocare a datelor deoare ce este
o bază de date construită pentru a putea gestiona foarte multe scrieri , iar sistemul poate produce
foarte multe scrieri. Fiecare angajat generează două înregistrări pe minut , iar odată cu creșterea
sistemului o bază de date relațională ar fi depăși tă. În tabelul de mai jos înregistrările pe minute
sunt calculate utilizând formula: numărul de administratori * numărul de angajați pentru fiecare
administrator * 2.
66
Administratori
de flotă Angajați pentru
fiecare
administrator Înregistrări
generate pe
minut Înregistrări
generate pe zi
10 25 500 720000
100 25 5000 7200000
500 25 25000 36000000
1000 25 50000 72000000
Înregistrările transmise către RabbitMQ sunt stocate în coadă persistentă de unde sunt
preluați de consumatorii din Java. Datorită numărului mare de scriere sunt folosite mai multe
procese concurente de pre luare a mesajelor din RabbitMQ și salvate în Cassan dra, consumatori i
din coadă pot fi distribuiți ș i pe mai multe servere.
Baza de date creată are un factor de replicare de 2 ceea ce înseamnă ca fiecare înregistrare
se află pe două din cele 3 noduri ale sistemului garantând înalta disponibilitate a sistem ului. Datele
sunt salvate într -o singură tabelă cu denumirea de task_logs și are următoarele coloane:
task_id ce reprezintă identificatorul unic a unei sarcini de lucru din MySQL
log_time pentru timpul la care sa făcut înregistrarea
car_id reprezintă ident ificatorul mașinii asociate angajatului la momentul
înregistrării
employee_id reprezintă identificatorul angajatului
latitude
longitude
speed
altitude
Figura 44 – Fluxul salvării datelor în Cassandra
67
Tabela are cheia primară , identificatorul unic al sarcinii de lucru fiind de asemenea și
cheia de r ând. Timpul la care a fost făcută înregistrarea este folosit pentru o cheie de grupare a
datelor intern e, numele coloanelor fiind stocate și cu valoarea acestei coloane.
De exemplu o inserare a datelor pentru sarcina de lucru A la momentul de timp 0 și la
momentul de timp 1 se vor regăsi î n Cassandra ca și două înregistrări diferite în cadrul aceluiași
rând, dacă nu se folosea cheia de grupare în tabelă se regăsea doar înregistrarea de la momentul
de timp .
Figura 46 – Înregistrări de date din Cassandra Figura 45 – Structura bazei de date din Cassandra
68
Aplicația Web
Aplicația Web destinată folosi ri de către administratori de flotă oferă acestora o interfață
grafică ușor de utilizat pentru gestiunea și monitorizarea flotei. Aplicația este construită utilizând
limbajul de programa re JavaScript ș i interfață creată cu HTML și CSS , iar principalele teh nologii
sunt:
AngularJS 1
Bootstrap
StompJS
jQuery
Google Maps
AngularJS conform [ 30] este un cadru de lucru JavaScr ipt cu sursă deschisă menținut î n
principal de către Google și este folosit pentru dezvoltare aplicațiilor web de tip SPA(Single
Page A pplication) . Este un cadru de lucru pentru partea de client de tip MVC (Model -View –
Controller) și simplifică dezvoltarea și testarea aplicațiilor.
O aplicație de o singură pagină (SPA) este o aplicație web sau un site web care se potrivește
pe o singură pagină Web, cu scop ul de a oferi o experiență de utilizator similară cu cea a unei
aplicații desktop. Într-o aplicație SPA toate resursele necesare(JavaScript, HTML, CSS) sunt
preluate cu o singură încărcare de pagină și sunt adăugate resurse dinamic ca răspuns la acțiunile
utilizatorului.
Bootstrap este un cadru de lucru web gratuit și open -source pentru dezvoltarea interfețelor
grafice a aplicațiilor web. Acesta conține șabloane de design HTML și CSS pentru tipografii,
formulare, butoane, navigație și alte componente de in terfață, precum și extensii JavaScript
opționale. Spre deosebire de multe cadre web, se referă numai la dezvoltarea pentru partea de
client.
StompJS este o librărie JavaScript folosită pentru transmiterea mesajelor prin protocolul
STOMP dintr -o aplicație web.
Autentificare
Aplicația folosește în principal serviciul web expus pentru a implementa funcționalitățile
necesare administratorilor de flote auto, comunicația realizându -se prin cereri HTTP din
JavaScript.
69
Accesul la serviciul web fiind restr icțion at utilizatorii trebuie să se autentifice utilizând o
adresa de email și o parolă moment în care se face o cerere HTTP pentru verificarea datelor , iar în
caz de succes se va primi ca răspuns un token JWT. Token -ul primit se va salva la client în browser
pentru a fi folosit la următoarele cereri HTTP.
Figura – 47 Cerere HTTP pentru autentificare
Monitorizare
Rolul principal al aplicației este acela de a afișa în timp real locațiile GPS a angajaților pe
o hartă. Hârțile sunt realizate utilizând librăria JavaScript pentru Google Maps. Locațiile
angajaților sunt primite imediat ce sunt transmise de către aplicațiile Android, recepționarea
mesajelor fiind realizată cu librăria JavaScript StompJS.
La încărcarea paginii web principale se face o conexiune pr in STOMP peste WebSocket
cu aplicația Java care la rândul ei se conectează la broker -ul de mesaje RabbitMQ. După realizarea
conexiunii aplicația se abonează la subiectul cu care se transmite coordonatele angajaților și la
subiectul pentru alerte. După abon are orice mesaj transmis este primit fără ca utilizatorul să facă
vreo acțiune.
În figura de mai jos este prezentat codul JavaScript pentru conectarea cu RabbitMQ prin
aplicația Java, primirea și trimiterea de mesaje. Metoda de abonare primește ca paramet ru un
subiect și o altă metodă care va fi apelată atunci când un mesaj este primit, de exemplu aceea
metodă actualizează locația unui angajat pe hartă. Toate mesajele trimise ș i primite sunt transmise
în format JSON.
70
Figur a 48 – Codul JavaScript pentru trimiterea/recepționarea de mesaje
În cadrul aplicației administratorii de flotă pot vizualiza locațiile tuturor angajaților care sunt
angajați sau doar pentru un angajat specific. În imaginea de mai jos este prezentată harta cu
locațiile angajaților unui administrator. Fiecare marker de pe hartă reprezintă un angajat iar
deasupra acestuia este numele angajatului. Poziția fiecărui marker este actualizată atunci când un
mesaj cu noile coordonate este primit.
71
Primirea și afișarea alertelor
Pentru prim irea alertelor se folosește aceeași tehnică ca și la primirea coordonatelor
angajaț ilor. La primirea unei alerte în cardul interfeței este incrementat numărul de alerte noi
primite de către un utilizator.
Un administrator de flotă poate primi două tipuri de alerte: o alertă atunci când un task a
fost început de către un angajat și o alertă atunci când un angajat a finalizat un task. Un
administrator poate vedea ultimele alerte în partea de sus a aplicației sau într -o secțiune specială
unde toate alertele s unt listate împreună cu detaliile despre acestea.
Figura 49 Monitorizarea angajaților
Figura 50 – Numărul de alerte al unui administrator
72
Alertele inițiale sunt preluate în urma unei cereri HTTP către serviciul web care întoarce
un răspuns JSON cu lista de alerte pentru un administrator apoi datele sunt procesate și afișate în
interf ață.
Gestiunea resurselor flotei
Resursele flotei pentru un administrator sunt reprezentate de: angajați, vehicule și sarcinii
de lucru. Pentru fiecare resursă un administrator poat e adaugă , modifica și vizualiza o listă cu
fiecare în parte. Aceste acț iuni sunt realizate prin cereri HTTP către serviciul web cu date în
format JSON pentru a fi adăugate sau modificate și în cazul afișărilor sunt primite date în format
JSON apoi interpretate și afișate. Figura 51 – Afișarea alertelor
Figura 5 2 –Interfața grafică pentru gestionarea vehiculelor
73
În „Figura 52 –Interfața grafică pentru gestionarea vehiculelor ” este prezentată interfața
grafică pentru gestiunea vehiculelor din flotă. În partea de jos a paginii sunt listate toate
vehiculele unui administrator împreună cu numele angajatului care este responsabil. Pentru
fiecare vehicul există opțiunea de a modifica datele. În partea de sus a pagin ii este un formular cu
ajutorul căruia se poate adăugă vehicule sau se modifică de datele pentru un vehicul existent.
Pagina de gestiune angajaților este foarte similară cu cea de vehicule doar că formularul
este adaptat pentru datele necesare unui angaja t, iar în listare există un buton pentru a urmări
locația angajatului.
Pentru pagina de sarcinii de lucru sunt implementate mai multe funcționalități pentru a
ușura munca administratorilor de flotă. Există posibilitatea de a căuta sarcinii de lucru după:
1. Starea sarcinii de lucru
2. Identificatorul unic al angajatului asociat sarcinii de lucru
Figura 53 – Interfața grafică pentru căutare și listarea sarcinilor de lucru
Pentru fiecare task afișat există mai multe acțiuni care te duc către diferite secțiuni di n
aplicație pentru monitorizarea locației sau afișarea sarcinii de lucru mai detaliat. Afișare detaliată
reprezintă detalii despre angajatul res ponsabil, informații despre data de început, finalizare și
afișare a pe hartă a sursei, destinație și a tuturor c oordonatelor înregistrate în timpul execuției.
74
Pentru adăugarea unei noi sarcini de lucru există un formular, folosit și pentru
modificarea datelor unui task existent în care un administrator trebuie să selecteze data limită
până când transportul trebuie s ă se înche ie, să asocieze un angajat și să seteze pe o hartă cu
ajutorul unor markere coordonatele GPS pentru sursă și destinație.
Aplicația Android
Aplicația Android destinată folosirii de către angajați este realizată utilizând limbajul de
programar e Java și din punct de vedere al funcționalităților este mai simplă decât celelalte
componente ale sistemului. Ca și aplicația web comunică cu serviciul web prin cererii HTTP și
date în format JSON.
Aplicația implementează următoarele funcționalității:
Autentificarea
Listarea sarcinilor de lucru filtrate după stare
Vizualizarea pe hartă a destinației, sursei și a locației curente
Actualizarea stării unei sarcini de lucru
Figura 54 – Formular sarcina de lucru
75
Transmiterea coordonatelor GPS
Primirea de alerte în timp real
Autentificarea angaj aților în aplicație se realizează introducând adresa de email și parola
după care se face o cerere HTTP pentru a fi verificate cu da tele din baza de date. Dacă datele
de autentificare sunt corecte se va primi ca și răspuns un token JWT care este apoi folos it în
alte cereri HTTP pentru a accesa date.
După autentificare angajații pot vizualiza sarcinile de lucru pentru care sunt resp onsabili.
Pentru fiecare sarcină de lucru există două butoane după cum se vede în figura de mai jos folosit e
pentru: de modi ficare stării ș i pentru vizualizarea detaliilor sarcinii de lucru.
Butonul de modificare a stării unei sarcini de lucru poate fi folosit pentru a marca o sarcină
de lucru ca fiind în lucru ca în figura de mai sus sau pentru a finaliza o sarcină de lucru.
Actualizarea stării în baza de date se face printr -o cerere HTTP către serviciul web cu
identificatorul unic al sarcinii de lucru și starea corespunzătoare.
Butonul „Vezi destinație” are ca acțiune afișarea unei noi pagini din aplicație unde se pot
vedea coordonatele GPS pentru destinație, sursă și locația curentă a angajatului.
Figura 55 – Listarea sarcinilor de lucru
76
Harta este realizată cu ajutorului librăriei Google Maps pentru Android iar marker -ul de
culoare roșie din figura de mai jos reprezintă destinația sarcinii de lucru. Marker -ul de culoare
verde reprezintă sursa de unde obiectului ce trebuie transportat , iar cel de culoare mov reprezintă
locația curentă a angajatului . Utilizând Google Maps [31] se pot afla detalii pentru a ajunge la
destinație sau sursă precum: cel mai rapid tras eu, dist anța și timpul estimat.
Utilizând meniul din stânga sus al aplicației angajații pot sel ecta ce sarcinii de lucru vor să
vizualizeze în funcție de stare și anume: sarcinii de lucru noi, sarcinii de lucru în curs de finalizare
și sarcinii de lucru finali zate.
Pentru transmiterea și recepționarea de mesaje sa folosit un serviciu Android în cadrul
căruia se realizează o conexiune bidirecțională prin MQTT cu broker -ul de mesaje MQTT.
Figura 56 – Afișarea detaliilor unei sarcini de lucru pe hartă
77
Un serviciu Android este o c omponentă a aplicațiilor ce este folosit „pentru a efectua
operații îndelungate fără a fi nevoie de interacțiunea utilizatorilor ” conform [ 32]. Serviciul rulează
în fundal și nu afectează utilizarea aplicației de către angajați.
La instalarea aplicației serviciul este pornit și se creează conexiunea cu brokerul de mesaje,
conexiune ce va rămâne deschisă atâta timp cât telefonul are o conexiune la internet. După
pierderea conexiunii la internet se va încerca reconectarea cu brokerul de mesaje.
Tot în cadrul serviciului Android la fiecare 30 de secunde se preiau co ordonatele utilizând
GPS-ul telefonului. Dacă în aplicație este autentificat vreun angajat coordonatele sunt publicate
prin MQTT cu subiectul specific , iar în cazul în care mesajul nu poate fi publicat din diverse motive
acesta este stocat într -o coadă în memorie. După restabilirea conexiunii cu broker -ul de mesaje
toate mesajele sunt trimise.
Conexiunea MQTT din cadrul serviciului este folosit și pentru primirea de alerte din cadrul
sistemului. Angajații primesc un singur tip de alertă, cea de la adăuga rea unei sarcini de lucru
pentru care sunt responsabili. Alertele sunt primite fără interacțiunea angajaților atâta timp cât sunt
conectați la internet. În figura de mai jos este afișată o a lertă precum că o sarcină de lucru i -a fost
asignată iar la click pe alertă se va deschide aplicația cu fereastra în care sunt listate sarcinile de
lucru noi.
Figura 57 – Alerte Android
78
Concluzii
În cadrul acestui studiu s -a urmărit dezvoltarea unui sistem de monitorizare și gestiune în
timp real al unei flote auto care să permită companiilor de transport, curierat, serviciile de teren o
gestionare mai eficientă și maximizarea profitului. O funcționalitate importantă dezvoltată în
cadrul sistemului este cea de alertare în timp real a utilizatorilor sistemului astfel angajații știu
când au un nou t ransport de efectuat sau administratorii pot vedea data la care un transport a fost
finalizat.
Pentru achiziția de date legate de poziționarea vehiculelor s -a folosit un telefon cu sistem
de operare Android spre deosebire de alte sisteme ce folosesc apara te speciale pentru urmărirea
GPS. Această soluție este avantajoasă , deoarece nu necesită costuri suplimentare legate de
achiziția unor aparate destul de scumpe și nu este nevoie nici de instalare sau configurare. La
momentul actual aparatele GPS specializa te sunt mai precise față de un telefon , dar nu este
necesară măsurarea coordonatelor foarte precis.
Sistemul oferă administratorilor posibilitatea de a urmări în timp real, fără vreo acțiune
din partea lor, poziționarea pe o hartă a tuturor angajaților sau pentru un angajat specific. Această
monitorizarea în timp real este realizată cu ajutorul RabbitMQ care primește mesaje prin
protocolul MQTT de la angajații apoi transmite prin protocolul STOMP către administratori
abonați pentru recepționarea mesajelo r după care coordonatele GPS al angajatului sunt
actualizate în browser fără acțiune utilizatorului.
Datele înregistrate sunt stocate într -o bază de date NoSQL , deoarece volumul acestora
este foarte mare iar o bază de date relaționa lă nu ar face față la un moment dat. Cu datele salvate
administratorii pot vedea pe hartă tot parcursul pentru o sarcină de lucru.
O altă parte a sistemului la fel de importantă pentru administratori de flotă este cea de
gestiune ușurând astfel transmiterea comenzilor de luc ru către angajați. O comandă de l ucru
având o sursă de preluare a unui transport, o destinație dar și o dată limită până când trebuie
finalizată. Gestiunea flotei mai reprezintă și managementul complet al angajaților și a
vehiculelor.
Sistemul a fost dez voltat cu ultimele tehnologii disponibile precum: RabbitMQ, Spring,
AngularJS, Cassandra, StompJS dar și protocoale de comunicație ca: MQTT, AMQP, STOMP,
WebSocket ce facilitează transmiterea mesajelor între diferite componente ale sistemului. Toate
aceste tehnologii au fost alese ca sistemul să poată gestiona un trafic foarte mare de utilizatori, de
79
mesaje doar adăugând resurse hardware fără a modifica arhitectura sistemului sau partea
software.
Pentru îmbunătățirea sistemului dezvoltat și pentru maximiza rea profitului companiilor
ce dețin flote auto se pot adăuga următoarele funcționalități:
Adăugarea unor senzori la vehicule pentru înregistrarea nivelului de combustibil,
temperatură, viteză care să comunice cu aplicația Android prin B luetooth și aceasta să
transmită datele înregistrate și afișarea acestora în diferite grafice pentru administratorii
de flotă
Generarea unor statistici precum numărul de sarcini de lucru finalizate de un angajat,
numărul de kilometri parcurși de un vehicul/angajat/sarcină de lucru
Dezvoltarea unei aplicații pentru sisteme mobile bazată pe sistemul de operare IOS
Verificarea dacă data de sfârșit a unei sarcini de lucru a fost depășită și alertarea
administratorilor în caz afirmativ
80
Anexe
Anexa 1
Afișar ea conexiunilor din RabbitMQ și a cozilor de mesaje preluate din interfața grafică a
acestuia. Conexiunea prin protocolul STOMP este cea din browser a administratorului, prin
AMQP este aplicația Java iar prin MQTT este aplicația Android.
81
82
Anexa 2
Lista de clase Java folosite în dezvoltarea Api -ului, conexiunilor prin WebSocket și
salvarea datelor în Cassandra.
83
84
85
Anexa 3
Lista de clase din aplicația Android
86
Anexa 4
Codul Java folosit în aplicația Android pentr u conexiunea prin MQTT cu RabbitMQ și
primirea respectiv trimiterea de mesaje utilizând această conexiune.
package com.cosmin.cartracking.mqtt ;
import android.util.Log ;
import com.cosmin.cartracking.mqtt.listener.MqttListener ;
import com.cosmin.cartrack ing.mqtt.model.RejectedMessage ;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken ;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended ;
import org.eclipse.paho.client.mqttv3.MqttClient ;
import org.eclipse.paho.client.mqttv3.MqttConnectOption s;
import org.eclipse.paho.client.mqttv3.MqttException ;
import org.eclipse.paho.client.mqttv3.MqttMessage ;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence ;
import java.util.ArrayList ;
import java.util.List ;
import java.util.Queue ;
import java.util.concurrent.ConcurrentLinkedQueue ;
public class Mqtt {
private final static String uri_dev = "tcp://192.168.100.4:1883" ;
private final static String uri = "tcp://35.189.207.159:1883" ;
private final static String username = "xxxxxxxxx ";
private final static String pass = "xxxxxxxxxxxx ";
public final static String TAG = "mqtt-client";
private MqttClient client ;
private MqttMessageFactory messageFactory ;
private boolean isConnected = false;
private Queue<RejectedM essage> rejectedMessageQueue ;
private List<MqttListener > subscriptions = new ArrayList <>();
public Mqtt() {
this.messageFactory = new MqttMessageFactory ();
rejectedMessageQueue = new ConcurrentLinkedQueue <>();
}
public void connect() {
if (isConnected ) {
return;
}
try {
String clientId = MqttClient .generateClientId ();
client = new MqttClient (uri, clientId , new MemoryPersistence ());
setMqttCallback ();
client.connect(getOptions ());
isConnected = true;
Log.d(TAG, "successful connected to mqtt server" );
} catch (MqttException e ) {
Log.d(TAG, "failed to connect to mqtt server" );
87
throw new RuntimeException (e);
}
}
public void publish(String topic , Object payload ) {
if (checkConnection (topic, payload)) {
return;
}
try {
client.publish(topic, messageFactory .create(payload));
Log.d(TAG, "successful publish to topic " + topic);
} catch (MqttException e ) {
Log.d(TAG, "Failed to publish to topic. Message: " + e.getMessage ());
addToRejectedQueue (topic, payload);
}
}
public void subscribe (MqttListener listener ) {
subscriptions .add(listener );
}
private boolean checkConnection (String topic , Object payload ) {
if (isConnected ) {
return false;
}
try {
Log.d(TAG, "connect ing…");
this.connect();
for (MqttListener listener : subscriptions ) {
client.subscribe (listener .getTopic (), listener );
}
flushRejectedQueue ();
return false;
} catch (RuntimeException e ) {
addToRejectedQueue (topic, payload);
return true;
} catch (MqttException e ) {
return true;
}
}
public void disconnect () {
if (!isConnected ) {
return;
}
try {
client.disconnect ();
isConnected = false;
} catch (MqttException e ) {
Log.d(TAG, e.getMessage ());
}
}
private void addToRejectedQueue (String topic , Object payload ) {
rejectedMessageQueue .add(new RejectedMessage (topic, payload));
}
private void setMqttCallback () {
client.setCallback (new MqttCallbackExtended () {
@Override
88
public void connectComplete (boolean reconnect , String serverURI ) {
flushRejectedQueue ();
}
@Override
public void connectionLost (Throwable cause ) {}
@Override
public void messageArrived (String topic , MqttMessage message ) throws Exception {
topic = topic.replace("/", ".");
for (MqttListener listener : subscriptions ) {
listener .messageArrived (topic, message);
}
}
@Override
public void deliveryCo mplete(IMqttDeliveryToken token ) {}
});
}
private void flushRejectedQueue () {
if (rejectedMessageQueue .isEmpty()) {
return;
}
Log.d(TAG, "flush rejected queue – contains " + rejectedMessageQueue .size() + "
messages" );
while (!rejectedMessageQueue .isEmpty()) {
RejectedMessage rejectedMessage = rejectedMessageQueue .poll();
publish(rejectedMessage .getTopic (), rejectedMessage .getPayload ());
try {
Thread.sleep(100);
} catch (InterruptedException e ) {
Log.e(TAG, e.getMessage ());
}
}
}
private MqttConnectOptions getOptions () {
MqttConnectOptions options = new MqttConnectOptions ();
options.setMqttVersion (MqttConnectOptions .MQTT_VERSION_3_1_1 );
options.setUserName (username );
options.setPassword (pass.toCharArray ());
options.setAutomaticReconnect (true);
options.setConnectionTimeout (10);
options.setMaxInflight (200);
return options;
}
}
89
package com.cosmin.cartracking.mqtt.listener ;
import android.util.Log ;
import com.cosmin.cartracking.gson.GsonFactory ;
import com.cosmin.cartracking.mqtt.Mqtt ;
import com.google.gson.Gson ;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener ;
import org.eclipse.paho.client.mqttv3.MqttMessage ;
public abstract class MqttListener <T> implements IMqttMessageListener {
private Gson gson;
public MqttListener () {
gson = GsonFact ory.create();
}
@Override
public void messageArrived (String topic, MqttMessage message) throws Exception {
if (!topic.equals(getTopic ())) {
Log.d(Mqtt.TAG, String.format("skip message from %s! current listner is subscribed
to %s",
topic, getTopic ()));
return;
}
String json = new String(message.getPayload ());
onMessageReceived (gson.fromJson (json, getClassType ()));
}
public abstract String getTopic ();
public abstract void onMessageReceived (T message);
public abstract Class<T> getClassType ();
}
package com.cosmin.cartracking.mqtt.listener ;
import android.app.NotificationManager ;
import android.app.PendingIntent ;
import android.content.Context ;
import android.content.Intent ;
import android.support.v4.app.NotificationCompat ;
import android.util.Log ;
import com.cosmin.cartracking.MainActivity ;
import com.cosmin.cartracking.R ;
import com.cosmin.cartracking.mqtt.Mqtt ;
import com.cosmin.cartracking.mqtt.mode l.Alert;
public class AlertsListener extends MqttListener <Alert> {
private long userid;
private Context context;
private NotificationManager notificationManager ;
90
public AlertsListener (long userid, Context context, NotificationManager
notificationManager ) {
super();
this.userid = userid;
this.context = context;
this.notificationManager = notificationManager ;
}
@Override
public String getTopic () {
return String.format("user.%d.alerts" , userid);
}
@Override
public void onMessageReceived (Alert message) {
Log.d(Mqtt.TAG, "message received from alerts listener" );
NotificationCompat .Builder mBuilder = new NotificationCompat .Builder(context)
.setSmallIcon (R.mipmap.ic_car3)
.setContentTitle (message.getTitle ())
.setAutoCancel (true)
.setContentText (message.getMessage ());
try {
Intent resultIntent = new Intent(context, MainActivity .class);
PendingIntent resultPendingIntent =
PendingIntent .getActivity (context, 0, resultIntent ,
PendingIntent .FLAG_UPDATE_CURRENT );
mBuilder .setContentIntent (resultPendingIntent );
notificationManager .notify((int) System.currentTimeMillis (), mBuilder .build());
} catch (Exception e) {
Log.d(Mqtt.TAG, "Failed to show notif" );
Log.d(Mqtt.TAG, e.getMessage ());
}
}
@Override
public Class<Alert> getClassType () {
return Alert.class;
}
}
package com.cosmin.cartracking.mqtt ;
import com.cosmin.cartracking.model.TaskLog ;
public class TaskLogPublisher {
private final static String TOPIC = "user.%d.employee.%d.task.log s";
private Mqtt mqttClient ;
public TaskLogPublisher (Mqtt mqttClient ) {
this.mqttClient = mqttClient ;
}
public void publish(TaskLog taskLog, long userid, long adminId) {
String topic = String.format(TOPIC, adminId, userid);
try {
91
mqttClient .publish(topic, taskLog);
} catch (Exception e) {
e.printStackTrace ();
}
}
}
package com.cosmin.cartracking.mqtt ;
import com.cosmin.cartracking.gson.GsonFactory ;
import com.google.g son.Gson ;
import org.eclipse.paho.client.mqttv3.MqttMessage ;
import java.io.UnsupportedEncodingException ;
public class MqttMessageFactory {
public MqttMessage create(Object object) {
Gson gson = GsonFactory .create();
String json = gson.toJson(object);
return doCreate (json);
}
private MqttMessage doCreate (String json) {
try {
byte[] encodedPayload = json.getBytes ("UTF-8");
return new MqttMessage (encodedPayload );
} catch (UnsupportedEncodingException e) {
throw new RuntimeException (e);
}
}
}
92
Bibliografie
1. Fielding, Roy T.; Gettys, James; Mogul, Jeffrey C.; Nielsen, Henrik Frystyk; Masinter,
Larry; Leach, Paul J.; Berners -Lee, Tim (June 1999). Hy pertext Transfer Protocol –
HTTP/1.1. IETF. RFC 2616.
2. Vinoski, S. (2006). "Advanced Message Queuing Protocol” 87 –89
3. Russel Bradberry, Eric Lubow Practical Cassandra A Developers Approach, 2013
4. C.Y. Kan Cassandra Data Modelling and Analysis, 2014
5. Seth Gilb ert și Nancy Lynch, "Brewer's conjecture and the feasibility of consistent,
available, partition -tolerant web services", ACM SIGACT News, Volume 33 Issue 2
(2002), pg. 51 –59
6. Sisteme de baze de date Distribuite, Dorin Cârstoiu, 2013
7. Dorin Carstoiu, Baze de date, Editura Matrix Rom 2009
8. Richardson, Leonard; Ruby, Sam (2007), RESTful Web service, O'Reilly Media
9. Fielding, Roy Thomas (2000). "Chapter 5: Representational State Transfer (REST)".
Architectural Styles and the Design of Network -based Software Archite ctures (Ph.D.).
University of California, Irvine
10. Avraham Leff, James T. Rayfield, Web -Application Development Using the
Model/View/Controller Design Pattern. IEEE Enterprise Distributed Object Computing
Conference, Septembrie 2001,p. 118 –127
11. Erl, Thomas (2005). Service Oriented Architecture: Concepts, Technology, and Design.
Indiana: Pearson Education. p. 171. ISBN 0 -13-185858 -0.
12. Birman, K. and Joseph, T. "Exploiting virtual synchrony in distributed systems" in
Proceedings of the eleventh ACM Symposium on Operating systems principles (SOSP
'87), 1987. pp. 123 –138.
13. https://www.cloudamqp.com/blog/2015 -05-18-part1 -rabbitmq -for-beginners -what -is-
rabbitmq.html
14. http://www.rabbitmq.com/
15. https://dzone.com/refcardz/html5 -websocket
16. https://dzone.com/refcardz/amqp -essentials
17. https://dzone.com/articles/getting -started -with-rabbitmq -cloud -based -message
18. https://www.websocket.org/
19. https://www.amqp.org/
20. https://www.ietf.org/rfc/rfc6455.txt
21. https://jwt.io/introduction/
22. https://spring.io/
23. http://docs.spring.io/spring/docs/current/spring -framework –
reference/html/w ebsocket.html
24. https://dzone.com/articles/better -explaining -cap-theorem
25. https://www.iso.org/obp/ui/#iso:std:iso -iec:19464:ed -1:v1:en
26. http://cassandra.apache.org/doc/latest/
93
27. http://doc s.datastax.com/en/cassandra/3.0/
28. https://tools.ietf.org/html/rfc7519
29. http://www.smartfleet.ro/
30. https://angularjs.org/
31. https://developers.google.com/maps/
32. http://developer.android.com/develop/index.html
33. https://www.supergps.ro/
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Sistem De Monitorizare Si Gestiune A Unei Flote Auto Cosmin Seceleanu.docx [610542] (ID: 610542)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
