Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Mikhail Salosin (hjirnei - MS): - Hoi allegearre! Myn namme is michael. Ik wurkje as backend-ûntwikkelder by MC2 Software, en ik sil prate oer it brûken fan Go yn 'e efterkant fan' e Look+ mobile applikaasje.

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Hat immen hjir fan hockey?

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Dan is dizze applikaasje foar jo. It is foar Android en iOS en wurdt brûkt om útstjoerings fan ferskate sporteveneminten online te besjen en opnommen. De applikaasje befettet ek ferskate statistiken, tekstútstjoerings, tabellen foar konferinsjes, toernoaien en oare ynformaasje nuttich foar fans.

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Ek yn 'e applikaasje is d'r sa'n ding as fideomominten, d.w.s. jo kinne de wichtichste mominten fan wedstriden besjen (doelpunten, gefjochten, shootouts, ensfh.). As jo ​​​​net de heule útstjoering wolle besjen, kinne jo allinich de meast nijsgjirrige sjen.

Wat hawwe jo brûkt yn ûntwikkeling?

It haaddiel is skreaun yn Go. De API wêrmei mobile kliïnten kommunisearren waard skreaun yn Go. In tsjinst foar it ferstjoeren fan push-notifikaasjes nei mobile tillefoans waard ek skreaun yn Go. Wy moasten ek ús eigen ORM skriuwe, dêr't wy miskien wol ris oer prate. No, guon lytse tsjinsten waarden skreaun yn Go: ôfbylding feroarje en laden foar de bewurkers ...

Wy brûkten PostgreSQL as de databank. De bewurkerynterface is skreaun yn Ruby on Rails mei de ActiveAdmin-gem. It ymportearjen fan statistiken fan in statistykprovider wurdt ek skreaun yn Ruby.

Foar systeem API-tests brûkten wy Python unittest. Memcached wurdt brûkt om API-betellingsoproppen te smoaren, "Chef" wurdt brûkt om konfiguraasje te kontrolearjen, Zabbix wurdt brûkt om ynterne systeemstatistiken te sammeljen en te kontrolearjen. Graylog2 is foar it sammeljen fan logs, Slate is API-dokumintaasje foar kliïnten.

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Protokol seleksje

It earste probleem dat wy tsjinkamen: wy moasten in protokol kieze foar ynteraksje tusken de backend en mobile kliïnten, basearre op de folgjende punten ...

  • De wichtichste eask: gegevens oer kliïnten moatte yn realtime bywurke wurde. Dat is, elkenien dy't op it stuit nei de útstjoering sjocht, moat hast daliks updates krije.
  • Om dingen te ferienfâldigjen, hawwe wy oannommen dat gegevens dy't syngronisearre binne mei kliïnten net wiske wurde, mar ferburgen wurde mei spesjale flaggen.
  • Alle soarten seldsume oanfragen (lykas statistiken, teamkomposysjes, teamstatistiken) wurde krigen troch gewoane GET-oanfragen.
  • Plus, it systeem moast maklik 100 tûzen brûkers tagelyk stypje.

Op grûn dêrfan hiene wy ​​twa protokolopsjes:

  1. Websockets. Mar wy hienen gjin kanalen nedich fan 'e kliïnt nei de tsjinner. Wy hoege allinich updates fan 'e tsjinner nei de kliïnt te stjoeren, dus in websocket is in oerstallige opsje.
  2. Server-Sent Events (SSE) kaam krekt goed! It is frij simpel en foldocht yn prinsipe alles wat wy nedich binne.

Server-ferstjoerd eveneminten

In pear wurden oer hoe't dit ding wurket ...

It rint boppe op in http-ferbining. De client stjoert in fersyk, de tsjinner reagearret mei Content-Type: text/event-stream en slút de ferbining net mei de client, mar bliuwt gegevens te skriuwen nei de ferbining:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Gegevens kinne stjoerd wurde yn in formaat ôfpraat mei kliïnten. Yn ús gefal hawwe wy it yn dizze foarm stjoerd: de namme fan 'e feroare struktuer (persoan, spiler) waard stjoerd nei it evenemintfjild, en JSON mei nije, feroare fjilden foar de spiler waard stjoerd nei it gegevensfjild.

