Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Аляксей Найдзёнаў, CEO ITooLabs, Распавядае пра распрацоўку тэлекамунікацыйнай платформы для аператараў сувязі на мове праграмавання Go (Golang). Аляксей таксама дзеліцца досведам разгортвання і эксплуатацыі платформы ў адным з найбуйных азіяцкіх аператараў сувязі, які выкарыстаў платформу для аказання паслуг галасавой пошты (VoiceMail) і Віртуальнай АТС (Cloud PBX).

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Аляксей Найдзёнаў (далей - АН): - Ўсім прывітанне! Мяне клічуць Аляксей Найдзёнаў. Я - дырэктар кампаніі ITooLabs. Перш за ўсё я хацеў бы адказаць, што тут раблю і якім чынам тут апынуўся.

Калі вы паглядзіце Bitrix24 Marketplace (раздзел "Тэлефанія"), то 14 прыкладанняў і 36, якія там ёсць (40%) - гэта мы:

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Дакладней сказаць, гэта нашы партнёры-аператары, але за ўсім гэтым стаіць наша платформа (Platform as a Service) - тое, што мы ім прадаем за невялікую капейчыну. Уласна, аб развіцці гэтай платформы і аб тым, як мы дашлі ў Go, я бы і жадаў распавесці.

Лічбы па нашай платформе зараз:

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

44 партнёра-аператара, уключаючы "Мегафон". Мы, наогул кажучы, вельмі каханы пускацца ў розныя авантуры, і ў нас ёсць фактычны доступ да 100 мільёнаў абанентаў 44 аператараў тут, у Расіі. Таму, калі ў некага будуць з'яўляцца нейкія бізнес-ідэі, мы заўсёды іх з радасцю выслухаем.

  • 5000 кампаній-карыстальнікаў.
  • 20 000 абанентаў у суме. Гэта ўсё b2b - мы працуем толькі з кампаніямі.
  • 300 выклікаў у хвіліну днём.
  • 100 мільёнаў хвілін выклікаў за мінулы год (мы гэта адсвяткавалі). Гэта без уліку ўнутраных перамоваў, якія ёсць на нашай платформе.

Як гэта пачыналася?

Як увогуле правільныя чувакі пачынаюць рабіць сваю платформу? Трэба яшчэ ўлічыць, што ў нас у анамнезе была «хардкор-інтэрпрайз» распрацоўка, ды яшчэ і ў самую дакладную для enterprise пара года! Гэта быў той шчаслівы час, калі прыходзіш да замоўца і кажаш: "Нам трэба яшчэ пару сервераў". А заказчык: «Ды не пытанне! У нас дзясятка ў стойцы стаіць».

Таму мы займаліся Oracle, Java, WebSphere, Db2 і ўсё такое. Таму мы ўзялі, вядома, лепшыя вендорскія рашэнні, інтэгравалі іх і паспрабавалі з гэтым узляцець. Гулялі на свае. Гэта б такі ўнутраны стартап.

Усё гэта ўвогуле пачалося ў 2009 годзе. З 2006-га мы шчыльна займаемся аператарскімі рашэннямі, так ці інакш. Зрабілі некалькі заказных віртуальных АТС (накшталт таго, што ў нас зараз маецца на замову): паглядзелі, вырашылі, што гэта добра, і вырашылі зрабіць унутраны стартап.

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Узялі VMWare. Паколькі шпацыравалі на свае, то прыйшлося адразу адмовіцца ад стромкага вендорскага Storage. Мы ўсё пра іх ведаем: што абяцанні трэба дзяліць на 3, а кошт памнажаць на 10. Таму рабілі DirDB і гэтак далей.

Потым яно пачало расці. Да гэтага дадаўся сэрвіс білінгу, таму што платформа перастала спраўляцца. Затым серэр білінгу з MySQL сышоў на Mongo. У выніку атрымалася працуючае рашэнне, якое перапрацоўвае ўсе выклікі, якія туды ідуць:

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Але недзе там, унутры, круціцца той самы вендорскі прадукт – галоўны, ядзерны, які мы некалі ўзялі. Прыкладна да канца 2011 года мы для сябе зразумелі, што галоўным бутэлькавым горлышкам для нас, вядома, будзе з'яўляцца менавіта гэты прадукт - мы ў яго ўпрэмся. Мы бачылі перад сабой сцяну, у якую беглі на поўным скаку, паколькі кліенты ішлі, дадаваліся.
Адпаведна нам трэба было нешта рабіць. Вядома, мы правялі даволі доўгія даследаванні з нагоды розных прадуктаў - і open source, і вендорскіх. Я не буду зараз на гэтым спыняцца - не пра тое гаворка. Самы апошні запасны варыянт, аб якім мы думалі - гэта рабіць сваю ўласную платформу.

У канчатковым выніку мы дашлі менавіта да гэтага варыянту. Чаму? Таму што ўсе вендорскія і open source прадукты рабіліся для рашэння праблем 10-летняй даўнасці. Добра, калі 10-гадовай, а некаторыя і больш! Для нас стаў відавочны выбар: альбо мы развітваемся з нашай цудоўнай ідэяй аб ідэальнай паслузе (для партнёраў, аператараў і сябе), альбо мы робім нешта сваё.

Мы вырашылі рабіць нешта сваё!

Патрабаванні да платформы

Калі доўга нечым займаешся (эксплуатуеш чужы прадукт), то ў галаве паціху складваюцца думка: а як бы я гэта зрабіў сам? Паколькі мы ў кампаніі ўсе праграмісты (акрамя прадаўцоў, не праграмістаў няма), то патрабаванні ў нас склаліся даўно, і яны былі зразумелыя:

  1. Высокая хуткасць распрацоўкі. Вендорскі прадукт, які нас мучыў, не задавальняў у першую чаргу тым, што ўсё атрымлівалася доўга і павольна. Мы хацелі хутка - у нас было шмат ідэй! У нас і зараз шмат ідэй, але тады спіс ідэй быў такі, што здавалася, нібыта наперад гадоў на дзесяць. Цяпер толькі на год.
  2. Максімальная ўтылізацыя шмат'ядравага жалеза. Гэта таксама для нас было важна, бо мы бачылі, што ядраў будзе станавіцца толькі больш і больш.
  3. Высокая надзейнасць. Тое, з чым мы таксама наплакаліся.
  4. Высокая ўстойлівасць да збояў.
  5. Мы хацелі прыйсці ў канчатковым выніку да працэсу са штодзённымі рэлізамі. Для гэтага нам патрэбен быў выбар мовы.

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Адпаведна, з патрабаванняў да прадукта, якія мы для сябе прад'явілі, вырастаюць відавочна лагічным чынам патрабаванні да мовы.

  1. Калі мы хочам падтрымкі мультыядзерных сістэм, то нам патрэбна падтрымка паралельнага выканання.
  2. Калі нам патрэбна хуткасць распрацоўкі - нам патрэбна мова з падтрымкай канкурэнтнай распрацоўкі, канкурэнтнага праграмавання. Калі хто не сутыкаўся з розніцай, то яна вельмі простая:
    • раўналежнае праграмаванне – гэта пра тое, як два розных струменя выконваюцца на розных ядрах;
    • канкурэнтнае выкананне, дакладней падтрымка канкурэнтнасці - гэта пра тое, як мова (або runtime, усё роўна) дапамагае схаваць усю складанасць, якая выцякае з паралельнага выканання.
  3. Высокая ўстойлівасць. Відавочна, што нам патрэбен быў кластар, прычым лепш, чым у нас быў на вендорскім прадукце.

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Варыянтаў у нас было не так шмат насамрэч, калі ўспомніць. Па-першае, "Эрланг" - мы яго любім і ведаем, гэта быў мой асабісты, персанальны фаварыт. Па-другое, Java нават не Java, а менавіта Scala. Па-трэцяе, мова, якую на той момант часу мы ўвогуле не ведалі – Go. Ён тады толькі-толькі з'явіўся, дакладней, прыкладна два гады ўжо існаваў, але яшчэ не выйшаў у рэліз.

Перамог Go!

Гісторыя Go

Мы зрабілі платформу на ім. Паспрабую растлумачыць чаму.

Кароткая гісторыя Go. Стартаваў у 2007-м, адкрыты ў 2009-м, першая версія выйшла ў 2012-м (гэта значыць мы пачалі працаваць яшчэ да першага рэлізу). Ініцыятарам выступаў Google, які хацеў замяніць у сябе, як я падазраю, Java.

Аўтары - вельмі знакамітыя:

  • Кен Томсан, які стаяў за Unix'ам, прыдумаў UTF-8, працаваў над сістэмай Plan 9;
  • Роб Пайк, які разам з Кенам прыдумляў UTF-8, таксама працаваў над Plan 9, над Inferno, Limbo у Bell Labs;
  • Роберт Гізмер, якога мы ведаем і кахаем за тое, што ён прыдумаў Java HotSpot Compiler, і за тое, што ён працаваў над генератарам у V8 (інтэрпрэтатары Javascript'а ад Google);
  • І больш за 700 удзельнікаў, у тым ліку некаторыя нашы патчы.

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Go: першы погляд

Мы бачым, што мова больш-менш простая, зразумелая. У нас ёсць відавочныя тыпы: у некаторых выпадках іх трэба аб'яўляць, у некаторых - не трэба (гэта значыць, што тыпы выводзяцца, так ці інакш).

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Відаць, што модна апісваць структуры. Відаць, што ў нас ёсць паняцце паказальніка (там, дзе зорачка). Відаць, што ёсць спецыяльная падтрымка для аб'яўлення ініцыялізацыі масіваў і асацыятыўных масіваў.

Прыкладна зразумела - жыць можна. Спрабуем напісаць Hello, world:

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Што бачым? Гэта Сі-падобны сінтаксіс, кропка з коскай неабавязковая. Яна можа быць падзельнікам для двух радкоў, але толькі ў тым выпадку, калі гэта дзве канструкцыі, якія менавіта на адным радку.

Бачым, што дужкі ў кіруючых структурах (у 14-м радку) неабавязковыя, а вось фігурныя абавязковыя заўсёды. Бачым, што тыпізацыя статычная. Цім у большасці выпадкаў выводзіцца. Гэты прыклад крыху складаней звычайнага Hello, world – проста для таго, каб паказаць, што ёсць бібліятэка.

Што яшчэ бачым важнага? Код арганізаваны ў пакеты. І для таго каб пакет выкарыстоўваць у сваім уласным кодзе, неабходна яго імпартаваць пры дапамозе дырэктывы import - гэта таксама важна. Запускаем - працуе. Выдатна!

Спрабуем далей што-небудзь больш складанае: Hello, world, але толькі зараз гэта http-сервер. Што бачым цікавага тут?

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Па-першае, функцыя выступае параметрам. Гэта азначае, што функцыя ў нас - «першакласны грамадзянін» і з ім можна рабіць шмат усяго цікавага ў функцыянальным стылі. Бачым далей нечаканае: дырэктыва import спасылаецца непасрэдна на рэпазітар GitHub. Усё дакладна, так і ёсць - больш за тое, так і трэба рабіць.

У Go універсальным ідэнтыфікатарам пакета з'яўляецца url яго рэпазітара. Ёсць спецыяльная ўтыліта Goget, якая сыходзіць за ўсімі залежнасцямі, запампуе іх, усталюе, скампілюе і падрыхтуе да выкарыстання, калі гэта неабходна. Пры гэтым Goget ведае пра html-meta. Адпаведна, можна трымаць http-каталог, у якім будуць спасылкі на канкрэтны свой рэпазітар (як мы, напрыклад, які робіцца).

Што мы яшчэ бачым? Http і Json у штатнай бібліятэцы. Ёсць, відавочна, інтраспекцыя - reflection, якая павінна выкарыстоўвацца ў encoding/json, таму што мы яму падстаўляем проста нейкі адвольны аб'ект.

Запускаем і бачым, што ў нас у 20 радкоў уклаўся карысны код, які кампілюецца, запускаецца і аддае бягучую сярэднюю загрузку машыны (на машыне, на якой ён запушчаны).
Што яшчэ важна з таго, што мы можам тут убачыць? Яно кампілюецца ў адзін статычны бінарнік (buinary). У гэтага бінарніка ўвогуле няма ніякіх залежнасцяў, ніякіх бібліятэк! Яго можна скапіяваць на любую сістэму, адразу запусціць, і яно будзе працаваць.

Рухаемся далей.

Go: метады і інтэрфейсы

У Go ёсць метады. Вы можаце аб'явіць метад для любога карыстацкага тыпу. Прытым гэта неабавязкова структура, а можа быць або нейкага тыпу. Вы можаце аб'явіць alias для N32 і пісаць для яго метады, каб рабіць што-небудзь карыснае.

І вось тут мы ўпершыню ўпадаем у ступар… Высвятляецца, што ў Go няма класаў як такіх. Тыя, хто ведае Go, можа сказаць, што там ёсць уключэнне тыпаў, але гэта зусім іншае. Чым раней распрацоўшчык перастане думаць аб гэтым як аб атрыманні ў спадчыну, тым лепш. У Go класаў няма, і ўспадкоўванні таксама няма.

Пытанне! Што ж кампанія аўтараў пад кіраўніцтвам Google дала нам для таго, каб адлюстроўваць усю складанасць свету? Нам далечы інтэрфейсы!

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

Інтэрфейс - гэта такі спецыяльны тып, які дазваляе напісаць проста метады, сігнатуры метадаў. Далей любы тып, для якога гэтыя метады існуюць (выконваюцца), будзе адпавядаць гэтаму інтэрфейсу. Гэта значыць, што вы можаце проста апісаць адпаведную функцыю для аднаго тыпу, для іншага (які адпавядае таму тыпу інтэрфейсу). Далей - абвясціць зменную тыпу гэтага інтэрфейсу і прысвоіць ёй любы з гэтых аб'ектаў.

Для аматараў хардкора магу сказаць, што ў гэтай зменнай будзе насамрэч два паказальнікі: адзін – на дадзеныя, іншы – на адмысловую табліцу дэскрыптараў, якая характэрна менавіта для гэтага, канкрэтнага тыпу, для інтэрфейсу гэтага тыпу. Гэта значыць кампілятар такія табліцы дэскрыптараў робіць на момант лінкоўкі.

І ёсць у Go, вядома, паказальнікі на void. Слова interface {} (з двума фігурнымі дужкамі) - гэта пераменная, якая дазваляе паказваць наогул на любы аб'ект у прынцыпе.
Пакуль што ўсё ў парадку, усё звыкла. Нічога дзіўнага.

Go: goroutines

Цяпер падыходзім да таго, што зацікавіла: легкаважныя працэсы - goroutines (гаруціны) у тэрміналогіі Go.

Аляксей Найдзёнаў. ITooLabs. Кейс распрацоўкі на Go (Golang) тэлефоннай платформы. Частка 1

  1. Па-першае, яны сапраўды легкаважныя (менш за 2 Кб).
  2. Па-другое, выдаткі на стварэнне такой гаруціны нікчэмныя: іх можна ствараць тысячу ў секунду - нічога не будзе.
  3. Абслугоўваюцца яны сваім уласным планавальнікам, які проста перадае кіраванне ад адной гаруціны ў іншую.
  4. Пры гэтым кіраванне перадаецца ў наступных выпадках:
    • калі сустракаецца выраз go (калі гаруціна запускае наступную гаруціну);
    • калі ўключаецца блакуючы выклік Input/Out;
    • калі запускаецца зборка смецця;
    • калі запускаецца нейкая аперацыя з каналамі.

Гэта значыць кожны раз, калі праграма на Go запускаецца на кампутары, яна вызначае колькасць ядраў у сістэме, запускае столькі патокаў, колькі трэба (колькі ядраў у сістэме або колькі вы ёй сказалі). Адпаведна, планавальнік будзе запускаць гэтыя легкаважныя патокі выканання ва ўсіх гэтых патоках аперацыйнай сістэмы ў кожным ядры.

Трэба адзначыць, што гэта максімальна эфектыўны спосаб утылізацыі жалеза. Акрамя паказанага мы робім яшчэ шмат чаго. Мы робім, напрыклад, сістэмы DPI, якія дазваляюць у адзін unit абслугоўваць 40 гігабіт (гледзячы што адбываецца ў гэтых радках).

Там мы яшчэ да Go выкарыстоўвалі роўна тую ж схему менавіта па гэтым чынніку: таму што гэта дазваляе захоўваць лакальнасць кэша працэсара, значна зменшыць колькасць пераключэнняў кантэксту АС (што таксама займае вельмі шмат часу). Паўтаруся: гэта - максімальна эфектыўны спосаб утылізаваць жалеза.

Гэты просты прыклад у 21 радок - прыклад, які робіць проста echo-server. Пры гэтым звернеце ўвагу, што функцыя serve - лімітава простая, яна лінейная. Там няма ніякіх колбэкаў, ніякай патрэбы затлумляцца і думаць… Вы проста чытаеце і пішаце!

Пры гэтым, калі вы чытаеце і пішаце, яно насамрэч павінна заблакавацца - гэта гаруціна проста кладзецца ў чаргу і дастаецца планавальнікам тады, калі зноў стане магчыма выкананне. Гэта значыць, гэты просты код можа працаваць рэха-серверам на столькі злучэнняў, колькі дазволіць АС на гэтай машыне.

Працяг будзе зусім хутка…

Крыху рэкламы 🙂

Дзякуй, што застаяцеся з намі. Вам падабаюцца нашыя артыкулы? Жадаеце бачыць больш цікавых матэрыялаў? Падтрымайце нас, аформіўшы замову ці парэкамендаваўшы знаёмым, хмарныя VPS для распрацоўшчыкаў ад $4.99, унікальны аналаг entry-level сервераў, які быў прыдуманы намі для Вас: Уся праўда аб VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps ад $19 ці як правільна дзяліць сервер? (даступныя варыянты з RAID1 і RAID10, да 24 ядраў і да 40GB DDR4).

Dell R730xd у 2 разы танней у дата-цэнтры Equinix Tier IV у Амстэрдаме? Толькі ў нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТБ ад $199 у Нідэрландах! Dell R420 – 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB – ад $99! Чытайце аб тым Як пабудаваць інфраструктуру корп. класа c ужываннем сервераў Dell R730xd Е5-2650 v4 коштам 9000 еўра за капейкі?

Крыніца: habr.com

Дадаць каментар