ru
Feedback

Не попадитесь на канал ботавода! Telemetrio находит и помечает такие каналы 👉 Хотите видеть метку — оформите подписку

OTUS: программирование и карьера в IT

OTUS: программирование и карьера в IT

Открыть в Telegram

Канал для быстрого карьерного роста в IT: опыт практиков, актуальные технологии и инструменты, чтобы быть впереди коллег и привлечь внимание руководителей. Иногда шутим! 🔔Включайте уведомления, чтобы не пропустить!

Больше
7 377
Подписчики
-224 часа
+17 дней
-730 дней
Архив постов
#java #otus И вновь мы хотим порадовать Вас безумно интересной статьёй, но на этот раз о #java https://habrahabr.ru/company/otus/blog/338770/

#deepjava #otus Принято считать, что многопоточность (multithreading) одна из самых сложных тем в программировании. И мы решили посвятить ей не одну, а несколько заметок, которые вы сможете найти по хэштегу #deepjava. В этой заметке мы разберем типы ошибок многопоточного доступа к данным: race condition и memory consistency errors. Но, перед тем как обсуждать ошибки доступа, давайте сначала разберем, что такое многопоточный доступ к данным. В какой именно ситуации можно получить такие ошибки. Мы уже упоминали в предыдущем посте, что поток в Java это объект. У любого объекта есть класс. В классе могут быть методы и переменные. Представьте, что у вас есть класс — наследник от Thread, в котором вы в одной из переменных храните ссылку на массив. И этот массив вы получаете в конструкторе класса. Пусть теперь, в runtime вы создаете два объекта рассмотренного выше класса и передаете в оба один и тот же массив. К элементам этого массива вы можете обращаться в методах run() ваших объектов. Одновременно. Из разных потоков исполнения. Вот это и есть многопоточный доступ к данным которые хранит массив. Например, один поток может писать что-то в массив, а другой читать из него. Рассмотрим теперь ситуацию, когда два рассмотренных выше потока собираются увеличить значение числа, которое записано в первой ячейке массива. Со следующей последовательностью событий: первый поток прочитал значение и увеличил его, второй поток прочитал то же значение, первый записал новое, второй увеличил значение и записал его. В результате вместо ожидаемого увеличения значения на 2 мы получим увеличение на 1, так как результат работы первого потока был “перетерт” результатом работы второго. Такая ситуация происходит из-за неатомарности операции увеличения значения числа. И является разновидностью ошибки многопоточного доступа — race condition. Вторая возможная ошибка многопоточного доступа — memory consistency error происходит из-за того, что разные потоки могут быть физически исполнены на различных процессорах вашего компьютера. Каждый процессор может закэшировать значение переменной у себя, не записывая ее в общую память. В результате разные потоки могут видеть в одно и тоже время разное значение переменной. Описанные выше проблемы призвана решить Java Memory Model. Что это такое и как именно она может помочь разработчику, мы рассмотрим в следующих заметках. И, подробно разберем на занятиях курса “Разработчик Java” в OTUS о которых вы можете узнать подробнее перейдя по ссылке: otus.ru/promo/java-2017/?utm_source=telegram&utm_medium=internal&utm_campaign=java&utm_content=deeppost&utm_term=27.09

Вооружившись этими знаниями, вы сможете в рантайме смотреть за поведением GC и определить, не выросли ли паузы или количество FullGC. Как используется память вашего приложения и как объекты перемещаются между регионами памяти. Понимание этих процессов дает возможность более вдумчиво подойти к настройке вашего приложения. Это малая толика того, что наши преподаватели будут разбирать на наших курсах по Java. Да, не забывайте о том, что их теперь два вида: наш изначальный онлайн-курс на 5 месяцев и оффлайновые курсы при МАИ, где вы сможете получить ещё сертификат о повышении квалификации государственного образца https://otus.ru/promo/java-2017/?utm_source=telegram&utm_medium=internal&utm_campaign=java&utm_content=deeppost&utm_term=19.09

