Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Michaël Salosin (ďalej – MS): – Ahojte všetci! Volám sa Michaël. Pracujem ako backend vývojár v spoločnosti MC2 Software a porozprávam vám o využití Go v backend vývoji mobilnej aplikácie „Sívaj+”.

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Kto z prítomných má rád hokej?

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Potom je táto aplikácia pre vás. Je dostupná na platformách Android a iOS a slúži na sledovanie prenosov rôznych športových udalostí online aj zo záznamu. V aplikácii sú tiež rôzne štatistiky, textové prenosy, tabuľky konferencií, turnajov a iné informácie užitočné pre fanúšikov.

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

V aplikácii je tiež funkcia, ako sú videomomenty, t. j. môžete si pozrieť najzaujímavejšie momenty zápasov (góly, bitky, nájazdy a iné). Ak sa vám nechce sledovať celý prenos, môžete si pozrieť len to najzaujímavejšie.

Čo sme používali pri vývoji?

Hlavná časť bola napísaná v Go. Ten API, s ktorým komunikovali mobilné klienti, bol napísaný v Go. Taktiež sme na Go vytvorili službu na odosielanie push notifikácií na mobily. Ešte sme museli napísať naše vlastné ORM, o ktorom sa možno niekedy podelíme. A na Go boli napísané aj niektoré menšie služby: zmenšovanie a nahrávanie obrázkov pre redaktorskú stranu...

Ako databázu sme použili PostgreSQL. Rozhranie pre redaktorov bolo napísané v Ruby on Rails s pomocou gemu ActiveAdmin. Na Ruby boli napísané aj importy štatistík od poskytovateľa štatistík.

Na systémové testy API sme použili unittest v Pythone. Memcached sa používa na obmedzovanie počtu požiadaviek na API platby, Chef sa používa na správu konfigurácie, Zabbix na zber a monitoring interných štatistických údajov systému. Graylog2 sa používa na zber logov, Slate je dokumentácia API pre klientov.

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Výber protokolu

Prvý problém, s ktorým sme sa stretli: museli sme si vybrať protokol interakcie backendu s mobilnými klientmi, vychádzajúc z nasledujúcich bodov...

  • Najdôležitejšia požiadavka: údaje na klientoch sa musia aktualizovať v reálnom čase. To znamená, že všetci, ktorí práve sledujú prenos, by mali dostávať aktualizácie takmer okamžite.
  • Pre zjednodušenie sme prijali, že údaje, ktoré sa synchronizujú s klientmi, sa nemajú mazať, ale skrývať pomocou špeciálnych flagov.
  • Rôzne zriedkavé požiadavky (ako napríklad štatistiky, zostavy tímov, štatistiky tímov) sa získavajú bežnými GET požiadavkami.
  • Navyše, systém mal bez problémov zvládnuť 100 tisíc používateľov súčasne.

Na základe toho sme mali dve možnosti protokolu:

  1. Websockety. Ale nepotrebovali sme kanály od klienta k serveru. Potrebovali sme len posielať aktualizácie zo servera na klienta, takže web-socket je nadbytočný variant.
  2. Server-Sent Events (SSE) bolo presne to, čo sme potrebovali! Je dosť jednoduché a prakticky spĺňa všetko, čo potrebujeme.

Server-Sent Events

Pár slov o tom, ako táto vec funguje…

Funguje to nad http pripojením. Klient posiela požiadavku, na ňu server odpovedá Content-Type: text/event-stream a nezatvára spojenie s klientom, ale pokračuje v posielaní údajov do spojenia:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Údaje je možné posielať v formáte dohodnutom s klientmi. V našom prípade sme posielali takto: do poľa event sme posielali názov zmenenej štruktúry (človek, hráč), a do poľa data JSON s novými, zmenenými poľami pre hráča.

Teraz k tomu, ako funguje samotná interakcia.

  • Najprv klient určí, kedy naposledy došlo k synchronizácii so službou: pozrie sa do svojej lokálnej DB a určí dátum poslednej zmeny, zaregistrovanej u neho.
  • Posiela požiadavku s týmto dátumom.
  • Na oplátku mu posielame všetky aktualizácie, ktoré sa stali od tohto dátumu.
  • Potom sa pripojí k live kanálu a nezatvára ho, pokiaľ potrebuje tieto aktualizácie:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Posielame mu zoznam zmien: ak niekto dal gól – meníme skóre zápasu, ak dostal zranenie – to sa tiež posiela v reálnom čase. Takto klienti okamžite dostávajú aktuálne údaje v správe o zápase. Občas, aby klient vedel, že server nezlyhal, že sa nič nestalo, posielame každých 15 sekúnd timestamp – aby vedel, že všetko je v poriadku a nemusel sa znovu pripájať.

Ako sa obsluhuje live spojenie?

  • Najprv vytvoríme kanál, do ktorého prichádzajú aktualizácie s bufferom.
  • Potom sa prihlásime na tento kanál na prijímanie aktualizácií.
  • Nastavíme správny hlavičku, aby klient vedel, že všetko je v poriadku.
  • Posielame prvý ping. Jednoducho zapíšeme aktuálny timestamp spojenia.
  • Potom v cykle čítame z kanála, kým nie je kanál aktualizácií uzavretý. Do kanála pravidelne prichádza buď aktuálny timestamp, alebo zmeny, ktoré už zapisujeme do otvorených pripojení.

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Prvý problém, s ktorým sme sa stretli, spočíval v tom, že na každé otvorené pripojenie s klientom sme vytvárali časovač, ktorý tikal raz za 15 sekúnd – takže ak sme mali otvorených 6 tisíc pripojení s jedným strojom (s jedným API serverom), vytvorilo sa 6 tisíc časovačov. To viedlo k tomu, že stroj neudržal požadovanú záťaž. Problém nebol pre nás taký zrejmý, ale trošku nám pomohli a vyriešili sme ho.

Na konci teraz ping prichádza z rovnakého kanála, z ktorého prichádza update.

Tým pádom existuje iba jeden časovač, ktorý tiká raz za 15 sekúnd.

Tu je niekoľko pomocných funkcií – odoslanie hlavičky, pingu a samotnej štruktúry. Teda tu sa prenáša názov tabuľky (person, match, season) a samotné informácie o tejto záznamu:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Mechanizmus odosielania aktualizácií

Teraz trochu o tom, odkiaľ zmeny prichádzajú. Máme niekoľko editorov, ktorí v reálnom čase sledujú prenos. Vytvárajú všetky udalosti: niekoho vyhodili, niekto sa zranil, nejaká výmena…

Pomocou CMS sa dáta dostávajú do databázy. Potom databáza pomocou mechanizmu Listen/Notify informuje o tom API servery. API servery už rozosielajú tieto informácie klientom. Takto máme v podstate k databáze pripojených len niekoľko serverov a žiadna zvláštna záťaž na databázu nie je, pretože klient nijako priamo s databázou neinteraguje:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

PostgreSQL: Listen/Notify

Mechanizmus Listen/Notify v 'Postgres' umožňuje informovať odberateľov o udalostiach, že došlo k zmene v nejakej udalosti – bola vytvorená nejaká záznam v databáze. Na tento účel sme napísali jednoduchý spúšťač a funkciu:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Pri insert alebo zmene záznamu voláme funkciu notify na kanáli data_updates, predávame tam názov tabuľky a identifikátor záznamu, ktorý bol zmenený alebo vložený.

Na všetky tabuľky, ktoré by mali byť synchronizované s klientom, definujeme spúšťač, ktorý po zmene / aktualizácii záznamu volá funkciu, uvedenú na slajde nižšie.
Ako sa API prihlásilo na tieto zmeny?

