Алексей Найденов. Itoolabs. Кейс Разработки На Телефонной Платформе Go (Golang). Часть 2

Алексей Найденов, генеральный директор ITooLabs , рассказывает о разработке телекоммуникационной платформы для операторов связи на языке программирования Go (Golang).

Также Алексей делится опытом развертывания и эксплуатации платформы в одном из крупнейших азиатских операторов связи, который использовал платформу для предоставления услуг голосовой почты (VoiceMail) и Виртуальной АТС (Cloud PBX).



Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Алексей Найденов.

ITooLabs. Кейс разработки на телефонной платформе Go (Golang).

Часть 1



Перейти: каналы

Понятно, что при параллельном выполнении необходимы средства синхронизации.

Go предоставляет все необходимые инструменты синхронизации: мьютексы, разделяемую память.

Но его стандартный механизм — каналы.

Канал можно рассматривать как однонаправленную типизированную очередь из n элементов (по умолчанию — 1).

Сам канал может быть параметром, членом структуры.

Причем канал можно передавать по каналу — и этот канал будет иметь тип «канал каналов такого-то типа».



Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Что делает этот пример из 20 строк? Это счетчик http-вызовов.

Он просто подсчитывает, где запускается http-сервер, и показывает, сколько раз к этому серверу обращались.

Как это обычно делается? Обычно вы создаете переменную, помещаете ее в мьютекс и увеличиваете ее.

Или вы создаете атомарную переменную и увеличиваете ее атомарно.

В Го все по-другому.

Разработчик, попробовав это на Go, очень быстро начинает писать именно так.

В Go вы запускаете горутинную функцию count (8-я строка) и go count (17-я строка); сделать переменную; а потом просто увеличиваешь локальную переменную — в канал начинает отправляться следующее число.

Те из вас, кто помнил генераторы скриптов Atmos, конечно, будут правы, но в Go каналы допускают гораздо более широкое использование.



Перейти: выбрать

Наконец, есть оператор Select, который позволяет выбирать сразу из нескольких каналов.

Это типичный шаблон в Go для прекращения выполнения горутины:

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Вы передаете два канала.

В один канал идут запросы, а в другой – сигналы о том, что пора заканчивать.



Перейти: C API (CGO)

Для нас, как разработчиков платформы телефонии, было важно, чтобы у Go был C API, который позволяет писать некоторые кусочки на C прямо в коде Go, который потом нормально компилируется, нормально компонуется и потом нормально работает.

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

То есть вы можете получить доступ ко всем библиотекам C, которые есть в вашей операционной системе.

В то же время они также будут связаны статически.



Перейти: инструменты

Инструментарий Go — еще одна причина, по которой людям он нравится.

Все делается с помощью одной команды — (идти).

Существует команда go build, которая выполняет сборку, и команда go test, которая запускает специальные функции тестирования, описанные в конкретном пакете.

Существует команда go run, которая запускается и строит немедленно.

Есть команда, которая обновляет зависимости (go get).

Есть такие, которые форматируют исходники: go fmt - у нас это, например, на пушах.

Больше нет споров о том, где, как и какой стиль форматирования мы используем — табуляция или пробел: есть команда go fmt, есть определенный стиль, который она форматирует, и споров нет. Не нравится что-то? Запустите go fmt - все будет как надо.



Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Команда go doc позволяет читать документацию и отображать ее в формате html. Существует инструмент go pprof для профилирования, генератор синтаксического анализа (gotool yacc) и многое другое.

Короче говоря, инструменты Go очень продвинуты для такого молодого языка.

Многие идеи в нем были не то чтобы новаторскими, но очень интересными, которые позже были перенесены в другие системы — например, тот же Goget и возможность указывать в качестве имени пакета прямой репозиторий.



Перейти: IDE

В целом я предпочитаю Emacs. Если здесь есть любители, мы можем подраться позже.

Но для разработки я предпочитаю «взрослую» IDE:

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Я перепробовал их все, включая VIM. Могу сказать, что на данный момент самая крутая IDE — это обычная, какая-нибудь IDEA Edition с плагином для Go. Лучшее! Я рекомендую.

Если кто-то собирается его использовать, он должен начать сразу и не мучиться.



Перейти: библиотеки

Библиотеки – это был еще один очень и очень приятный сюрприз, потому что буквально каждый раз, когда мы чихали, мы сразу что-то находили.

Даже когда нам понадобился интерпретатор Javascript, мы думали, что придется писать его самим — мы его только нашли, он уже существовал.



Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

На данный момент в Git зарегистрировано более 35 тысяч различных репозиториев, имеющих хотя бы одну звезду.

Могу повторить свою мысль: есть наши библиотеки и другие, и есть множество компаний, которые открывают какие-то свои внутренние библиотеки.