#deepjava #otus О чем говорят логи Garbage Collector Наверняка вы слышали, что сборщик мусора в Java может оказывать значительное влияние на производительность приложения. Многое может зависеть от типа сборщика и его настройки. Есть много инструментов для того, чтобы мониторить различные параметры сборки, но иногда достаточно внимательно посмотреть на логи, которые пишет GC. В этой заметке я расскажу, как выглядят логи, которые пишет сборщик мусора и что с помощью них можно понять о работе вашего приложения. Для начала, нужно запустить JVM, указав специальные параметры: -XX:+PrintGCDetails - печатать детали о событиях сборки мусора -XX:+PrintGCDateStamps - также печатать timestamp этих событий -Xloggc:/home/otus/gc.log - опционально можно указать, в какой файл будут писаться логи, чтобы отделить их от логов вашего приложения. Сборщики мусора SerialGC, ParallelGC, ConcurrentMarkSweepGC (CMS) разбивают память (хип) java-приложения на несколько регионов. Это Eden+Survivor1+Survivor2 - молодое поколение и Tenured - старое поколение. Сборщик GC1 устроен иначе и его стоит рассматривать отдельно. Сборки мусора могут происходить только в молодом поколении - Minor GC или во всех регионах - FullGC. Давайте посмотрим на логи на примере ParallelGC (-XX:+UseParallelGC) В этих логах отображено 3 сборки мусора, сначала 2 minor, затем full: 2017-09-17T21:03:30.200+0300: 0,449: [GC (Allocation Failure) [PSYoungGen: 3662K->336K(4608K)] 3662K->3408K(15872K), 0,0020199 secs] [Times: user=0,01 sys=0,00, real=0,01 secs] 2017-09-17T21:03:30.506+0300: 0,755: [GC (Allocation Failure) [PSYoungGen: 3652K->400K(4608K)] 6724K->6544K(15872K), 0,0021768 secs] [Times: user=0,01 sys=0,00, real=0,00 secs] 017-09-17T21:03:30.815+0300: 1,064: [Full GC (Ergonomics) [PSYoungGen: 400K->0K(4608K)] [ParOldGen: 9216K->9581K(18944K)] 9616K->9581K(23552K), [Metaspace: 3570K->3570K(1056768K)], 0,0047284 secs] [Times: user=0,00 sys=0,00, real=0,01 secs] 2017-09-17T21:03:30.200+0300 - сперва идет timestamp - абсолютное время, когда сборка была начата, затем время относительно старта приложения (0,449) GC (AllocationFailure) - укзаывает, что это минорная сборка, при полной сборке будет указано Full GC. Причина начала сборки: не удалось выделить (allocate) место под новый объект PSYoungGen - тип сборщика. PSYoungGen - это сборка молодого поколения в ParallelGC. Также вы можете встретить DefNew - сборка молодого поколения в SerialGC, ParNew - сборка молодого поколения CMS Дальше идет самая интересная с практической точки зрения часть - занятая память до и после сборки по регионам: [PSYoungGen: 3662K->336K(4608K)] - В молодом поколении до сборки было 3662K, после - 336K. Всего в регионе доступно памяти - 4608K 3662K->3408K(15872K) - Статистика по всему хипу, доступно 15872K. И здесь мы видим интересный момент, что в молодом поколении освободилось 3326K, а общее место в хипе уменьшилось только на 3662 - 3408 = 254К. Это означает, что часть объектов были перемещены из молодого поколения в старое (promoted). Сборка заняла 0,0020199 secs Для FullGC в логах видно статистику по всем регионам памяти, так как сборка запускается и в молодом и в старом поколении. [PSYoungGen: 400K->0K(4608K)] [ParOldGen: 9216K->9581K(18944K)] 9616K->9581K(23552K), [Metaspace: 3570K->3570K(1056768K)], 0,0047284 secs] [Times: user=0,01 sys=0,00, real=0,01 secs] User - user-space время (операции вне ядра ОС), затраченное на GC Sys - kernel-space - время, затраченное на системные вызовы ОС Real - реальное время от начала и до конца сборки мусора. В нем учитывается, то время, пока процесс был прерван ОС или заблокирован (например, на IO) При использовании параллельной сборки User-space время может быть больше чем real-time, потому что user-space будет суммироваться по всем CPU, на которых исполнялась сборка.