Vytvára sa mechanizmus Fanout – ten rozosiela správy klientom. Zhromažďuje všetky kanály klientov a rozosiela aktualizácie, ktoré dostal cez tieto kanály:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Tu je štandardná knižnica pq, ktorá sa pripája k databáze a hovorí, že chce počúvať kanál (data_updates), kontroluje, či je spojenie otvorené a všetko je v poriadku. Kontrola chýb je vynechaná, aby sa ušetrilo miesto (neoverenie môže byť riskantné).

Potom asynchrónne nastavíme Ticker, ktorý bude posielať ping každých 15 sekúnd, a začneme počúvať kanál, na ktorý sme sa prihlásili. Ak dorazí ping, publikujeme tento ping. Ak prichádza nejaký záznam, publikujeme tento záznam všetkým odberateľom tohto Fanoutu.

Ako funguje Fan-out?

Po slovensky sa to prekladá ako „rozdvojovač“. Máme jeden objekt, ktorý registruje odberateľov, ktorí chcú dostávať nejaké aktualizácie. A keď len dorazí aktualizácia k tomuto objektu, rozdelí túto aktualizáciu všetkým existujúcim odberateľom. Je to dosť jednoduché:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Ako je to implementované v Go:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Existuje štruktúra, ktorá sa synchronizuje pomocou Mutexov. Má pole, ktoré ukladá stav pripojenia Fanout k databáze, t. j. momentálne počúva a bude dostávať aktualizácie, ako aj zoznam všetkých existujúcich kanálov – mapu, kde kľúčom je kanál a štruktúra vo forme hodnôt (v podstate sa nijako nepoužíva).

Dva metódy – Connected a Disconnected – umožňujú Fanoutovi vedieť, že máme spojenie s databázou, ktoré sa vytvorilo, a že spojenie s databázou bolo prerušené. V druhom prípade je potrebné odpojiť všetkých klientov a oznámiť im, že už nemôžu nič počúvať a že sa musia znovu pripojiť, keďže spojenie s nimi bolo uzavreté.

Existuje aj metóda Subscribe, ktorá pridáva kanál do „poslucháčov“:

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Existuje metóda Unsubscribe, ktorá odstraňuje kanál z poslucháčov, ak sa klient odpojil, a tiež metóda Publish, ktorá umožňuje rozposlať správu všetkým odberateľom.

Otázka: – Čo sa prenáša cez tento kanál?

MSC: – Prenáša sa model, ktorý sa zmenil, alebo ping (v podstate len číslo, integer).

MSC: – Môže sa prenášať čokoľvek, akákoľvek štruktúra – jednoducho sa premení na JSON a je to.

MSC: – Dostávame notifikáciu z „Postgresu“ – obsahuje názov tabuľky a identifikátor. Podľa názvu tabuľky a identifikátora získame požadovaný záznam a túto štruktúru posielame na publikáciu.

Infrastruktúra

Ako to vyzerá z pohľadu infraštruktúry? Máme 7 fyzických serverov: jeden z nich je úplne vyhradený pre databázu, na ostatných šiestich bežia virtuálne stroje. Existuje 6 kópií API: každá virtuálka s API beží na samostatnom fyzickom serveri – to je pre spoľahlivosť.

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Máme dva frontendové servery, na ktorých je nainštalovaný Keepalived na zlepšenie dostupnosti, aby v prípade potreby jeden frontend mohol nahradiť druhý. Ešte – dve kópie CMS.

Taktiež máme importér štatistík. Existuje DB Slave, z ktorého sa pravidelne robia zálohy. Existuje Pigeon Pusher – tá aplikácia, ktorá rozosiela push notifikácie klientom, a tiež infraštruktúrne veci: Zabbix, Graylog2 a Chef.

V skutočnosti je táto infraštruktúra nadbytočná, pretože 100 tisíc môžeme zvládnuť aj s menším počtom serverov. Ale hardvér bol – použili sme ho (povedali nám, že môžeme – prečo nie).

Výhody Go

Po tom, čo sme pracovali na tejto aplikácii, sa objavili také zjavné výhody Go.

  • Skvelá http knižnica. S ňou sa dá vytvoriť už dosť veľa „z krabice“.
  • Plus, kanály, ktoré nám umožnili veľmi ľahko implementovať mechanizmus posielania notifikácií klientom.
  • Úžasná vec Race detector nám umožnila odstrániť niekoľko kritických chýb (stagingová infraštruktúra). Všetko, čo beží na stagingu – je spustené, skompilované s kľúčom Race; a my môžeme na stagingovej infraštruktúre vidieť, aké máme potenciálne problémy.
  • Minimalizmus a jednoduchость jazyka.

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

Hľadáme vývojárov! Ak má niekto záujem – prosím.

Otázky

Otázka z publika (ďalej – O): – Zdá sa mi, že ste vynechali jeden dôležitý moment ohľadom Fan-out. Rozumiem správne, že keď posielate klientovi odpoveď, zablokujete sa, ak klient nechce čítať?

MSC: – Nie, neblokujeme sa. Po prvé, všetko je za nginx, teda nemáme žiadne problémy so pomalými klientmi. Po druhé, klient má kanál s vyrovnávacou pamäťou – v podstate môžeme zabudovať až sto aktualizácií... Ak nemôžeme zapísať do kanála, tak ho odstráni. Ak vidíme, že sa kanál zablokoval, jednoducho ho zatvoríme a hotovo – klient sa znovu pripojí, ak nastane nejaký problém. Preto tu v zásade nezaznamenávame žiadne blokácie.

A: – Nemohli ste posielať zápis priamo do Listen/Notify, a nie identifikátor tabuľky?

MSC: – Listen/Notify má obmedzenie na 8000 bajtov pri preload, ktorý odosiela. V zásade by sme to mohli posielať, ak by sme mali na starosti malé množstvo údajov, ale myslím, že to, čo robíme, je jednoducho spoľahlivejšie. Obmedzenia sú v samotnom „PostgreSQL“.

A: – Dostávajú klienti aktualizácie o zápasoch, ktoré ich nezaujímajú?

MSC: – V podstate áno. Zvyčajne je tam 2-3 zápasy súbežne, a to sa deje aj dosť zriedka. Ak klient sleduje niečo, zvyčajne sleduje ten zápas, ktorý práve beží. Potom má klient lokálnu databázu, do ktorej sa ukladajú všetky tieto aktualizácie, a dokonca aj bez pripojenia na internet môže klient vidieť všetky predošlé zápasy, ku ktorým má aktualizácie. V podstate synchronizujeme našu databázu na serveri s lokálnou databázou klienta, aby mohol pracovať aj offline.

A: – Prečo ste vytvorili svoju ORM?

Alexej (jeden z vývojárov „Svet+“): – V tom čase (to bolo pred rokom) bolo ORM menej ako teraz, keď ich je pomerne dosť. Z väčšiny existujúcich ORM sa mi najviac nepáči, že väčšina z nich pracuje na prázdnych rozhraniach. To znamená, že metódy, ktoré sú v týchto ORM, sú pripravené prijať čokoľvek: štruktúru, ukazovateľ štruktúry, číslo, niečo, čo vôbec nesúvisí...

Naša ORM generuje štruktúry na základe modelu údajov. Automaticky. A preto sú všetky metódy konkrétne, nepoužívajú reflexiu atď. Akceptujú štruktúry a očakávajú, že budú používať tie štruktúry, ktoré prídu.

A: – Koľko ľudí sa zúčastnilo?

MSC: – V počiatočnej fáze boli dvaja ľudia. Niekedy v júni sme začali, v auguste bola pripravená väčšina (prvá verzia). V septembri bol vydaný.

A: – Tam, kde opisujete SSE, nepoužívate timeout. Prečo?

MSC: Ak hovoríme otvorene, SSE je predsa len HTML5 protokol: štandard SSE je určený na komunikáciu s prehliadačmi, ak som to správne pochopil. Má ďalšie funkcie, aby sa prehliadače mohli znovu pripojiť (a ďalšie), ale tie nepotrebujeme, pretože sme mali klientov, ktorí mohli implementovať akúkoľvek logiku pripojenia a získavania informácií. Spravili sme skôr niečo, čo je podobné SSE. Nie je to samotný protokol.
Nebolo to potrebné. Ak sa nemýlim, klienti realizovali pripojovací mechanizmus prakticky od nuly. Im to v zásade bolo jedno.

A: Aké ďalšie nástroje ste používali?

MSC: Najaktívnejšie sme používali govet a golint, aby bol štýl jednotný, a tiež gofmt. Nič iné sme nepoužívali.

A: S pomocou čoho ste vykonávali ladenie?

MSC: Ladenie sa v podstate vykonávalo pomocou testov. Žiaden debugger, GOP sme nepoužívali.

A: Môžete vrátiť snímku, kde je implementovaná funkcia Publish? Nezáleží vám na jednopísmenných názvoch premenných?

MSC: Nie. Ich oblasť viditeľnosti je dosť "úzka". Nikde, okrem tohto, už viac nie sú používané (okrem vnútorností tejto triedy), a je veľmi kompaktná – zaberá len 7 riadkov.

A: Pripadne mi to ešte dosť intuitívne...

MSC: Nie-nie, to je pravý kód! Nie je to o štýle. Je to proste taký utilitárny, úplne malý trieda – len 3 polia vnútri triedy...

Michail Salosin. Golang Meetup. Použitie Go v backend aplikácie „Sleduj+“

MSC: Vo všeobecnosti sa všetky údaje, ktoré sa synchronizujú s klientmi (sezónne zápasy, hráči), nemennia. Hrubo povedané, ak by sme robili nejaký iný šport, v ktorom by bolo potrebné meniť zápas, jednoducho to zvážime v novej verzii klienta, a staré verzie klienta budú zablokované.

A: Existujú nejaké externé balíčky na správu závislostí?

MSC: Používali sme go dep.

A: V téme prezentácie bolo niečo o videu, ale v prezentácii o videu nie je.

MSC: Nie, nemám v téme o videu nič. Nazýva sa to "Svetlo+" – takto sa to volá aplikáciu.

A: Hovorili ste, že sa streamuje klientom?..

MSC: Streamingovým videom sme sa nezaoberali. To úplne robil "Megafon". Áno, nespomenul som, že aplikácia je od megafonu.

MSC: – Go – na prenos všetkých údajov – o faktúre, o udalostiach zápasu, štatistikách… Go – to je celý backend pre aplikáciu. Klient sa musí niekde dozvedieť, aký odkaz použiť pre prehrávač, aby mohol používateľ sledovať zápas. Máme odkazy na videá a streamy, ktoré sú pripravené.

Prehrajte video

Trochu reklamy 🙂

Ďakujeme, že ostávate s nami. Páčia sa vám naše články? Chcete vidieť viac zaujímavých materiálov? Podporte nás, vytvorením objednávky alebo odporúčaním známym, cloud VPS pre vývojárov od 4,99 dolárov, unikátny ekvivalent entry-level serverov, ktorý sme pre vás vytvorili: Celá pravda o VPS (KVM) E5-2697 v3 (6 jadier) 10GB DDR4 480GB SSD 1Gbps od 19 dolárov alebo ako správne rozdeliť server? (k dispozícii varianty s RAID1 a RAID10, až 24 jadier a až 40GB DDR4).

Dell R730xd je dvakrát lacnejší v dátovom centre Equinix Tier IV v Amsterdame? Len u nás 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TB od 199 dolárov v Holandsku! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — od 99 dolárov! Prečítajte si o tom Ako vybudovať infraštruktúru korporátneho typu s použitím serverov Dell R730xd E5-2650 v4 s cenou 9000 eur za zlomok ceny?

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster