Начал изучать новый низкоуровневый язык программирования Rust. Ну как низкоуровневый, ну ниже точно чем Node.Js. На нем можно работать с оперативной памятью и командывать потоками и процессами как тебе вздумается.
В процессе изучения пишу свой pet-проект на github, в котором есть интеграция с OpenAI (ChatGPT) и TTS сервисом. Планирую еще сделать интеграцию с каким нибудь AI для генерации изображений (например dreamstudio.ai).
Так-же пришлось написать маленький срипт на Python с использованием FastAPI и Silero AI для TTS запросов. Бот умеет отвечать голосом, зачитывая ответы с ChatGPT. Для этого пришлось поднять отдельный сервис.
Этот пет уже отлично себя показал. Он помогает мне в ежедневной работе, помог составить грамотную страницу профиля для github ну и бесконечно отвечает на мои вопросы по изучению Rust.
Кстати, превью для этой записи, я тоже сгенерировал на dreamstudio.ai
Понадобилось выгружать определенные метрики по событиям из приложения, на Nodejs. Например, инкрементировать метрику в случае успешного ответа и т.п.
Из подручных средств был забикс и графана.
Оказалось что для nodejs есть модуль prom-client который умеет экспортировать метрики, но вот незадача — с pm2 как и другие модули он работать не умеет.
Проблема в том, что метрика собранная в одном процессе, не может нормально получена в другом процессе, который отвечает за http предоставление метрики zabix агенту.
Сегодня поговорим о деплое с нулевым даунтаймом в NodeJs приложении.
Для того что бы это было возможным, ваше приложение должно быть запущено в child process. Например используйте PM2 / ts-node-dev
Итак:
Первое что нам нужно сделать, это сообщить о том, что новый (задеплоенный) процесс готов принимать на себя работу передеплоемого приложения. Для этого необходимо вызвать
process.send(“ready”)
В вашем приложении, после того как все необходимые зависимости перейдут в состояние готовности. Например коннект с базой установится и т.п.
Так же в нашем приложении нужно добавить логику, по завершению всех текущих операций при получении сигнала терминации (SIGINT)
process.on(“SIGINT”, () => {
this.connection.close(); // Например закроем текущие соединение с AMQP и перестанем принимать новые сообщения
setTimeout(() => {
process.exit()
}, 5000) // Подождем 5 сек пока завершаться текущие процессы
})
Запуская такое приложение, например при помощи ts-node-dev, вы можете заметить что после control+c приложение завершается не сразу, а через 5 минут.
Что произойдет:
Новое приложение, запущенное в child process запускается и сообщает ready, после чего начинает бизнес логику
одновременно с этим старому процессу посылается SIGINT и оно переходит в режим завершения работы и финализазции, после чего уничтожается.
Пример
class App {
private isOnline = true
public start() {
console.log(“Started”)
this.restartListener()
this.loop()
}
private loop() {
if (!this.isOnline) return
console.log(“Some business logic like redis/sql/amqp and others operation”)
this.loop()
}
private restartListener() {
if (typeof process.send !== “function”) return
process.send(“ready”)
process.on(“SIGINT”, () => {
this.isOnline = false
setTimeout(() => {
process.exit()
}, 3000)
})
}
}
В этом году постоянно ловлю себя на мысли, что происходит то, что я даже совсем недавно и представить не мог:
Война России с Украиной сопровождающаяся вероятностью применения ядерного оружия, примитивной и кривой пропагандой с разжиганием межнациональной ненависти. Свобода слова исчезла окончательно, инакомыслие наказывается штрафом и тюремным сроком.
Рождение детей и вынужденная эмиграция сначала из Москвы в Сочи (на машине два дня), потом из Сочи в Казахстан вместе с семьей и машиной
Раскол мнений в России привел к конфликтам и ссорам, в том числе между близкими людьми.
Глобальный кризис в IT сфере. Во многих компаниях-гигантах сокращения доходят до тысячи айтишников.
На фоне глобального кризиса и войны многие талантливые разработчики (особенно не семейные) просто отказываются покидать страну (при имеющейся на то возможности) и смиренно ждут, пока их попросят на войну.
ChatGPT уже готов потягаться со многими профессионалами. Сейчас он достаточно неплохо пишет код на всех языках по текстовому ТЗ, можешь найти в любом коде уязвимые места и баги а так-же можешь сочинить неплохой текст на любом языке для linkedin.
На фоне привлекательных зарплат в IT, за последние пару лет образование поставленно на поток, из IT ушла какая-то субкультурность. Очень большой процент специалистов мотивированно исключительно деньгами.
Некоторые пункты переворачивают сознание:
Люди, которые учили нас добру, народному единству, ругали нас за сигареты и драки в школе — поддерживают войну.
Попрежнему остаются люди, абстрагированные от происходящего.
Среди поддерживающих есть и православные.
Израиль бьет по Палестине, что тоже не вызывает особых угнетений у Православного сообщества.
Результат многолетней работы человека на позиции менеджера — обнищание населения, запредельный уровень коррупции и третья мировая война. Но люди продолжат повторять «кто если не он?».
Чему я научился в результате этого
Нужно держаться подальше от любой идеологии, тем более которая насаждает тебе исключительность. Мир — огромен. Знаний и возможностей есть бесконечное множество. Современный Мир дает шанс быть свободным, выбирать дом, в котором тебе сегодня комфортно в любой земного шара.
Прежние колеса были с самого рождения этой машины, поэтому стоило их давно обновить. Да и править я их уже устал. Все таки низкопрофильная резина не способствует сохранению дисков.
Я очень хотел себе SSR Minerva AGLE, но сейчас это очень большая редкость. Поэтому купил что то похожее.
XXR 526 2P. 8,5 ширина у них и 35 вылет. R18. Плюс проставки по 1.2 см
Три года назад я недоумевал почему патриотическое воспитание происходит через милитаризацию: юнармия, концерты с военной тематикой, периодические выставки военной техники. Почему военным такая дешевая ипотека а не ученым? Сегодня же не остается вопросов и курс правительства для меня окончательно ясен.
Мне очень жаль что Россия не имеет своих условных Илонов Масков, Билов Гейтсов, Стивов Джобсов. Очевидно они тут не вырастут в ближайшие 50 лет точно. Агрессия, жажда все отнять у успешного соседа, зависть, хамство, жажда халявы, жажда обмануть ближнего — мне все это не близко и отвратительно.
Уже окончательно ясно, что инновационных разработок, передовые технологии, освоение космоса на моей жизни я уже не увижу в России. Это будут жалкие пародии типо телефонов из китая с операционкой от гугл, и железом из США, пиратство и возможно какие то клоны популярных сервисов, которые всегда будут отставать в технической реализации, будут грязнуть в откатах и распилах.
У меня нет никакого желания принимать участие в компании по импортозамещению покинувших Россию сервисов. Мне хватило уроков, которые я вынес из ситуации с Павлом Дуровым и Вконтакте, Евгением Чичваркиным, и проектом nginx. Я открывал и закрывал ИП, обивал пороги налоговых и роскомнадзора. Все. Хватит, спасибо.
Принял решение в ближайшее время инвестировать в образование и эвакуировать семью и детей. Что бы дети росли свободными, без сумасшедшей цензуры. Что бы они спокойно могли сказать 2*2=4, что бы установка была на созидание а не разрушение.
PS: Да я отлично понимаю что везде в какой то мере присутствует цензура, я так же понимаю что теперь много где к русским отношение будет предвзятое. Но у детей шансов там вырости открытыми всему миру считаю больше чем тут.
В этой небольшой статье ничего не будет про план нумерации астериска. Речь пойдет про ARI — гибкий интерфейс управления Астериском.
Как только в астериск приходит инвайт, и вызов уходит в нашу программу (Stasis) мы получаем возможность для низкоуровневого построения звонка.
Взаимодействие с ARI происходит через прием событий по websocket от астериска, обработку и создания новых событий через HTTP REST API в сторону ARI.
StasisStart
Событие, которое получает наша программа, когда канал вошел в стазис контекст. StasisStart может сигнализировать, например о начале исходящего либо входящего звонка, в результате чего мы запускаем низкоуровневую логику по созданию канала в сторону другого абонента, добавлению его в бридж с каналом инициатором и дозвону.
Упрощенная схема обычного звонка
Получили инвайт (StasisStart) событие от ARI, что сигнализирует о созданном канале A
Создали канал B с эндпоинтом в сторону сип пира, либо в локальный прокси. (пример. SIP/MY_PEER/79001231122)
Канал А из п.1 и B из п.2 объядинили в bridge
Сделали дозвон (dial) в канал B
Подождали ARI событие ChannelStateChange для канала B. И в случае если state — ‘Up’, запускаем ответ в канал A и звонок диалог начинается.
При получении события ChannelHangupRequest для канала A либо B разрушаем звонок.
Сессия звонка
Созданных каналов может быть множество и есть необходимость знать, к каким звонкам относятся события по каким каналам. Поэтому при создании каналов в сторону другого абонента, можно записывать в стор для созданного канала указатель на id канала A, а в сторе для канала A хранить все данные, включая CDR и прочую техническую информацию.
В качестве хранилища я бы рекомендовал использовать redis, так как при больших cps и интенсивных запросах в базу данных может образоваться существенная нагрузка на жесткие диски и просесть производительность.
Оптимизация
Для оптимальной работы вашего ARI приложения под большим cps, я бы рекомендовал свести к минимуму запросы в реляционную базу данных. В своей практике я использовал запросы для небольшой ограничительной логики в момент инициализации звонка и для записи CDR после окончания звонка. Все остальные запросы выполняются в рэдис.
Тест производительности
Для тестирования я использовал консольную утилиту baresip, инициировав баш скриптом 200 дозвонов по пулу тестовых номеров, которые отвечают tt-monkeys.
200 параллельно запущенных звонков сумарно потребили около 5% загрузки на CPU. Все звонки завершились успешно, включая записанные CDR.
Дебаг stasis приложения, которое сигнализирует об отвеченных звонкахSIP сигнализация
Мое третье явление в game dev вышло давольно плодотворным.
Опять моя тоска по закрытому игровому проекту, в котором мы всем кланом боролись с полчищами монстров и в pvp соревнованиях 4×4 и 2×2 одержала верх и я решил попробовать сам написать подобный проект с нуля.
У меня давно было желание попробовать себя в создании игровых миров. Но дальше чтения литературы и создания примитивных прототипов не заходило. Теперь же я настроен на создание рабочего прототипа мобильной многопользовательской игры. Основной ресурс это время, и его всегда не хватает. Конечно после успешного опыта, я планирую отдать модели персонажей, оружия и локации на аутсорс.
Игровой клиент
Для игрового клиента решил использовать движок Unity 3d. При создании рабочего прототипа использовал бесплатные модели, которые находятся в свободном доступе, что бы не сгореть на этапе создания графического дизайна. Хоть у меня за последние три года и появился опыт работы в Blender, но отрисовка 3d моделей отнимает очень много сил. Так что пока из графики мое — только UI.
На этапе альфы планирую:
Уровень COOP сражения (до четырех online игроков) с волнами, в которых игроку предстоит с командой зачистить локацию от разнообразных монстров (от летающих до ползающих) плюс босс на последней волне.
PVP 1v1 на зеркальной арене.
Сервер
Сервер матча я написал на Nodejs. Для коммуникации клиент-сервер использую вебсокет и json формат. Каждый матч инстанцирует процесс, который на определенном сетевом порту обслуживает игровую сессию для всех игровых клиентов матча. Я пока не определил на сколько это хорошая идея использовать tcp протокол а не udp. Но при тестировании с двух устройств одновременно проблем не возникло.
Сейчас сервер успешно спаунит NPC монстров по сценарию из базы данных на все игровые клиенты.
Большая тема для обсуждения — это синхронизация позиционирования и вообще действий игрока, при потере пакетов. Так как может получиться так что у игрока на клиенте персонаж уже находится в точке C, а у всех остальных (из за потери данных) в точке B.
Ассеты
Внутриигровые ассеты, которые могут подвергаться частым изменениям (персонажи. модели, звуки, логика стрельбы) я решил вынести в Asset Bundle и каждый раз при запуске игрового клиента, проверять обновления. Так обычно делают в современных играх, что бы не приходилось при хотфиксах заставлять пользователей постоянно перекачивать приложение из маркета ну и что бы уменьшить первоначальный размер игры дабы не отпугнуть игрока.
Git репозиторий
Игра включает в себя код сервера и клиента. Если с сервером при хранении все просто, так как код занимает 4 мегабайта, то с клиентом сложнее. Сырые текстуры для пребилда занимают около гигабайта и будут рости. Поэтому я решил собрать дома свой гит сервер на raspberry pi 4.
Приобрел raspberry pi 4, а так-же корпус к нему, куллер и ssd на m2 сокете на 512GB и сливаю весь код локально на raspberry.
raspberry pi 4 в корпусе m2 Argon выглядит как тв приставка
Так же я поднял на нем копию сервера и тестирую весь игровой процесс локально с двух компьютеров. Думаю позже покажу как забавно выглядят со стороны мои тесты.
Финал
Мне пришла идея логировать все изменения и наработки по игре в телеграм канал https://t.me/sniperhit так же я завел домен с рабочий названием, где добавил виджет на канал https://sniperhit.ru/. Далее думаю все новости по проекту писать только туда.
С тех пор, как я стал тимлидом большой команды, ежедневно передо мной стоит множество вопросов. Как эффективно построить команду, которой будет интересно работать, и которая будет показывать работоспособность и продуктивность. Как вовлечь команду, и т.п. Поскольку, раньше я занимался только программированием и у меня не было опыта управления и постройки команд, то переодически я стараюсь обучаться и заполнять пробелы.
Эта программа, конечно открывает на многое глаза. Мне повезло! Я смог познакомится с Baba Shiv и другими классными преподавателями из Стэндфорта а так же пообщаться с другими CEO и менеджерами и узнать какие у них возникают проблемы и как они их решают.