Нас часто спрашивали, почему только языки программирования? Как на счет других специальностей в IT? Что делать, если я достаточно хорошо программирую, вырос до senior разработчика и понял, ... что управлять мне нравится сильно больше, чем программировать? Мы вас услышали! И подготовили курс для тех, кто хочет стать хорошим управленцем в сфере IT. Курс затрагивает такие интересные вопросы как правильное взаимодействие с заказчиками, управление изменениями, организацию процессов и финансы. Познакомьтесь с программой сами: http://otus.ru/lessons/it-menedzher/?utm_source=telegram&utm_medium=internal&utm_campaign=itsm&utm_term=welcome Насколько эти темы могут быть интересны - вы скоро оцените сами - ведь мы собираемся выпустить несколько #deeppost на тему IT management. В общем, мы так рады запуску нового курса, что как только открыли возможность прохождения вступительного тестирования - побежали едва ли не всей компанией проверять свои знания :) А вы?

Завершается посадка на очередной рейс обучения в OTUS по курсу “Python для Web-Разработки” Мы провели Дни открытых дверей, разыграли бесплатные места в группе, рассказали об интересных "фишках" в постах #deepwebdev, пригласили тех кто прошел вступительное тестирование в наше профессиональное сообщество, где можно обмениваться опытом и просто приятно и с пользой общаться. Новая группа начинает занятия уже завтра! Это значит, что завтра утром мы закроем возможность оплаты и присоединения к группе. В группе остались последние места - еще есть совсем немного времени, чтобы успеть присоединиться! https://clck.ru/BpEj9 Преподавателем курса стал Илья Лебедев - профессионал своего дела с многолетним опытом разработки! Мы желаем очередной группе успехов в учебе, что курс им понравится! Недавно завершился первый курс “Java-Разработчик” и успешные слушатели уже получили и приняли первые офферы от компаний партнеров, об этом мы обязательно расскажем подробнее в отдельных историях успеха наших выпускников - следите за новостями! Также мы выкатили новый дизайн нашего сайта - он стал еще ярче и вместе с тем удобнее и функциональнее - оцените сами! https://clck.ru/BpEiv

Через пять минут открывается День открытых дверей по нашему замечательному курсу "Python для web-разработки". Приглашаем всех: https://www.youtube.com/channel/UCetgtvy93o3i3CvyGXKFU3g/live P.S. среди тех прошёл тестирование будут разыграны два бесплатных места .

У нас очень, очень, очень классный редизайн Главной страницы: https://otus.ru/?utm_source=telegram&utm_medium=internal&utm_campaign=java Никаких абстрактных картинок и фотобанковских фото! Мы украсили каждый курс своей яркой, неподражаемой совой и добавили странице динамики! Вывели на Главную страницу одну из ключевых ценностей OTUS: наших преподавателей. И, конечно, не забыли и о работодателях. А еще мы обновили меню, добавили блоки с самыми востребованными разделами и напоминания. Нам очень нравится! А вам? :)

Открыт набор в третью группу “Java - Разработчик”, стартуем 14 октября! Что нового? Главная новость третьего набора в том, что теперь программу курса для вас будут вести 2 преподавателя, а это значит что вы получите в два раза больше качественного общения, опыта и знаний. Помимо бессменного Виталия Чибрикова, рады представить для вас второго педагога, Дмитрия Архангельского - специалиста с серьезным кейсом знаний и умений в области. Недавно завершился первый курс “Java-Разработчик” и успешные слушатели уже получили и приняли первые офферы от компаний партнеров, об этом мы обязательно расскажем подробнее - следите за новостями! Что осталось прежним? Качество обучения: авторская программа Виталия Чибрикова, проработанная и успешно прочитанная уже двум курсам, дополненная с учетом вопросов возникающих при работе с аудиторией. Профессиональное сообщество - куда мы рады будем пригласить прошедших вступительное тестирование. Присоединяйтесь, общайтесь и растите профессионально, обмениваться опытом в кругу единомышленников и профессионалов - бесценно! Приглашение на собеседования от наших компаний партнеров на вакансии разработчиков уровня middle для успешных выпускников курса. Удобный формат и график занятий, интересные боевые задачи и прекрасная атмосфера на занятиях и в группах для общения и получения новых знаний. Проходите вступительное тестирование. присоединяйтесь к нам! https://clck.ru/Bnxqs