No litte wy prate oer hoe't de ynteraksje sels wurket.

  • It earste ding dat de klant docht is bepale de lêste kear dat syngronisaasje mei de tsjinst waard útfierd: it sjocht nei syn lokale databank en bepaalt de datum fan 'e lêste feroaring dy't troch it is opnommen.
  • It stjoert in fersyk mei dizze datum.
  • As antwurd stjoere wy him alle updates dy't sûnt dy datum bard binne.
  • Dêrnei makket it in ferbining mei it live kanaal en slút it net oant it dizze updates nedich is:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Wy stjoere him in list mei feroarings: as immen in doelpunt makket, feroarje wy de skoare fan 'e wedstriid, as hy blessearre wurdt, wurdt dit ek yn realtime ferstjoerd. Sa krije kliïnten daliks aktuele gegevens yn 'e feed foar wedstriidevenemint. Periodyk, sadat de kliïnt begrypt dat de tsjinner net ferstoarn is, dat der neat mei bard is, stjoere wy elke 15 sekonden in tiidstempel - sadat it wit dat alles yn oarder is en d'r gjin ferlet is om opnij te ferbinen.

Hoe wurdt de live ferbining betsjinne?

  • As earste meitsje wy in kanaal wêryn buffered updates sille wurde ûntfongen.
  • Dêrnei abonnearje wy dit kanaal om updates te ûntfangen.
  • Wy sette de juste koptekst sadat de klant wit dat alles goed is.
  • Stjoer de earste ping. Wy registrearje gewoan it hjoeddeistige ferbiningtiidstempel.
  • Dêrnei lêze wy fan it kanaal yn in lus oant it fernijingskanaal sletten is. It kanaal ûntfangt periodyk de aktuele tiidstempel of wizigingen dy't wy al skriuwe om ferbiningen te iepenjen.

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

It earste probleem dat wy tsjinkamen wie it folgjende: foar elke ferbining iepene mei de kliïnt, makken wy in timer dy't ien kear elke 15 sekonden tikte - it docht bliken dat as wy 6 tûzen ferbiningen iepen hiene mei ien masine (mei ien API-tsjinner), 6 tûzen timers waarden makke. Dat late der ta dat de masine net de fereaske lading hold. It probleem wie net sa dúdlik foar ús, mar wy krigen in bytsje help en reparearre it.

As gefolch, no komt ús ping fan itselde kanaal wêrfan update komt.

Dêrtroch is d'r mar ien timer dy't ien kear elke 15 sekonden tikt.

D'r binne hjir ferskate helpfunksjes - it ferstjoeren fan de koptekst, ping en de struktuer sels. Dat is, de namme fan 'e tafel (persoan, wedstriid, seizoen) en de ynformaasje oer dizze yngong wurde hjir oerbrocht:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Mechanisme foar it ferstjoeren fan updates

No in bytsje oer wêr't de feroaringen wei komme. Wy hawwe ferskate minsken, redakteuren, dy't de útstjoering yn realtime besjen. Se meitsje alle eveneminten: immen waard stjoerd, immen waard ferwûne, in soarte fan ferfanger ...

Mei it brûken fan in CMS komme gegevens de databank yn. Hjirnei ynformearret de databank de API-tsjinners oer dit mei it Listen/Notify-meganisme. API-tsjinners stjoere dizze ynformaasje al nei kliïnten. Sa hawwe wy yn essinsje mar in pear servers ferbûn mei de databank en d'r is gjin spesjale lading op 'e databank, om't de kliïnt op gjin inkelde manier direkt ynteraksje mei de databank:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

PostgreSQL: Harkje / Notify

It Listen/Notify-meganisme yn Postgres lit jo abonnees fan eveneminten ynformearje dat ien of oare evenemint feroare is - wat record is makke yn 'e database. Om dit te dwaan, hawwe wy in ienfâldige trigger en funksje skreaun:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

By it ynfoegjen of feroarjen fan in record, neame wy de notify-funksje op it data_updates-kanaal, en jouwe dêr de namme fan 'e tabel en de identifier fan it record dat is feroare of ynfoege.

Foar alle tabellen dy't moatte wurde syngronisearre mei de kliïnt, definiearje wy in trigger, dy't, nei it feroarjen / bywurkjen fan in rekord, de funksje neamt oanjûn op 'e dia hjirûnder.
Hoe abonnearret de API op dizze feroarings?