В общем, я не могу вспомнить момент, когда мне что-то понадобилось и я не сразу нашел это на GitHub (в случае с Go).



Перейти: эксплуатация

«Эксплуатация — это мечта, особенно для тех, кто, например, работал с Java.
  • Статическая сборка.

    Никаких зависимостей во время выполнения!

  • Единственный двоичный файл.

    Вплоть до того, что у нас в платформе есть еще один компонент: медиапроцессор, который мы написали на C++ просто потому, что там не так важна скорость разработки, как скорость выполнения.

    Никаких сборщиков мусора! Но в итоге мы тоже стали собирать его со статикой, потому что убедились, насколько это удобно.

  • Никаких зависимостей – вам просто не нужно об этом думать.

    В остальном опыт эксплуатации какой-либо крупной системы вам здесь очень поможет.

  • При падении остаются следы стека.

    Но они нужны довольно редко.



Перейти: сообщество

Сообщество также победило в этом.

Сообщество Go удивительное и восходящая звезда.

К сожалению, информации на слайде мало и ее не видно: слева — репозиторий на GitHub, справа — теги Stack Overflow:

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Если вы посмотрите на Go, то увидите, что он находится в компании языков, которые в пять раз старше его!

Go против Node.js

Боевой! Давайте сравним, например, с Node.js. На самом деле вы можете сравнить это с чем угодно.

Но почему с Node? Я предполагаю, что Google планировал, что Go вытеснит Java и составит конкуренцию Java. Не совсем.

Основным конкурентом Go оказались Node.js, Python и интерпретируемые языки.

Почему? Потому что в Go за счет вывода типов, за счет множества мелких деталей (типа команды go run) возникает ощущение интерпретируемого языка, то есть легкого языка, на котором можно делать макеты, быстро строить и прототипировать что-то.

.

Но при этом он действительно работает: действительно быстро компилируется, запускается и работает. Здесь у нас есть два простых сервера — и http, и http:

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Разница.

  • Он компилируется на Go, интерпретируется в Node.js. Запустил и он сразу работает (ну и там тоже).

  • В Go много потоков (столько, сколько процессоров в машине).

    В Node.js, как вы знаете, есть один поток (если вам нужно много потоков, запустите кластер).

  • Теперь начинаем усложнять логику — усложняем ее в Handler. В Go ничего не усложняешь, просто берешь и делаешь так, как написал линейную программу, которая блокирует (отправляет запрос в базу данных — рассчитывает — отправляет ответ клиенту).

  • А в Node.js сразу возникают вопросы.

    Что вы теперь будете использовать — коллбэки, промисы, Q, async.js или новомодный доходность?

Когда у вас есть такая модель, как Erlang или Go, жизнь становится намного проще.



Идите: недостатки?

Да, вполне!

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

  • Нет параметризованного полиморфизма, шаблонов, дженериков.

    Есть только специальные операции для работы с массивом, массивами и ассоциативными массивами.

    Все остальное отсутствует.

  • Отладчика до сих пор нет. Не то чтобы оно не нужно, но его там нет.
  • Провоцирует стиль вырезания и вставки.

    Если вы пишете на Go достаточно долго, вы обнаружите, что просто берете куски кода и вставляете их — это нормально.

    Вы раздражены тем, что это нормально.

  • Строго диктует правила, в том числе форматирование.

    Я, например, очень люблю Haskell, пишу на нем много домашних проектов для себя, есть простор для фантазии.

    В Го — нет! У вас всегда есть только один, простой и понятный способ что-то сделать.

  • Отступление в сторону начинает выглядеть таким извращением, что вы просто не можете заставить себя это сделать.

    Поэтому нет воображения – надо сосредоточиться на задаче.

  • Никаких исключений.

    Паника/восстановление есть, но их нельзя использовать для контроля.

  • Очень простой синтаксис, который иногда начинает бесить (потом привыкаешь).

  • Здесь нет места фантазии – слишком просто!


Зачем вообще идти?

Может из-за быстрой сборки или из-за развертывания одним бинарником? За счет конкуренции или эффективного использования железа? Может быть, потому, что он быстро растёт, или из-за классного сообщества? Я долго пытался ответить для себя на этот вопрос.

В конце концов я понял: нет, ни одна из этих причин! Все гораздо проще: Go работает.

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Go — чрезвычайно практичный язык для инженеров.

Для инженеров, которые занимаются разработкой веб-сервисов и распределенных систем, на нем можно писать интерфейсы, много чего.

Можно ли на нем написать «Битрикс»? Я не знаю.

Скорее всего нет, потому что интерфейсов слишком много.

Но написать на нем платформу, на которой Битрикс будет работать быстрее (например, шину сообщений) — это то, что нужно, я уверен.



Кто использует Го?

