Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Mikhail Salosin (a továbbiakban – MS): - Sziasztok! A nevem Michael. Az MC2 Software-nél háttérfejlesztőként dolgozom, és a Go használatáról fogok beszélni a Look+ mobilalkalmazás hátterében.

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Szereti itt valaki a jégkorongot?

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Akkor ez az alkalmazás az Ön számára. Androidra és iOS-re készült, és különféle sportesemények online és rögzített közvetítésének nézésére szolgál. Az alkalmazás különféle statisztikákat, szöveges közvetítéseket, konferenciák, versenyek táblázatait és egyéb, a rajongók számára hasznos információkat is tartalmaz.

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Az alkalmazásban van olyan is, mint a videós pillanatok, vagyis a meccsek legfontosabb pillanatait nézheti meg (gólok, küzdelmek, szétlövések stb.). Ha nem szeretné végignézni a teljes adást, csak a legérdekesebbeket nézheti meg.

Mit használtál a fejlesztés során?

A fő rész Go nyelven íródott. Az API, amellyel a mobilkliensek kommunikáltak, a Go-ban íródott. A Go-ban egy szolgáltatást is írtak mobiltelefonokra push értesítések küldésére. Meg kellett írnunk a saját ORM-ünket is, amiről talán majd egyszer beszélünk. Nos, a Go-ban megírtak néhány apróbb szolgáltatást: átméretezés és képek betöltése a szerkesztőknek...

Adatbázisként PostgreSQL-t használtunk. A szerkesztő felület Ruby on Rails nyelven íródott az ActiveAdmin gyöngyszem segítségével. A statisztikák importálása egy statisztikai szolgáltatótól szintén Ruby nyelven íródott.

A rendszer API-tesztekhez Python unittestet használtunk. A Memcached az API fizetési hívások korlátozására szolgál, a „Chef” a konfiguráció vezérlésére, a Zabbix pedig a belső rendszerstatisztikák gyűjtésére és figyelésére szolgál. A Graylog2 a naplók gyűjtésére szolgál, a Slate pedig az API-dokumentáció az ügyfelek számára.

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Protokoll kiválasztása

Az első probléma, amellyel szembesültünk: protokollt kellett választanunk a háttérrendszer és a mobil kliensek közötti interakcióhoz, a következő pontok alapján...

  • A legfontosabb követelmény: az ügyfelek adatait valós időben kell frissíteni. Vagyis mindenkinek, aki éppen nézi az adást, szinte azonnal meg kell kapnia a frissítéseket.
  • A dolgok leegyszerűsítése érdekében azt feltételeztük, hogy az ügyfelekkel szinkronizált adatok nem törlődnek, hanem speciális jelzők segítségével el vannak rejtve.
  • Mindenféle ritka kérés (például statisztikák, csapatösszeállítások, csapatstatisztikák) a szokásos GET-kérésekből származik.
  • Ráadásul a rendszernek egyszerre 100 ezer felhasználót kellett könnyedén támogatnia.

Ez alapján két protokoll lehetőségünk volt:

  1. Websockets. De nem volt szükségünk csatornákra a klienstől a szerverig. Csak frissítéseket kellett küldenünk a szerverről a kliensnek, így a websocket redundáns lehetőség.
  2. A szerver által küldött események (SSE) pont jól jöttek! Nagyon egyszerű, és alapvetően mindent kielégít, amire szükségünk van.

Szerver által küldött események

Néhány szó a dolog működéséről...

http kapcsolaton fut. A kliens kérést küld, a szerver Content-Type: text/event-stream-el válaszol, és nem zárja le a kapcsolatot a klienssel, hanem folytatja az adatok írását a kapcsolatra:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Az adatok az ügyfelekkel egyeztetett formátumban küldhetők. Esetünkben ebben a formában küldtük: az esemény mezőbe a megváltozott struktúra neve (személy, játékos), az adatmezőbe pedig a JSON a játékos számára új, megváltozott mezőkkel került.

Most beszéljünk arról, hogyan működik maga az interakció.

  • Az ügyfél első dolga, hogy meghatározza a szolgáltatással való utolsó szinkronizálás időpontját: megnézi a helyi adatbázisát, és meghatározza az általa rögzített utolsó változtatás dátumát.
  • Ezzel a dátummal küld egy kérést.
  • Válaszul elküldjük neki az összes frissítést, ami azóta történt.
  • Ezt követően kapcsolatot létesít az élő csatornával, és addig nem záródik be, amíg nincs szüksége a következő frissítésekre:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Küldünk neki egy listát a változásokról: ha valaki gólt rúg, módosítjuk a meccs eredményét, ha megsérül, akkor ezt is valós időben küldjük el. Így az ügyfelek azonnal megkapják a naprakész adatokat a mérkőzés esemény hírfolyamában. Időnként, hogy a kliens megértse, hogy a szerver nem halt meg, nem történt vele semmi, 15 másodpercenként küldünk egy időbélyeget - hogy tudja, hogy minden rendben van, és nem kell újracsatlakozni.

Hogyan történik az élő kapcsolat kiszolgálása?

  • Először is létrehozunk egy csatornát, amelybe a pufferelt frissítések érkeznek.
  • Ezt követően feliratkozunk erre a csatornára, hogy értesüljünk a frissítésekről.
  • Beállítjuk a megfelelő fejlécet, hogy az ügyfél tudja, hogy minden rendben van.
  • Az első ping küldése. Egyszerűen rögzítjük az aktuális csatlakozási időbélyeget.
  • Ezt követően ciklusban olvasunk a csatornából a frissítési csatorna bezárásáig. A csatorna időszakonként megkapja vagy az aktuális időbélyeget, vagy a már írt változtatásokat a nyitott kapcsolatokhoz.

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Az első probléma, amivel szembesültünk, a következő volt: minden klienssel megnyitott kapcsolathoz készítettünk egy időzítőt, ami 15 másodpercenként egyszer ketyeg – ebből kiderül, hogy ha egy géppel (egy API szerverrel) 6 ezer kapcsolatunk lenne nyitva, akkor 6 ezer időzítőt hoztak létre. Ez oda vezetett, hogy a gép nem bírta a szükséges terhelést. A probléma nem volt olyan nyilvánvaló számunkra, de kaptunk egy kis segítséget, és megoldottuk.

Ennek eredményeként a pingünk ugyanarról a csatornáról érkezik, amelyről a frissítés érkezik.

Ennek megfelelően csak egy időzítő van, amely 15 másodpercenként ketyeg.

Számos kiegészítő funkció van itt - a fejléc elküldése, a ping és maga a szerkezet. Azaz a tabella neve (személy, meccs, szezon) és a bejegyzéssel kapcsolatos információk itt kerülnek továbbításra:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

A frissítések küldésének mechanizmusa

Most egy kicsit arról, hogy honnan származnak a változások. Többen, szerkesztőink vannak, akik valós időben nézik az adást. Ők teremtik meg az összes eseményt: valakit kiállítottak, valaki megsérült, valami csere...

CMS segítségével az adatok bekerülnek az adatbázisba. Ezt követően az adatbázis a Listen/Notify mechanizmussal értesíti erről az API szervereket. Az API-kiszolgálók már elküldik ezeket az információkat az ügyfeleknek. Így lényegében csak néhány szerver csatlakozik az adatbázishoz, és nincs különösebb terhelés az adatbázison, mivel a kliens semmilyen módon nem lép kapcsolatba közvetlenül az adatbázissal:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

PostgreSQL: Figyelj/Értesítés

A Postgres Listen/Notify mechanizmusa lehetővé teszi, hogy értesítse az eseményre feliratkozókat, ha valamilyen esemény megváltozott – bizonyos rekordokat hoztak létre az adatbázisban. Ehhez írtunk egy egyszerű triggert és függvényt:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Rekord beszúrásakor, módosításakor a data_updates csatornán meghívjuk a notify függvényt, átadva ott a tábla nevét és a módosított vagy beszúrt rekord azonosítóját.

Minden klienssel szinkronizálandó táblához definiálunk egy triggert, amely egy rekord módosítása/frissítése után meghívja az alábbi dián jelzett függvényt.
Hogyan iratkozik fel az API ezekre a változásokra?

Létrejön egy Fanout mechanizmus – üzeneteket küld a kliensnek. Összegyűjti az összes ügyfélcsatornát, és az alábbi csatornákon keresztül küldi el a kapott frissítéseket:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Itt a szabványos pq könyvtár, ami csatlakozik az adatbázishoz és azt mondja, hogy hallgatni akarja a csatornát (data_updates), ellenőrzi, hogy a kapcsolat nyitva van-e és minden rendben van. Helytakarékosság miatt kihagyom a hibaellenőrzést (az ellenőrzés hiánya veszélyes).

Ezután aszinkron módon beállítjuk a Tickert, amely 15 másodpercenként küld egy pinget, és elkezdi hallgatni azt a csatornát, amelyre előfizettünk. Ha pinget kapunk, közzétesszük ezt a pinget. Ha kapunk valamilyen bejegyzést, akkor ezt a bejegyzést közzétesszük a Fanout összes előfizetője számára.

Hogyan működik a Fan-out?

Oroszul ez „elosztó”-nak felel meg. Van egy objektumunk, amely regisztrálja azokat az előfizetőket, akik frissítéseket szeretnének kapni. És amint frissítés érkezik ehhez az objektumhoz, ezt a frissítést kiosztja minden előfizetőjének. Elég egyszerű:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Hogyan valósul meg a Go-ban:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Van egy szerkezet, Mutexes segítségével szinkronizálják. Van egy mezője, amely elmenti a Fanout adatbázishoz való kapcsolódási állapotát, azaz éppen hallgat, és frissítéseket fog kapni, valamint az összes elérhető csatorna listája - térkép, amelynek kulcsa a csatorna és a struktúra értékeket (lényegében semmilyen módon nem használják).

Két módszer – Connected és Disconnected – lehetővé teszi, hogy közöljük a Fanouttal, hogy van kapcsolatunk az alappal, megjelent, és megszakadt a kapcsolat a bázissal. A második esetben le kell választani az összes klienst, és közölni kell velük, hogy már nem hallgathatnak semmit, és újra csatlakoznak, mert a kapcsolat megszakadt.

Van egy feliratkozási módszer is, amely hozzáadja a csatornát a „hallgatókhoz”:

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Létezik egy Leiratkozás metódus, amely eltávolítja a csatornát a hallgatók közül, ha a kliens megszakad, valamint egy Publish metódus, amivel minden előfizetőnek üzenetet küldhet.

Kérdés: – Mit közvetítenek ezen a csatornán?

KISASSZONY: – A megváltozott modell vagy ping átvitelre kerül (lényegében csak egy szám, egész szám).

KISASSZONY: - Bármit küldhet, bármilyen struktúrát küldhet, közzéteheti - csak JSON-ba alakul, és kész.

KISASSZONY: – Értesítést kapunk a Postgrestől – ez tartalmazza a táblázat nevét és azonosítóját. A táblanév és az azonosító alapján megkapjuk a szükséges rekordot, majd ezt a struktúrát elküldjük publikálásra.

Infrastruktúra

Hogyan néz ki ez infrastruktúra szempontjából? 7 hardveres szerverünk van: az egyik teljes egészében az adatbázisnak van dedikálva, a másik hatban virtuális gépek futnak. Az API-nak 6 példánya van: minden API-val rendelkező virtuális gép külön hardverkiszolgálón fut – ez a megbízhatóság érdekében történik.

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Két kezelőfelületünk van telepítve a Keepaliveddel a kisegítő lehetőségek javítása érdekében, így ha valami történik, az egyik kezelőfelület helyettesítheti a másikat. Továbbá – a CMS két példánya.

Van egy statisztikai importőr is. Van egy DB Slave, amelyről rendszeres időközönként biztonsági mentések készülnek. Van egy Pigeon Pusher, egy olyan alkalmazás, amely push értesítéseket küld az ügyfeleknek, valamint infrastrukturális dolgokat: Zabbix, Graylog2 és Chef.

Valójában ez az infrastruktúra redundáns, mert 100 ezret kevesebb szerverrel ki lehet szolgálni. De volt vas - használtuk (mondták, hogy lehet - miért ne).

A Go előnyei

Miután ezen az alkalmazáson dolgoztunk, a Go ilyen nyilvánvaló előnyei jelentek meg.

  • Menő http könyvtár. Elég sok mindent létrehozhat vele a dobozból.
  • Ráadásul olyan csatornák, amelyek lehetővé tették számunkra, hogy nagyon könnyen megvalósíthassunk egy olyan mechanizmust, amellyel értesítéseket küldhetünk az ügyfeleknek.
  • A csodálatos dolog, a Race detector lehetővé tette számunkra, hogy kiküszöböljünk számos kritikus hibát (staging infrastruktúra). Minden, ami a színpadon működik, elindul, a Race billentyűvel lefordítva; és ennek megfelelően megnézhetjük a színpadi infrastruktúrát, hogy lássuk, milyen potenciális problémáink vannak.
  • A nyelv minimalizmusa és egyszerűsége.

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

Fejlesztőket keresünk! Ha valaki szeretné kérem.

kérdések

Kérdés a közönségtől (továbbiakban – B): – Úgy tűnik számomra, hogy egy fontos pontot kihagytál a Fan-out kapcsán. Jól értem, hogy amikor választ küld egy ügyfélnek, akkor blokkolja, ha az ügyfél nem akarja olvasni?

KISASSZONY: - Nem, nem blokkoljuk. Először is, mindez az nginx mögött van, vagyis a lassú kliensekkel nincs probléma. Másodszor, a kliensnek van egy pufferes csatornája - sőt, akár száz frissítést is rakhatunk oda... Ha nem tudunk írni a csatornára, akkor törli. Ha azt látjuk, hogy a csatorna blokkolva van, akkor egyszerűen bezárjuk a csatornát, és ennyi - az ügyfél újracsatlakozik, ha bármilyen probléma merül fel. Ezért itt elvileg nincs blokkolás.

BAN BEN: – Nem lehetne azonnal rekordot küldeni a Listen/Notify-nak, és nem egy azonosító táblát?

KISASSZONY: – A Listen/Notify 8 ezer bájtos limittel rendelkezik az általa küldött előtöltésben. Elvileg akkor is lehetne küldeni, ha kis mennyiségű adattal lenne dolgunk, de nekem úgy tűnik, hogy így [ahogyan csináljuk] egyszerűen megbízhatóbb. A korlátok magában a Postgresben vannak.

BAN BEN: – Kapnak-e híreket az ügyfelek azokról a mérkőzésekről, amelyek nem érdeklik őket?

KISASSZONY: - Általában igen. Általában 2-3 meccs zajlik párhuzamosan, és akkor is elég ritkán. Ha egy ügyfél néz valamit, akkor általában azt a meccset nézi, ami éppen folyik. Ezután az ügyfélnek van egy helyi adatbázisa, amelybe az összes frissítést összeadják, és még internetkapcsolat nélkül is megtekintheti az összes korábbi mérkőzést, amelyhez frissítései vannak. Lényegében a szerveren lévő adatbázisunkat szinkronizáljuk a kliens helyi adatbázisával, hogy offline tudjon dolgozni.

BAN BEN: – Miért csinált saját ORM-ot?

Alexey (a Look+ egyik fejlesztője): – Akkoriban (egy éve volt) kevesebb ORM volt, mint most, amikor elég sok van belőlük. A legtöbb ORM-ben az a kedvencem, hogy a legtöbb üres felületen fut. Vagyis ezekben az ORM-ekben a metódusok bármire készek: struktúrára, szerkezetmutatóra, számra, valami teljesen irrelevánsra...

Az ORM-ünk az adatmodell alapján struktúrákat generál. Magamat. Ezért minden módszer konkrét, nem használ reflexiót stb. Elfogadják a struktúrákat, és elvárják, hogy azokat a struktúrákat használják, amelyek jönnek.

BAN BEN: - Hányan vettek részt?

KISASSZONY: – A kezdeti szakaszban ketten vettek részt. Valahol júniusban kezdtük, augusztusra pedig kész is volt a fő rész (az első verzió). Szeptemberben volt kiadás.

BAN BEN: – Ahol leírja az SSE-t, ott nem használja az időtúllépést. Miert van az?

KISASSZONY: – Hogy őszinte legyek, az SSE még mindig egy html5 protokoll: az SSE szabványt úgy tervezték, hogy a böngészőkkel kommunikáljon, amennyire én értem. További funkciókkal rendelkezik, hogy a böngészők újracsatlakozhassanak (és így tovább), de nincs rájuk szükségünk, mert voltak olyan klienseink, amelyek bármilyen logikát képesek voltak megvalósítani a csatlakozáshoz és az információ fogadásához. Nem SSE-t készítettünk, hanem valami hasonlót az SSE-hez. Ez nem maga a protokoll.
Nem volt rá szükség. Ha jól értem, az ügyfelek szinte a nulláról valósították meg a csatlakozási mechanizmust. Nem igazán érdekelte őket.

BAN BEN: – Milyen további segédprogramokat használt?

KISASSZONY: – A stílus egységesítéséhez legaktívabban a govet és a golint, valamint a gofmt-t használtuk. Mást nem használtak.

BAN BEN: – Mit használtál a hibakereséshez?

KISASSZONY: – A hibakeresés nagyrészt tesztekkel történt. Nem használtunk hibakeresőt vagy GOP-t.

BAN BEN: – Vissza tudja adni azt a diát, ahol a Publish funkciót megvalósították? Összezavarnak az egybetűs változónevek?

KISASSZONY: - Nem. Meglehetősen „szűk” a láthatóságuk. Nem használják sehol máshol, csak itt (kivéve ennek az osztálynak a belső részeit), és nagyon kompakt - mindössze 7 sort vesz igénybe.

BAN BEN: – Valahogy még mindig nem intuitív…

KISASSZONY: - Nem, nem, ez egy igazi kód! Ez nem a stílus kérdése. Ez egy ilyen haszonelvű, nagyon kicsi osztály - csak 3 mező van az osztályon belül...

Mihail Salosin. Golang Meetup. A Go használata a Look+ alkalmazás hátterében

KISASSZONY: – Általánosságban elmondható, hogy az ügyfelekkel szinkronizált összes adat (szezonmérkőzések, játékosok) nem változik. Nagyjából, ha más sportot űzünk, amiben meccset kell váltanunk, akkor egyszerűen mindent figyelembe veszünk a kliens új verziójában, és a kliens régi verziói ki lesznek tiltva.

BAN BEN: – Léteznek harmadik féltől származó függőségkezelési csomagok?

KISASSZONY: – A go dep-et használtuk.

BAN BEN: – A riport témájában volt valami videóról, de a videóról nem volt szó.

KISASSZONY: – Nem, nincs semmi a témában a videóval kapcsolatban. „Look+”-nak hívják – ez az alkalmazás neve.

BAN BEN: – Azt mondtad, hogy az ügyfeleknek közvetítik?...

KISASSZONY: – Nem vettünk részt a videó közvetítésében. Ezt teljes egészében a Megafon készítette. Igen, nem azt mondtam, hogy az alkalmazás a MegaFon.

KISASSZONY: – Go – az összes adat elküldéséhez – az eredményekről, a mérkőzések eseményeiről, a statisztikákról... A Go az alkalmazás teljes háttérrendszere. A kliensnek valahonnan tudnia kell, hogy melyik linket használja a játékos számára, hogy a felhasználó megnézhesse a meccset. Vannak linkjeink az elkészített videókhoz és streamekhez.

Néhány hirdetés 🙂

Köszönjük, hogy velünk tartott. Tetszenek cikkeink? További érdekes tartalmakat szeretne látni? Támogass minket rendeléssel vagy ajánlj ismerőseidnek, felhő VPS fejlesztőknek 4.99 dollártól, a belépő szintű szerverek egyedülálló analógja, amelyet mi találtunk ki Önnek: A teljes igazság a VPS-ről (KVM) E5-2697 v3 (6 mag) 10 GB DDR4 480 GB SSD 1 Gbps 19 dollártól, vagy hogyan oszthat meg egy szervert? (RAID1 és RAID10, akár 24 maggal és akár 40 GB DDR4-gyel is elérhető).

A Dell R730xd kétszer olcsóbb az amszterdami Equinix Tier IV adatközpontban? Csak itt 2x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6 GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV 199 dollártól Hollandiában! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 dollártól! Olvasni valamiről Hogyan építsünk infrastrukturális vállalatot? osztályú Dell R730xd E5-2650 v4 szerverek használatával 9000 eurót ér egy fillérért?

Forrás: will.com

Hozzászólás