Внимание!!! До старта курса “Python для Web Разработки” остались считанные дни - начинаем уже в эту субботу! Время пройти вступительное тестирование и присоединиться к группе еще есть: https://clck.ru/BnwYJ 13 сентября в 20-00 по Мск у нас состоится День открытых дверей курса Python для Web-Разработки! Присоединяйтесь к нам в онлайн режиме - из любой точки мира. Познакомимся с преподавателем Ильей Лебедевым, расскажем о проекте, о курсе и программе, ответим на все вопросы, и разыграем бесплатные места в группе, будет интересно!. Программа курса ориентирована на тех, кто уже уверенно владеет основами и хочет прокачаться до уровня middle/senior. Традиционно по результатам курса успешных выпускников пригласят на собеседования наши партнеры - топовые IT компании. Научимся выполнять боевые задачи бекенд-разработки: писать поддерживаемый код, выполнять рефакторинг, проектировать схему базы данных и взаимодействие с ней, организовать работу с ошибками и профилирование, проектировать и развивать схему взаимодействия с клиенсайдом, проводить код-ревью и писать тесты. Преподаватель Илья Лебедев - евангелист Moscow Python, преподаватель курсов Learn Python, сооснователь сервиса Devman.оrg. Знакомьтесь с программой, проходите вступительное тестирование и присоединяйтесь к нам!

#otus #deepwebdev Многие знают только одну команду у pip – install. Этого часто достаточно, но у этого пакетного менеджера есть и другие классные возможности. Давайте рассмотрим некоторые из них. pip list --outdated – покажет, какие из установленных пакетов можно обновить. pip install --user <package> – установит пакет глобально, но в домашнюю директорию. Для этого не нужны права суперпользователя. Не работает в виртуальном окружении. pip show <package> – показывает информацию о пакете, в т.ч. версию, автора и короткое описание. pip search <query> – ищет на PyPI пакеты, в названии или описании которых входит поисковый запрос. Очень полезно, например, если вы забываете полное название какого-то пакета. pip completion --bash >> ~/.profile – эта команда научит bash автодополнению команд. Мелочь, но какая приятная! Это – только часть приятных бонусов, которые нам предоставляет pip. Если захотите больше – добро пожаловать в официальную документацию или на курс Python для Web Разработки. Проходите тестирование и присоединяйтесь к новой группе http://otus.ru/lessons/python-dlja-web-razrabotki/?utm_source=telegram&utm_medium=internal&utm_campaign=webdev&utm_content=deeppost&utm_term=07.09

13 сентября в 20-00 по Мск у нас состоится День открытых дверей курса Python для Web-Разработки! Присоединяйтесь к нам в онлайн режиме - из любой точки мира - будет интересно и полезно! Познакомимся с преподавателем расскажем о проекте, о курсе и программе, ответим на все вопросы, и разыграем бесплатное обучение. Программа курса ориентирована на тех, кто уже уверенно владеет основами и хочет прокачаться до уровня middle/senior. Научимся выполнять боевые задачи бекенд-разработки: писать поддерживаемый код, выполнять рефакторинг, проектировать схему базы данных и взаимодействие с ней, организовать работу с ошибками и профилирование, проектировать и развивать схему взаимодействия с клиенсайдом, проводить код-ревью и писать тесты. Проводить День открытых дверей будет преподаватель Илья Лебедев - евангелист Moscow Python, преподаватель курсов Learn Python, сооснователь сервиса Devman.оrg. Помимо Python 3 (на основе которого разработана программа курса) Илья будет рассказывать всякие интересности про Автотесты, работу с API и много всего прочего, нужного хорошему Веб разработчику! Продолжительность курса - 4 месяца. Традиционно по результатам обучения лучших студентов пригласят на собеседования компании-партнеры. Старт занятий намечен на 16 сентября!! Знакомьтесь с программой, проходите вступительное тестирование и присоединяйтесь к нам! https://clck.ru/Bm85k

Доброе утро. друзья! В рамках набора на наш курс "Python для Web - Разработки" ловите полезную статью :) https://habrahabr.ru/company/otus/blog/337108/