Кто уже успел запрыгнуть в этот вагон?

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

  • Google понятен: у него много проектов, которые используют Go и давно на него перешли.

  • Докер.

  • ИнфлюксДанные.

    Если кто не пробовал, рекомендую.

    Тоже восходящая звезда.

  • Твиттер.

  • Дропбокс.

  • Коддинг.

  • Даже Байду.

    Го, кстати, очень популярен в Китае.

  • Многие другие.

Есть список компаний, которые так или иначе были отмечены и делают какие-то проекты на Go: https://github.com/golang/go/wiki/GoUsers

Что мы сделали в Go? ITooLabs Centrex

Что мы написали в этом году?
  1. Динамический кластер, позволяющий равномерно распределять нагрузку между всеми его узлами (согласно хеш-кольцу).

  2. Использует Protobuffer для внутренней связи.

  3. Использует SIP/HTTP/WebSocket для внешней связи.

  4. Есть медиапроцессор (оставим его в стороне, он на C++).

  5. Он имеет встроенный интерпретатор JavaScript и не является узлом (не нужно возиться с обратными вызовами).

    Он работает так же, как Go: вы пишете в прямом и простом блочном стиле.

    Изначально у нас там был Lua, но, немного помучавшись, мы от него отказались — нашли интерпретатор JavaScript в Go и теперь смело им пользуемся (разработчики довольны).

  6. Что еще мы сделали для себя? Понятно, что когда вы делаете систему, которая, по вашему мнению, должна работать при очень больших нагрузках, первое, что вам нужно сделать, — это нагрузочное тестирование.

    И мы сделали генератор нагрузки/тестер звонков, который может генерировать до 2 тысяч звонков в секунду на двух машинах.

  7. Наша система чрезвычайно дружелюбна к DevOps. Например, чтобы развернуть в производство новое приложение сигнализации, нужно запустить всего одну команду, которая моментально скачает из репозитория конкретную версию этого самого приложения сигнализации, раздаст ее по всем узлам кластера, заменит, и потом в любой момент можно откатиться.

    Для одних клиентов можно будет оставить одну версию, для других — другую.

  8. От решения до первого развертывания у нас прошел 1 год.


О развертывании

Как я уже сказал, примерно в 2012 году мы поняли, что перед нами стена.

Это было довольно страшно.

Мы не сильно ошиблись в своих прогнозах (что пройдет еще два года и это будет крах), потому что в начале 2014 года дела у нас были действительно очень плохи.

И мы быстро перенесли на нашу новую платформу значительную часть генерирующего функционала, в частности записи, всякие внешние транки — то, что генерирует большую нагрузку на ЦП, и с чем старая платформа вендора совершенно не справлялась.



Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2



Случай.

Голосовая почта для 70 миллионов абонентов

Сейчас все это уже успешно работает и почти вся запись, которая идет на платформу, проходит через нашу систему Go. Если долго работать на репутацию, в какой-то момент репутация начинает работать на меня.

И уже давно к нам приходят разные люди из операторов с предложениями что-то сделать.

  • В конце прошлого года «что-то» оказалось системой голосовой почты индонезийского оператора Indosat с 70 миллионами абонентов.

    Мы подумали об этом и сделали его на базе нашей платформы.

    С момента принятия решения (точнее, с момента установки оборудования, потому что это заняло много времени) до момента его развертывания прошло около трёх недель.

  • Система находится на 16 серверах, из которых, обратите внимание, только 7 серверов — это сам Application Service и сервис SIB в Go. Все остальное — медиашлюзы в C++.

    Эти 16 серверов держат 1800 вызовов в секунду и 50 000 одновременных диалогов.

    Это 6,5 млн звонков в час (любимый критерий оператора – BHCA).

  • 280 звонков в секунду — это текущая ежедневная нагрузка, которая есть сейчас.

    Это 1 миллион BHCA на 36 миллионов подписчиков, плюс каждую неделю добавляется 2 миллиона подписчиков.

    Или сейчас, на данный момент, это 100 миллионов звонков в секунду.

  • После того как все это будет запущено в итоге целевая нагрузка составит около 600 звонков в секунду.

    В качестве хранилища записи мы используем Ceph с тройной репликацией.

  • Мы проверили и протестировали: система полностью выдерживает отказ системы до двух серверов.

    То есть их можно просто отключить.

    Именно это и произошло здесь, потому что индонезийцы, прокладывающие кабели, допустили небольшую ошибку.

  • Наконец, мы обычно делаем скользящие обновления.

Можем ли мы сделать это на любом другом языке за такое короткое время? Напомню, с 2012 по 2015 год – 3 года на продукт, который выдерживает такую нагрузку и работает на миллионы индонезийских подписчиков.

Не знаю, но думаю, мы могли бы сделать это на орланге.

Возможно, они могли бы сделать это на Java. Поскольку помимо основной работы я еще читаю лекции по системам реального времени и параллельному программированию в Тульском университете, то для меня одним из окончательных результатов, причин, по которым мы решили использовать Go, стал очень простой эксперимент. Я провел лабораторные работы для студентов и обнаружил, что кривая обучения Go была более крутой, чем у любого другого языка, с которым я когда-либо сталкивался (в этой области).

Студенты стали писать более-менее приличный код, потому что неприличный Go просто не позволял им писать.

Go создает скучный код, и только скучный код! Но это не получается неприлично – это очень сложно.



Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

Могу похвастаться тем, что 31 декабря 2015 года, всего через месяц после развертывания, в системе за один день было зафиксировано 160 тысяч сообщений, которые абоненты передают друг другу.



Вопросы

Вопрос из зала (далее Б): – Большое спасибо за репортаж! Очень интересные случаи.

Скажите, пожалуйста, как сейчас выглядит обработка ошибок в Go? Например, когда я пишу на Node и мне нужно выполнить 5 асинхронных операций подряд, мой код выглядит как 5 строк: подожди, подожди, подожди, подожди, подожди.

АН: – Как я уже сказал, исключений нет. По крайней мере, в том смысле, в котором их можно использовать для контроля и управления.

В: – Как вы справляетесь с ошибками?

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

АН: - если'ами! Повторюсь, Golang позволяет писать довольно скучный код и провоцирует вырезание и вставку.

В: — А сколько таких «если» будет для 5 асинхронных операций, каждая из которых может взорваться? АН: — С моей точки зрения, они будут синхронными (с точки зрения этой горутины).

5 если.

В: – Код увеличивается практически вдвое.

АН: — Наверное, если бы я заплатил разработчикам кода, я бы расстроился.

Но поскольку я плачу за то, чтобы они создавали хороший, работающий код, я в принципе доволен этим.

В: – Возможно ли вообще динамически подключить какую-нибудь библиотеку C? АН: - Да.

В: – То есть этот функционал сохраняется? АН: — Про CGO я показал и рассказал, что он линкуется со статической библиотекой, если она есть, а если нет — подключает динамическую.

Более того, в Go 1.5 в принципе появилось динамическое связывание, и теперь оно позволяет даже создавать динамические библиотеки.

Но мы настолько к этому привыкли, настолько испытали на себе такой механизм, что уже не ощущаем в этом необходимости.

Конечно, вы можете подключить динамические библиотеки C, но не C++.

В: – И двоичный файл в итоге не окажется слишком гигантским? АН: — Нет. Бинарник всей нашей системы, которая обрабатывает все эти вызовы (вместе с интерпретатором JavaScript внутри), занимает всего 6 мегабайт. Это бинарник, который в принципе укладывается во второй кэш.

В: — Я сам часто слышал сравнения: Go часто сравнивают с интерпретируемыми языками, а задача написать полноценную коммуникационную платформу мало у кого стоит. Какие более простые практические случаи существуют?

Алексей Найденов.
</p><p>
 ITooLabs. Кейс разработки на телефонной платформе Go (Golang).
</p><p>
 Часть 2

АН: – Простой случай – это здорово.

Для компании Мегафон мы написали пребиллинг - что-то вроде автобуса, который собирает платформы из разных компонентов (биллинг, Мультифон - у крупного оператора их всегда много), интегрирует все это внутри, заносит в базу данных, рассчитывает что нужно и отправляет события в разные места.

В той же Индонезии есть простой шлюз (пусть и простой, но распределенный), который принимает события от нашей системы и передает их дальше в систему, которая отправляет их на SSD. Вот типа задач - конечно , все это написано очень и очень быстро, что и привлекает.

Немного рекламы :)

Спасибо, что остаетесь с нами.

Вам нравятся наши статьи? Хотите увидеть больше интересных материалов? Поддержите нас, разместив заказ или порекомендовав друзьям, облачный VPS для разработчиков от $4,99 , уникальный аналог серверов начального уровня, который мы придумали для вас: Вся правда о VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps от 19$ или как правильно раздать сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40 ГБ DDR4).

Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только здесь 2 x Intel TetraDeca-Core Xeon, 2 x E5-2697v3, 2,6 ГГц, 14C, 64 ГБ DDR4, 4 твердотельных накопителя по 960 ГБ, 1 Гбит/с, 100 ТВ от 199 долларов США в Нидерландах! Dell R420 — 2x E5-2430, 2,2 ГГц, 6C, 128 ГБ DDR3, 2 твердотельных накопителя по 960 ГБ, 1 Гбит/с, 100 ТБ — от 99 долларов США! Прочтите об этом Как построить корпоративную инфраструктуру класса, используя серверы Dell R730xd E5-2650 v4 стоимостью 9000 евро за копейки? Теги: #программирование #ИТ-инфраструктура #Конференции #Go

Вместе с данным постом часто просматривают: