Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Firebase and real-time backend infrastructure

Firebase and real-time backend infrastructure

Marko Frankovic

January 16, 2017
Tweet

Other Decks in Programming

Transcript

  1. Sadržaj - Firebase i backend - Primjer - Iskustva i

    kratak pregled infrastrukture - Struktura projekta
  2. Problemi - Količina podataka - Velik broj korisnika - Svaki

    korisnik kreira više tipova podataka: količina kretanja, san, meditacija… - Velika količina podataka se kreira na dnevnoj razini ili češće - Firebase - Ne nudi kvalitetan „download” podataka - Mogućnost preuzimanja cijele baze u obliku json-a je problematično - Mogućnost preuzimanja dijela baze također problematično - Nema mogućnosti analize direktno na bazi (radi same konstrukcije) - Firebase listener API je nužno Single-Thread što predstavlja usko grlo
  3. Fsync – Ideja - Dignuti Firebase listenere na sve potrebne

    pathove - Restartati što je rjeđe moguće - Broj listenera je pre veliki za jedan server – shardati usere - Garantirati da je svaki payload isporučen točno jednom - Implementirati generički - Agnostičan prema modelu - Dodavanje novog listenera/korisnika ne smije zahtjevati restart - Definiranje processora mora biti jednostavno. Treba ponuditi raznovrsne inicijalne sinkove
  4. Consistent Hashing - Primjena - Razdijeliti n hasheva u k

    bucketa na nacin da u svakom bucketu bude približno n/k hasheva. - Minimizirati prebacivanje hasheva pri dodavanju ili odbacivanju bucketa - Dobre hash funkcije - Murmur - Md5
  5. Leader Election - Služi za određivanje tko će u clusteru

    odrađivati posebne poslove - Odrađuje se koristeći ZK - Svaki server stvara sekvencijalne čvorove u ZK - Prvi je proglašen leaderom
  6. Distributed Barrier - Kao i barrier pattern, ali za distribuirano

    računanje - Ako proces dođe do barrier-a, čeka dok se barrier ne spusti - ZK se brine o barrier-i
  7. Infrastruktura - Više servera u clusteru, leader odrađuje inicijalizaciju clustera

    i detektira spadanje i ulazak nodova u cluster - ZooKeeper za leader election i distributed barrier - Consistent hashing algoritmom se konzistentno i ravnomjerno distribuira posao na razne servere u clusteru - Kafka za zaprimanje novih usera i prosljeđivanje syncanih podataka - Cassandra kao storage
  8. Promjene u clusteru • Full reshard definicija - Node koji

    dobije ovaj event, kreira novi Consistent hashing od svih nodova koji trenutno participiraju u Leader election procesu. Nakon toga, čita sve korisnike iz C*, radi deltu sa korisnicima koje trenutno obrađuje i diže potrebne listenere. • Full reshard event ◦ Restart - Bira se leader. Leader diže barijeru i čeka da se svi nodovi pridruže. Nakon toga spušta barijeru i šalje full reshard event svim nodovima u clusteru ◦ Node fail - Leader prati sudionike u Leader election procesu. Kad node ispadne, leader čeka neko vrijeme. Ukoliko se node ne vrati, šalje full reshard event. Ukoliko se vrati, samo taj node radi full reshard ◦ Node added - Ukoliko se u leader election procesu pojavi novi node, leader šalje full reshard event svim nodovima u clusteru
  9. Mapiranje • Mapiranje definira koji processor je potrebno postaviti na

    listener za neki path • Konfiguracija nudi odabir tipa listenera (child/value/sync_path) te načina obrade primljenih podataka • Default implementacija sprema podatke u C* ◦ Nadogradnje default implementacije ▪ Kafka sink ▪ ElasticSearch indeksiranje ▪ Postavljanje drugog procesora na child node ▪ Custom procesori • Jednostavno je implementirati svoje obrade primljenih podataka, ali je ideja da se Fsync odnosi agnostički prema podacima. Same obrade se odrađuju u narednim mikroservisima ili u data flow-u [ { "syncPath":"/v0/data/meditation/completedExercises/:us erId", "listenerType":"CHILD", "lazyDataSpel":null, "processorType":"SPRING_BEAN", "processorName":"fSyncProcessServiceMeditation", "childSyncProcessorName":null }, { "syncPath":"/v0/data/leaf/sync/:userId", "listenerType":"SYNC_PATH", "lazyDataSpel":"data['rawDataReference']", "processorType":"SPRING_BEAN", “targets”:[“leaf-api”,”step-agg”], "processorName":"fSyncProcessServiceChildListenerRegis trator", "childSyncProcessorName":"fSyncProcessServiceKafka" } ]
  10. Promjene u mapiranju • Mapping flow - Mapiranje se clusteru

    komunicira preko RESTa. Request može završiti na bilo kojem nodu clustera. Node koji ga dobije, zapisuje novi mapping u C*, te u zookeeper zapisuje id tog mappinga na odgovarajući zNode. Leader sluša promjene tog zNoda, te šalje Mapping changed event • Mapping changed event ◦ Node koji dobije ovaj event, napravi deltu između mapiranja koje trenutno koristi i novog mapiranja. Po toj delti, dodaje ili odbacuje listenere za sve korisnike koje trenutno obrađuje.
  11. Dodavanje novog korisnika • UAA server pri registraciji korisnika, komunicira

    korisnički ID preko kafke Fsync klasteru • Svaki node u FSync clusteru je anonimni consumer. Ukoliko dobiveni ID pripada njemu, zapisuje korisnika u C* te diže odgovarajuće Firebase listenere
  12. Nedostaci Memorijska složenost • Zbog količine listenera prema Firebaseu je

    povećana memorijska složenost • Ovo je posljedica Firebase API-a • Zbog prirode Firebase API-a su svi strojevi u clusteru single threaded • Strojevi ne trebaju imati jaki procesor, ali im je potrebna visoka količina memorije
  13. Nedostaci Restart clustera • Ukoliko se cluster kompletno restarta, svi

    podaci iz Firebase-a će se ponovo povući • To je posljedica Firebase API-a te nije moguće utjecati na to • Potrebno je naknadno osigurati exactly once garancije
  14. Primjer – Event per minute • Event per minute –

    model kojim se komuniciraju podaci sa leafa • Definirati novi fSyncMapping ◦ Path sadrži dva ID-a – definiramo sync-path processor ◦ Kao child processor definiramo kafka sink • Payload sadrži data reference? ◦ Definiramo lazyDataSpel path: /v0/data/sync/leaf/ :userId/:leafId “data":{ "appVersion":"1.21.3", "data": { "rawDataReference":"/users/123/v0/leaf/234/sync/345.js on" }, "dataEnd":"2016-12-09T15:06:12.000", "osVersion":"7.0", "sourceVersion":"CS10947g10", "dataStart":"2016-12-09T14:58:12.000", "timezone":"Europe/Zagreb", "deviceName":"LGE Nexus 5X", "timestamp":"2016-12-09T16:06:05.396" }
  15. Primjer - Envelope • Izlaz iz Fsync-a je syncani podatak

    omotan envelopom koji završava u Kafki • Topic sluša Frouter mikroservis. On vidi da je envelopeType Lazy, pa ju šalje na fetchanje u Fetcher ms • Fetcher ms povlaći podatke sa GSC-a te ih dodaje u envelopu I vraća Frouteru • Router dalje radi fanout prema targets polju. Default je – Spring Data Flow { "envelopeType":"LAZY", "type":"VALUE", "syncTmstp":1481891217393, "userId":"123", "childId":"345", "syncPath":"/v0/data/leaf/sync/123/234", "lazyDataUrl":"/users/123/v0/leaf/234/sync/345.json", “targets”:[“leaf-api”,”step-agg”] "fetchedData":null, "data":{ Ovdje je syncani child entity }, "error":false, "rawErrorPayload":null }
  16. Microservisi - iskustva - Standardizirati projekte - Maven archtype -

    Koristiti testirane tehnologije - Netflix OSS (Spring Cloud) - Single front proxy - Zuul - Service discovery - Eureka - Client side load balancing i retry - Ribbon - Standardizirani api klijenti - Feign - Circuit breaker pattern - Hystrix - Cloud Config - Pub/Sub - Kafka (Spring stream kafka) - Standardizirati storage (Spring data JPA/Cassandra/Redis) - Standardizirati logging infrastrukturu - Svi microservisi koriste isti logging pattern. Loggregator, LogXtender, ELK stack - Dobra cloud infrastruktura - AWS - CI/CD - Jenkins, Nexus, Cloud Foundry - HA