In Fanout-meganisme wurdt makke - it stjoert berjochten nei de kliïnt. It sammelet alle klantkanalen en stjoert updates dy't it ûntfongen is fia dizze kanalen:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Hjir kontrolearret de standert pq-bibleteek, dy't oanslút op de databank en seit dat it nei it kanaal harkje wol (data_updates), dat de ferbining iepen is en alles goed is. Ik lit flaterkontrôle weilitte om romte te besparjen (net kontrolearjen is gefaarlik).

Dêrnei sette wy Ticker asynchronysk yn, dy't elke 15 sekonden in ping sil stjoere, en begjinne te harkjen nei it kanaal wêrop wy ynskreaun hawwe. As wy in ping ûntfange, publisearje wy dizze ping. As wy in soarte fan yngong krije, dan publisearje wy dizze yngong oan alle abonnees fan dizze Fanout.

Hoe wurket Fan-out?

Yn it Russysk wurdt dit oerset as "splitter". Wy hawwe ien objekt dat registrearret abonnees dy't wolle ûntfange wat updates. En sa gau as in fernijing oankomt foar dit objekt, ferspraat it dizze fernijing oan al har abonnees. Ienfâldich genôch:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Hoe wurdt it ymplementearre yn Go:

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

D'r is in struktuer, it wurdt syngronisearre mei Mutexes. It hat in fjild dat bewarret de steat fan Fanout syn ferbining mei de databank, d.w.s. it is op it stuit harket en sil ûntfange updates, likegoed as in list fan alle beskikbere kanalen - map, de kaai fan dat is it kanaal en struktuer yn 'e foarm fan wearden (yn essinsje wurdt it op gjin inkelde manier brûkt).

Twa metoaden - Ferbûn en loskeppele - tastean ús te fertellen Fanout dat wy hawwe in ferbining mei de basis, it is ferskynd, en dat de ferbining mei de basis is brutsen. Yn it twadde gefal moatte jo alle kliïnten losmeitsje en har fertelle dat se neat mear harkje kinne en dat se opnij ferbine om't de ferbining mei har sluten is.

D'r is ek in Subscribe-metoade dy't it kanaal tafoegje oan 'e "harkers":

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

D'r is in metoade foar ôfskriuwing, dy't it kanaal fan harkers ferwideret as de klant loskeart, en ek in metoade foar Publisearje, wêrtroch jo in berjocht kinne stjoere nei alle abonnees.

Fraach: - Wat wurdt troch dit kanaal oerbrocht?

MS: - It model dat is feroare of ping wurdt oerdroegen (yn essinsje gewoan in getal, hiel getal).

MS: - Jo kinne alles ferstjoere, elke struktuer stjoere, it publisearje - it feroaret gewoan yn JSON en dat is it.

MS: - Wy krije in notifikaasje fan Postgres - it befettet de tabelnamme en identifier. Op grûn fan 'e tabelnamme en identifier krije wy it rekord dat wy nedich binne, en dan stjoere wy dizze struktuer foar publikaasje.

Ynfrastruktuer

Hoe sjocht dit der út út in ynfrastruktuerperspektyf? Wy hawwe 7 hardware tsjinners: ien fan harren is folslein wijd oan de databank, de oare seis rinne firtuele masines. D'r binne 6 kopyen fan 'e API: elke firtuele masine mei de API rint op in aparte hardware-tsjinner - dit is foar betrouberens.

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Wy hawwe twa frontends mei Keepalved ynstalleare om tagonklikens te ferbetterjen, sadat as der wat bart, de iene frontend de oare kin ferfange. Ek - twa eksimplaren fan it CMS.

Der is ek in statistyk ymporteur. D'r is in DB-slave wêrfan periodyk backups wurde makke. D'r is Pigeon Pusher, in applikaasje dy't push-notifikaasjes stjoert nei kliïnten, lykas ynfrastruktuerdingen: Zabbix, Graylog2 en Chef.

Yn feite is dizze ynfrastruktuer oerstallich, om't 100 tûzen kinne wurde betsjinne mei minder servers. Mar der wie izer - wy brûkten it (wy waarden ferteld dat it mooglik wie - wêrom net).

Foardielen fan Go

Nei't wy oan dizze applikaasje wurke hawwe, ferskynden sokke foar de hân lizzende foardielen fan Go.

  • Cool http bibleteek. Mei it kinne jo meitsje in soad út 'e doaze.
  • Plus, kanalen dy't ús tastean om in meganisme foar it ferstjoeren fan notifikaasjes nei kliïnten heul maklik te ymplementearjen.
  • De prachtige ding Race detector tastien ús te elimineren ferskate krityske bugs (staging ynfrastruktuer). Alles dat wurket op staging wurdt lansearre, kompilearre mei de Race kaai; en wy, accordingly, kinne sjen op de staging ynfrastruktuer om te sjen hokker potinsjele problemen wy hawwe.
  • Minimalisme en ienfâld fan taal.

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

Wy binne op syk nei ûntwikkelders! As immen wol, asjebleaft.

Jo fragen

Fraach út it publyk (hjirnei – B): – It liket my ta dat jim ien wichtich punt oangeande Fan-out mist hawwe. Begryp ik goed dat as jo in antwurd stjoere nei in klant, jo blokkearje as de klant net lêze wol?

MS: - Nee, wy blokkearje net. As earste hawwe wy dit alles efter nginx, dat is, d'r binne gjin problemen mei trage kliïnten. Twadder hat de kliïnt in kanaal mei in buffer - yn feite kinne wy ​​dêr oant hûndert updates pleatse ... As wy net kinne skriuwe nei it kanaal, dan wisket it it. As wy sjogge dat it kanaal is blokkearre, sille wy it kanaal gewoan slute, en dat is it - de kliïnt sil opnij ferbine as der in probleem ûntstiet. Dêrom is hjir yn prinsipe gjin blokkearjen.

Yn: - Koe it net mooglik wêze om fuortendaliks in rekord te stjoeren nei Listen / Notify, en net in identifiertafel?

MS: - Harkje / Notify hat in limyt fan 8 tûzen bytes op 'e foarladen dy't it ferstjoert. Yn prinsipe soe it mooglik wêze om te stjoeren as wy te meitsjen hiene mei in lyts bedrach fan gegevens, mar it liket my dat dizze manier [de manier wêrop wy it dogge] gewoan betrouberder is. De beheiningen binne yn Postgres sels.

Yn: - Krij klanten updates oer wedstriden wêryn se net ynteressearre binne?

MS: - Yn 't algemien, ja. Yn 'e regel binne der 2-3 wedstriden parallel, en sels dan frij komselden. As in klant wat sjocht, dan sjocht er meastal de wedstriid dy't spilet. Dan hat de kliïnt in lokale databank wêryn al dizze fernijings wurde tafoege, en sels sûnder in ynternetferbining kin de klant alle ferline wedstriden besjen wêrfoar hy updates hat. Yn essinsje syngronisearje wy ús databank op 'e tsjinner mei de lokale databank fan 'e kliïnt, sadat hy offline kin wurkje.

Yn: - Wêrom hawwe jo jo eigen ORM makke?

Alexey (ien fan 'e ûntwikkelders fan Look+): – Destiids (it wie in jier lyn) wiene der minder ORM's as no, as dat der nochal in soad binne. Myn favorite ding oer de measte ORM's is dat de measte fan har rinne op lege ynterfaces. Dat is, de metoaden yn dizze ORM's binne ree om alles oan te nimmen: in struktuer, in struktueroanwizer, in nûmer, wat folslein irrelevant ...

Us ORM genereart struktueren basearre op it gegevensmodel. Myself. En dêrom binne alle metoaden konkreet, brûke gjin refleksje, ensfh Se akseptearje struktueren en ferwachtsje dy struktueren te brûken dy't komme.

Yn: - Hoefolle minsken diene mei?

MS: – Yn de earste faze diene twa minsken mei. Wy begûnen earne yn juny, en yn augustus wie it haaddiel klear (de earste ferzje). Der wie in útjefte yn septimber.

Yn: - Wêr't jo SSE beskriuwe, brûke jo gjin timeout. Wêrom is dat?

MS: – Om earlik te wêzen, is SSE noch altyd in html5-protokol: de SSE-standert is ûntwurpen om te kommunisearjen mei browsers, sa fier as ik begryp. It hat ekstra funksjes sadat browsers opnij ferbine kinne (ensafuorthinne), mar wy hawwe se net nedich, om't wy kliïnten hiene dy't elke logika kinne ymplementearje foar it ferbinen en ûntfangen fan ynformaasje. Wy hawwe gjin SSE makke, mar earder wat fergelykber mei SSE. Dit is net it protokol sels.
Der wie gjin need. Sa fier as ik begryp, kliïnten ymplementearre de ferbining meganisme hast fanôf it begjin. Se makken der net echt om.

Yn: - Hokker ekstra nutsbedriuwen hawwe jo brûkt?

MS: - Wy hawwe it meast aktyf brûkt govet en golint om de styl unifoarm te meitsjen, lykas gofmt. Der waard neat oars brûkt.

Yn: - Wat hawwe jo brûkt om te debuggen?

MS: - Debuggen waard foar it grutste part útfierd mei tests. Wy hawwe gjin debugger of GOP brûkt.

Yn: - Kinne jo de slide weromjaan wêr't de funksje Publisearje is ymplementearre? Ferwarje nammen mei ien-letter fariabele jo?

MS: - Nee. Se hawwe in frij "smel" berik fan sichtberens. Se wurde net brûkt earne oars útsein hjir (útsein foar de internals fan dizze klasse), en it is hiel kompakt - it duorret mar 7 rigels.

Yn: - Op ien of oare manier is it noch net yntuïtyf ...

MS: - Nee, nee, dit is in echte koade! It giet net om styl. It is krekt sa'n utilitaristyske, heul lytse klasse - mar 3 fjilden yn 'e klasse ...

Mikhail Salosin. Golang Meetup. Gebrûk fan Go yn 'e efterkant fan' e Look+-applikaasje

MS: - Yn 't algemien feroaret alle gegevens dy't binne syngronisearre mei kliïnten (seizoenswedstriden, spilers) net. Rûchwei, as wy meitsje in oare sports dêr't wy moatte feroarje de wedstriid, wy sille gewoan nimme alles yn rekken brocht yn de nije ferzje fan de klant, en de âlde ferzjes fan de klant wurdt ferbean.

Yn: – Binne d'r pakketten foar ôfhinklikensbehear fan tredden?

MS: - Wy brûkten go dep.

Yn: - D'r wie wat oer fideo yn it ûnderwerp fan it rapport, mar d'r wie neat yn it rapport oer fideo.

MS: - Nee, ik haw neat yn it ûnderwerp oer de fideo. It hjit "Sjoch +" - dat is de namme fan 'e applikaasje.

Yn: - Jo seine dat it wurdt streamd nei kliïnten? ..

MS: - Wy wiene net belutsen by it streamen fan fideo. Dit waard folslein dien troch Megafon. Ja, ik sei net dat de applikaasje MegaFon wie.

MS: - Gean - foar it ferstjoeren fan alle gegevens - oer de skoare, oer wedstriden, statistiken ... Go is de folsleine efterkant foar de applikaasje. De kliïnt moat fan earne witte hokker keppeling foar de spiler te brûken, sadat de brûker de wedstriid kin besjen. Wy hawwe keppelings nei fideo's en streamen dy't binne taret.

Guon advertinsjes 🙂

Tankewol foar it bliuwen by ús. Hâld jo fan ús artikels? Wolle jo mear ynteressante ynhâld sjen? Stypje ús troch in bestelling te pleatsen of oan te befeljen oan freonen, wolk VPS foar ûntwikkelders fan $ 4.99, in unike analoog fan servers op yngongsnivo, dy't troch ús foar jo útfûn is: De hiele wierheid oer VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps fan $19 of hoe te dielen in tsjinner? (beskikber mei RAID1 en RAID10, oant 24 kearnen en oant 40GB DDR4).

Dell R730xd 2 kear goedkeaper yn Equinix Tier IV data sintrum yn Amsterdam? Allinne hjir 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV fan $199 yn Nederlân! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - fan $99! Lêze oer Hoe kinne jo Infrastructure Corp. klasse mei it brûken fan Dell R730xd E5-2650 v4 tsjinners wurdich 9000 euro foar in penny?

Boarne: www.habr.com

Add a comment