#otus #deepwebdev Итак, у вас есть приложение. Оно запущено в бою, используемо, и вы хотите знать, какие части приложения за какое время работают. Не сломалось ли чего? Как себя ведут технические и бизнес-метрики. Желательно всё это смотреть в красивом интерфейсе и в реальном времени. Рассмотрим один из возможных вариантов для реализации этой задачи. Значения нужных параметров можно хранить в InfluxDB – хранилище данных для временных последовательностей. В него можно класть данные по http-API и получать данные, делая запросы на языке, похожем на SQL. Конечно, есть обёртка вокруг API на Python. Что отслеживать? Во-первых, время выполнения кода основных обработчиков нашего сервиса целиком и отдельных важных его частей. Количество кода будет небольшое – достаточно написать декоратор или менеджер контекста для отправки метрик в InfluxDB. После этого можно заняться мониторингом бизнес-метрик: отдельно записывать количество регистраций, заказов услуг, прочитанных статей в справке. Теперь нужно визуализировать эти данные так, чтобы было видно, насколько хорошо всё работает. Для этого хорошо подходит Grafana – гибкое средство для визуализации и мониторинга, которое умеет брать данные из InfluxDB. Оно же умеет сообщать о том, что какие-то параметры вышли за допустимые границы. На курсе “Python для WEB-разработки” мы разберём, как оптимизировать эту схему для высоконагруженных систем, не превратив при этом систему мониторинга в свалку графиков,а также когда и чем это решение лучше использования Zabbix. Присоединяйтесь, будет интересно! http://otus.ru/lessons/9?utm_source=telegram&utm_medium=internal&utm_campaign=webdev&utm_term=deeppost31.08

#otus #deepwebdev Представьте, что вы разрабатываете модель данных для вашего приложения. Дело ответственное: скоро модель обрастёт другим кодом и для изменения модели придётся переписывать существенную часть приложения. Ошибки при проектировании модели дорогого стоят. Рассмотрим несколько правил, которые позволят снизить количество ошибок. Во-первых, лучше использовать названия из предметной области для моделей и полей. Так, чтобы эксперт в предметной области смог всё понять. О том, как работает приложение этому эксперту знать не нужно: до бизнес-логики дело пока не дошло. Во-вторых, не стоит придумывать новые сущности для упрощения модели. Иногда хочется придумать промежуточную сущность, которая не имеет смысла в предметной области, но позволяет проще уложить данные в хранилище. Это почти всегда плохая идея: новый термин начинает плохо дружить с существующими сущностями, а при реализации бизнес-логики приходится добавлять всё новые и новые костыли. Не говоря уже о том, что придётся всем объяснять смысл нового термина. В-третьих, не нужно упрощать связи. Если у поста может быть много авторов, не надо делать одного потому что в сервисе предусмотрен только один автор. Завтра это требование поменяется и жизнь существенно усложниться. А пока не поменялось, количество лишнего кода можно существенно сократить, но не на уровне модели. Выше перечислены три самые частые ошибки при формировании модели данных. Эти же утверждения лежат в основе Domain Driven Design.

Доброе утро, друзья! Рады сообщить о продолжении набора на курс Python для web разработки! Старт намечен на 16 сентября - вас ждет 4 месяца обучения, за это время прокачаем и подтянем самые необходимые скилы, структурируем уже полученные знания и потренируемся выполнять боевые задачи под руководством Ильи Лебедева, разработчика с более чем шестилетним стажем в области. И, в связи с продолжением набора, ловите еще одну заметку #deeppython #deepwebdev #otus Слышали о GraphQL? Если нет, то давайте вкратце разберем, что это такое и зачем оно нужно. GraphQL – спецификация протокола для общения фронтенда и бекенда. Чтобы получить данные, нужно отправить запрос на сервер, указав, какие именно данные в каком формате нужны. Например, чтобы получить посты указанного пользователя, можно сделать такой запрос: posts(user_id=42, is_draft=False) { title, published_at, text, tags { title, url } } GraphQL обладает плюсами для всех участников. Для фронтендеров есть много оберток вокруг этого протокола, которые существенно упрощают создание различных компонентов. Это радикально снижает количество кода, который нужно написать и упрощает время реализации интерфейса. Для бекендеров плюс в том, что благодаря единой точке входа, можно гибко и просто управлять кешированием, удобно собирать данные из разных источников и собирать разные части данных на разным машинах. И тем и другим удобно то, что вместо большого количества ручек API с разными параметрами, отражающими предметную область, теперь есть только одна, которая позволяет гибко указывать, какие данные нужны, а какие – нет. Graphene – реализация этой спецификации на Python - подробности которой будем разбирать в программе курса - проходите вступительное тестирование и присоединяйтесь! http://otus.ru/lessons/9?utm_source=telegram&utm_medium=internal&utm_campaign=webdev&utm_term=deeppost21.08

Завершается посадка на очередной рейс обучения в OTUS курс “DevOps - Практики и инструменты” Мы провели Два дня открытых дверей, по традиции определили 4 счастливчика, выигравших бесплатные места в группе, рассказали о "фишках" DevOps в постах #deepdevops, создали профессиональное сообщество для успешно прошедших вступительное тестирование, где можно общаться на профессиональные темы. Мы активно знакомили пользователей с нашим продуктом и рассказывали, почему мы больше, чем просто обучающие курсы, отвечали на вопросы и делали много-много всего (в том числе подписали соглашение с 13 партнером, таким важным и долгожданным, как для нас, так и для обучающихся), чтобы наши студенты получили хорошие знания и возможности профессионального и карьерного роста. Новая группа начинает занятия в понедельник! Это значит, что ближе к вечеру понедельника мы закроем возможность оплаты и присоединения к группе. В группе остались последние места - еще есть совсем немного времени, чтобы успеть присоединиться! http://otus.ru/lessons/7?utm_source=telegram&utm_medium=internal&utm_campaign=devops&utm_term=lastcall У нас отличная команда преподавателей - инженеров компании Экспресс 42, и мы искренне рады за наших новых студентов - им точно не будет скучно + у них есть возможность личной профессиональной дискуссии с преподавателями - профессионалами своего дела! Мы желаем ребятам успеха и уверены, что курс им понравится! Совсем скоро - в конце августа и сентябре наши первые выпускники курса Java пойдут на собеседования. Мы с нетерпением ожидаем этого события - ведь мы уверены в своих выпускниках и знаем, что их ждут отличные карьерные перспективы!

Ошибки использования Ansible #devops #otus #ansible #infrastructureascode #iac Ansible одна из самых простых систем управления конфигурацией, она использует декларативное описание конфигурации в YAML формате. Эта простота имеет и обратную сторону медали - используя Ansible без понимания принципов IaC, можно легко скатиться в создание своих bash скриптов, только на Ansible. Чем это плохо? Использование Ansible как bash не обеспечивает идемпотентность. Отсутствие идемпотентности выражается в том, что повторный запуск конфигурационного скрипта может зачастую приводить к неожиданным результатам. В то время, как идея систем управления конфигурацией как Ansible, состоит в том, чтобы привести систему в соответствие с декларативным описанием и не применять конфигурацию дважды для тех компонент, которые уже находятся в требуемом состоянии. Например: - name: устанавливаем Apache (используя модуль yum, определенной версии) yum: name: httpd-2.4.6-67.0.1.el7 - name: устанавливаем Apache (пытаемся использовать Ansible как bash) shell: "yum -y install httpd" Другой частой ошибкой можно назвать отсутствие четкой структуры каталогов с описанием инфраструктуры. Это может быть как сваливание всех YAML файлов в один каталог, так и несогласованное командное взаимодействие, когда один инженер предпочитает одну схему размещения кода, а другой - другую, и в итоге все выглядит хаотичным и весьма сложным для понимания и внесения изменений. Для избежания этого необходимо следовать “Best Practices”, описанным в документации, а также выработать и использовать в команде единый подход к структуре каталогов. Еще одной характерной для всех систем управления конфигурацией проблемой является их использование для одноразовой настройки системы. Например, мы хотим применить изменение в каком-нибудь файле конфигурации и запускаем плейбук вручную один раз. Для эффективного применения IaC необходимо применять описание инфраструктуры на регулярной основе для обеспечения заданного состояния окружений. Научиться использовать Ansible и практику Infrastructure as Code вам помогут эксперты из Экспресс 42 в курсе DevOps практики и инструменты, курс стартует уже в понедельник! Присоединяйтесь! http://otus.ru/lessons/7?utm_source=telegram&utm_medium=internal&utm_campaign=devops&utm_content=deeppost&utm_term=10.08

Сегодня на втором Дне открытых дверей определились победители розыгрыша бесплатных мест на курсе DevOps. Победителями розыгрыша стали: Леонтьев Игорь и Гринёв Игорь. Поздравляем! Как это было можно посмотреть тут: https://www.youtube.com/watch?v=2hRdbt9Fbno

Совсем скоро начинаем второй День Открытых дверей по DevOps. Присоединяйтесь! https://www.youtube.com/channel/UCetgtvy93o3i3CvyGXKFU3g/live