ДомоДанные: как анализ данных используется в архитектуре и урбанистике

Преподавали мы в GoTo свои нейроночки, XGBoos’ы, SVM’ы и прочие случайные леса, и тут до нас кое-что дошло — мы много говорим про технологии и почти ничего не рассказываем про области, в которых их можно применить.
Мы решили исправить эту оплошность циклом статей, в которых расскажем о разных областях с неожиданно большими объемами данных, возьмём интервью у аналитиков и разработчиков, расскажем про проекты, которые мы решили попробовать сделать на школе и так далее.

И начнём мы с немного экзотических сфер — урбанистики и архитектуры.

Если хотите узнать подробности, прочитать интервью с техническим директором аналитической компании Habidatum и куратором программистко-архитектурных проектов из МАРХИ — милости прошу под кат.

Урбанистика

Начнём с урбанистики.

Урбанистика — наука, изучающая развитие различных городских систем (транспорт, пешеходная инфраструктура, экология, здравоохранение и другие), их взаимодействие между собой и с жителями города.

Аналитики в этой области собирают данные из большого количества источников: например, данные о перемещении общественного транспорта, данные сотовых операторов, соц. сети — и используют их для изучения функционирования среды (кто и когда ей пользуется, какие улицы самые нагруженные и т.д.) и для предсказания её поведения после нововведений. Всё движущееся и не движущееся на улицах города является объектом изучения для урбанистов.

Подробнее об этой области расскажет технический директор аналитической компании Habidatum Вадим Смахтин.

Интервью: Вадим Смахтин

Знакомство

Итак, начнём. Расскажите, пожалуйста, кто вы и чем занимаетесь?

Меня зовут Вадим, я технический директор компании Habidatum. Я занимаюсь проектированием различных систем, сервисов и устройств для работы с данными. Более пяти лет я разрабатываю софт для визуализации и аналитики данных, связанных с городской тематикой. Иногда напрямую участвую в аналитических проектах.
Фактически, в компании я являюсь «прослойкой» между программистами и урбанистами.

Расскажите про Habidatum. Чем вы занимаетесь?

Мы с друзьями основали Habidatum около пяти лет назад. Как тогда, так и сейчас мы занимаемся аналитикой данных для архитекторов и градостроителей, у которых есть вопросы относительно характеристик функционирования среды. Если они хотят узнать, как среда используется, как она отреагирует на нововведения (строительство новых зданий, переделка проезжей части в пешеходную зону…), как можно оптимизировать её использование и т.д., они приходят к нам. Также с недавних пор мы продаём свой аналитический софт.
Как технический директор, я отвечаю за архитектуру и спецификацию наших софтверных решений и курирую их разработку. Сейчас у нас есть целая линейка внутренних и внешних продуктов, одним из которых является система для визуализации данных “Хронотоп”.

Хронотоп

Что за Хронотоп?

Это софт для архитекторов и градостроителей, которым нужно анализировать разные потоки данных не только в пространственном аспекте, но и временном. Мы разработали методы, типа пространственно-временного куба, которые позволяют делать это безболезненно.
Кроме этого, Хронотопом также пользуются компании, которым нужно предоставлять доступ к своим данным для аналитиков и прессы, но которые не могут по причинам конфиденциальности сделать это напрямую. В любом случае, когда сырыми данными делиться нельзя, мы помогаем клиентам создать готовую визуализацию.

Существуют ли аналоги Хронотопа?

Хронотоп — это достаточно нишевая система, поэтому очень сложно говорить про каких-то прямых конкуртентов. Есть GIS системы типа QGIS и ArcGIS, есть системы визуализации данных, как, например, “Tableau”; есть аналитические пакеты, у которых нет своей визуализации — а продуктов, которые бы соединяли обе функции практически нет. Есть конечно ArcGIS, которые даже выпустили свой пространственно-временной куб, но у них он статический, поэтому функционал крайне ограничен. Плюс у них это десктопное приложение, а у нас всё работает в облаке.

Но нужно понимать, что мы в основном не продаём Хронотоп, как отдельный продукт. В основном мы используем его, как продажу доступа к данным с большим функционалом для анализа. Это довольно новаторская идея, кажется, никто так больше не делает. Идея в том, что у нас есть некоторые источники данных от партнеров, с которыми мы заключили соглашение (например сотовые операторы или операторы фискальных данных), и мы продаём проектировщикам доступ к ним не в сыром виде, а в интерфейсе. Так что наша бизнес модель касательно Хронотопа — это такая гибридная модель продажи софта и данных вместе. Да, у других компаний есть свои дата маркет плейсы, но там ты получаешь просто куски данных, никак не синхронизированные по времени, а у нас ты получаешь всё в удобном виде и выровненное относительно друг друга по времени и в пространстве.

Есть ли в Хронотопе какие-то математические или статистические модели или он только про визуализацию?

Изначально да, он был только про визуализацию. Конечно, там были какие-то базовые подсчёты статистик, но ничего такого. Но теперь, после того, как удалось успешно запустить графический движок в облаке, мы прикрутили к нему систему детекции аномалий, которая указывает аналитику интересные места, на которые стоит обратить внимание. У системы также есть открытый API, который позволяет писать свои детекторы. Это пока достаточно экспериментальная штука, но релиз уже скоро.
Также сейчас мы пробуем использовать “Хронотоп” для моделирования поведения среды, анализа постэффектов и предсказательного построения пространственно-временного куба.

Постэффектов?

Постэффекты — это изменения в состоянии среды после исполнения каких-то проектировочных решений. Например, вот мы поставили кафе в этой точке и хотим предсказать, как это повлияет на потоки людей в округе, прибыль других бизнесов и прочее. Т.е. мы вносим изменение в систему и смотрим на изменения всех её показателей.

Можешь рассказать про ваш стэк?

Сам рендерный движок написан на плюсах, активно используем CUDA и OpenGL шейдеры, которые рисуют воксельный обьем. Бэк по большей части написан на Питоне (Django). Конечно, возможно, это не лучшее проектировочное решение, но, т.к. сначала мы стремились максимально снизить порог вхождения для новых разработчиков, Питон казался лучшим выбором. Конечно, Питон удобен для написания аналитических модулей, но всю инфраструктуру писать на нём достаточно странно. Сейчас мы используем микросервисную инфраструктуру, поэтому в скором времени скорее всего перепишем обслуживающие модули. На фронтенде всё достаточно стандартно, кроме, наверное, TypeScript’а, который мы внесли ещё в одной из первых релизных версий. Из фреймворков — React и Redux

Аналитический отдел

Какого рода исследования проводит аналитический отдел?

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

Можешь рассказать пару примеров?

В принципе все проекты есть на нашем сайте, там можно посмотреть подробнее.

Из интересного — мы делали аналитику для нескольких районов Лондона, где изучали зависимость стоимости земли и квартир от поведения людей на улицах, их отзывах о местных заведениях и так далее. Это позволяет определять самые важные факторы при выборе человеком места проживания и позволяет повысить качество новых районов.

Есть проекты по спортивным ивентам. Здесь мы занимаемся пространственно-временной координацией. Например если у нас есть матч с большим количеством болельщиков, то мы можем понять, как нам развести в пространстве и по времени болельщиков и местное население. Это позволяет поднять плотность использования пространства и, конечно, позволяет избежать конфликтов.

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

Какие люди работают у вас аналитиками?

В основном все аналитики — это географы или люди, которые закончили Высшую Школу урбанистики. Есть ещё архитекторы, которые часто занимаются менеджментом проектов. Все эти люди не обязательно умеют программировать, но мы стараемся развивать атмосферу, в которой люди будут ближе к технологиям — развиваем коммуникацию между разработчиками и аналитиками. Это позволяет немного «размазать» экспертизу, поэтому людям намного проще отлавливать баги и проблемы на своём уровне. Ну и конечно разработчики не могут разрабатывать систему для визуализации данных, природу которых они совсем не понимают.

А программисты участвуют в работе аналитиков?

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

Например?

Есть сентимент анализ, word2vec для поиска синонимов, топик моделинг и прочий NLP. Это, конечно, не супер адвандст вещи, но наша работа не столько в разработке bleeding edge методов, сколько в использовании уже готовых алгоритмов для нужд города и строительства. Поэтому и разработчиков в дата сайнс отдел мы ищем таких, которым была бы интересна урбанистика и всё, что с ней связано. У нас было бы тяжело работать, например, людям, увлекающимся спортивным машинным обучением, в котором природа данных почти не важна. У нас задачи стоят не в выбивании лишних процентов из модели, а в понимании специфики данных, поэтому важным является именно интерес к теме и умение общаться с соответствующими специалистами.

Вообще насколько аналитикам нужно уметь программировать, если у вас есть специальные команды для этого?

Конечно, у нас всегда была идея создать некоего универсального солдата, который умеет и программировать и анализировать, но в целом эта концепция не совсем работает. Всё равно команда в итоге балансируется, поэтому люди, которые лучше программируют — больше программируют, те, кто хорошо пишут истории по данным — пишут истории. Ну а в целом, конечно, да, программирование никому не помешает. Легче самому посчитать какие-то статистики или сделать простую предобработку данных, вопрос только в том, сколько времени этому уделять.

Куда посоветуете пойти учиться будущему аналитику из мира урбанистики?

У нас работает большое количество ребят из Высшей Школы урбанистики. Не знаю, как там с точки зрения программирования, но с точки зрения урбанистического образования, это хорошее образование. Ну а для программирования существует огромное количество онлайн и просто курсов.
С точки зрения программиста мне кажется, что можно пойти в любую школу, которая занимается анализом данных (как ШАД, например), получить там основы машинного обучения и статистики и после этого начать делать какие-то проекты, связанные с городом.

Архитектура

Но не урбанистикой единой, товарищи.

В архитектуре тоже есть ряд задач, в которых IT сильно упрощает жизнь. Это задачи связанные с изучением эксплуатирования зданий и задачи автоматического проектирования.

Про это нам расскажет Доцент Учебно-Научного Центра Архитектуры и Компьютерных технологий МАРХИ Милан Станкевич.

Знакомство

Расскажите, пожалуйста, кто вы, и чем занимаетесь?

Архитектор, Магистр архитектуры,
Доцент Учебно-Научного Центра Архитектуры и Компьютерных технологий МАРХИ.
Член Союза Московских Архитекторов
Куратор Интенсивов-Про “Алгоритмическое проектирование и Цифровое производство” в МАРШ
Главный Архитектор проектов в Цимайло-Ляшенко и Партнеры.

В основном занимаюсь проектированием зданий и всего, что можно назвать архитектурой.
Руководитель Магистерских диссертаций в МАРХИ.

Все что выше — это формальности.

По сути,
Работаю в рамках архитектурного бюро в команде архитекторов над разными проектами. В основном жилых и общественных зданий.
Кроме архитектурных решений, занимаемся задачами информационного моделирования зданий.
В рамках работы со студентами чаще всего занимаемся исследовательскими проектами, которые связаны с использованием цифрового инструментария как в процессе проектирования, так и в самих концепциях.

Почему вы стали архитектором?

Поступил в архитектурный по советам родственников, но только на третьем курсе понял, каким архитектором хочу стать, после поступления в группу к немецкому проф. Михаэлю Айхнеру.
Также, побывав в качестве гостя в Мюнхене, Барселоне, Роттердаме, Делфте, Лондоне, а именно в архитектурных школах, расположенных там, сильно проникся идеями и мировоззрением местных школ.

Почему вы решили заниматься IT в архитектуре? Что вас привлекает в этом?

Очень все просто.
Мне интересны первопричины тех или иных процессов и почему они так устроены. Потому в момент, когда всем был интересен результат получаемый в 3Ds max например, (эффектная визуализация), то казалось, что намного важнее разобраться почему и как моделируется компьютером та или иная трехмерная форма, почему именно так она оцифровывается. В этот момент все больший интерес стали проявлять к Rhinoceros 3D, где грамотность построения геометрических форм неразрывно связана с пониманием логики работы самой программы.

Про АД в архитектуре

Мы выяснили, зачем программирование урбанистам. А зачем оно архитекторам?

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

Одни из примеров применения:
http://www.zha-code-education.org/
http://drl.aaschool.ac.uk/portfolio/osteobotics-3/

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

Понятней всего про программирование в архитектуре может скорее всего рассказать
Михаэль Хансмайер
или Марк Бурри.

На данный момент все больше направлений в архитектурной деятельности, в которых программирование имеет место быть.
Архитектура оперирует шаблонами, элементами и блоками, поэтому при проектировании взаимодействие между “паттернами” или шаблонами очень неплохо поддаётся задачам программирования, главное знать, как формализовать задачи.

Какая область исследований на стыке программирования и архитектуры интересует вас больше всего? Расскажите про интересные проекты в вашей области

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

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

Компания unsense занимается интересным направлением. Они исследуют возможности интеграции цифровых технологий в архитектуру для того чтобы связать это как-то с человеческими чувствами.

Или проект для Лондона, в котором предлагается сделать его более пешеходным. Вся аналитическая часть позволила выявить конечный “паттерн” пешеходных зон в городе и найти неприглядные пространства для того, чтобы их улучшить.

Есть ли у вас идеи относительно применения IT технологий в архитектуре, до которых ещё не дошли руки?

Если в целом: моделирование частиц и формирование пространств с учетом энергетических потоков и эмоциональных состояний. Сложное сочетание познаний моделирования динамики флюидов (частиц), анализа окружающей среды и эффективного и комфортного использования пространства под каждого человека.

Но в частности сейчас больше интересует тема, затронутая в моей диссертации, а именно реновация жилых малоэтажных кварталов и переход их к умной “регенерирующейся” среде. На практике — это эффективное использование архитектурных элементов в умном городе, связь Iot (internet of things, Индустрии 4.0 c возможностями существующих жилых домов, самоорганизацией общества, соучастия жителей в архитектуре реновации своих домов)

Могут ли обычные программисты помочь вам в ваших исследованиях?

Могут, если архитекторы поймут, что программисты сами могут. Пока этого понимания очень мало, хотя бы в РФ.
Если более конкретно, то нужно дифференцировать задачи архитектора.

Одни — концептуально-аналитические — помощь в принятии решений, где требуется сбор и анализ данных, т.е. рассмотрение исходной информации о участке или сфере проектирования. Тут много подзадач для аналитики, в зависимости от масштаба, градостроительный это уровень или совсем элементный, уровень дверной ручки.

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

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

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

Выше приведены только проектные задачи.
А есть еще целый ряд задач, которые нужны как в процессе строительства, так и при эксплуатации объектов. Ну проектирование и производство становятся ближе, потому, например, для цифрового производства архитектурных элементов непременно нужны программисты — без них никак не настроить общение между машинами и архитекторами.

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

Про архитекторов

Чем занимается ваша кафедра?

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

До сих пор у нас достаточно широкий профиль изучения разных задач.
В частности от нашей кафедры имеются 4 дисциплины для студентов МАРХИ, а также мы готовим своих собственных Магистров. Для Бакалавров 1,2 курса у нас — Компьютерно Композиционно Комбинаторный Курс. Там студенты через ряд заданий от составления абстрактных композиций переходят к архитектурным фантазиям. Они занимаются трехмерным моделированием в 3dsmax.
Для 3го курса — Компьютерная графика, там студенты знакомятся с большим количеством программного обеспечения, позволяющего анализировать проекты, и оформлять архитектурную документацию.
А для магистров — Цифровые Средства Параметрического формообразования и Градостроительные исследования при помощи ГИС.
В данных курсах студенты знакомятся с более широким спектром программного обеспечения и начинают использовать элементы визуального программирования.

Где учиться программированию архитекторам? Как? Куда бежать? Что изучить перед этим? Есть ли open-source проекты/исследования по этой тематике?

В данном случае стоит говорить и об одних, и о других. И о программистах, и об архитекторах. На самом деле проще программистам посмотреть, какие задачи и исследования нужны архитекторам.
Во-первых, кажется, что архитекторам нужны общие познания информатики и IT технологий.
Можно начинать со школьных лет или с открытых в интернете и в бесплатном доступе курсов.

Во-вторых, конечно, есть специализация, и по каждой теме конечно тоже существуют open source проекты и исследования, но реже встречаются.
Временами они переходят в формат семинаров и воркшопов.
Если говорить про качественные ресурсы, то их проводят в основном зарубежные школы.
Правда, если это формат воркшопа а особенно тематического, то зачастую это переходит в коммерческую историю и стоит участникам денег.
А так в основном увидеть проекты в области архитектуры и IT технологий можно увидеть на разных фестиваялх как например https://www.smartgeometry.org/
или по направлениям можно на порталах технологических институтов
ETH Zurich
ITKE
SciArch
MIT департамент Архитектуры
AA School of Lonson, DRL
Эти же институты проводят многочисленные воркшопы, рассматривающие ту или иную тему в области архитектуры и IT.

Если говорить про РФ, то все исследовательские проекты, курсы по данной теме, а также мероприятия в основном являются инициативами локальными и не имеют институционального характера.
Есть немногочисленные направления, которые проводят:
Интенсивы PRO: Алгоритмическое проектирование в МАРШ, SimplexNoise, ShukhovLab, Softculture.
Либо связка IT и архитектуры проходит в рамках отдельных дисциплин внутри процесса обучения архитектуре в МАРХИ и в МАРШ.

Список онлайн ресурсов также невелик, т.к. относится больше к получению навыков и обучению работе в программах, таких как Grasshopper, Dynamo для Revit. В меньшей степени можно найти онлайн курсы в какой-то отдельной области архитектуры, в основном они общие.
Открытых исследовательских ресурсов достаточно мало. Один из таких в 2011 году работал — Точка ветвления.

Что касается онлайн курсов зарубежных, то можно вспомнить
https://thinkparametric.com/
http://www.grasshopper3d.com/page/tutorials-1
и там же ссылки
http://designalyze.com/software/grasshopper
http://digitaltoolbox.info/ и т.д.
www.lynda.com
они направлены больше на изучение навыков.
Есть такие ресурсы, которые запускают отдельные компании
https://provingground.io
https://kierantimberlake.com/
http://www.carloratti.com
http://www.co-de-it.com
https://theverymany.com/

Насколько быстро архитекторы осваивают программирование?

В целом — тяжело и долго.
В частности, зависит от того, на каком этапе своего развития приступает человек к изучению.
Большая часть работы архитектора заключается в комбинировании элементов и информации о них, получении необходимых параметров (площадей и объемов), потому изучение программирования как еще один пласт информации достаточно комплексной, может быть трудоемкой задачей.
Также специфика программ для автоматизированного проектирования предполагает уже определенный набор элементов и правил, которыми архитектор оперирует (их тоже предостаточно). Чем дальше и больше архитектор работает в той или иной программе, тем она ему более знакома, и новое (языки программирования) могут проще восприниматься. Но, в связи с тем, что рынок ПО для проектирования не стоит на месте, то раз в три или пять лет архитекторам приходится адаптироваться к новым интерфейсам или новым возможностям программ.
Потому программирование проще осваивать до освоения проектного ПО или уже после. Так кажется более гуманно и проще адаптироваться.

А наоборот? Тяжело ли влиться программисту в область архитектуры? Стоит ли?

Стоит, только нужно выбрать именно правильную для себя сферу, где есть понятные задачи.
Вопрос про цели и задачи, которые перед собой ставит человек.
В архитектуре как и в программировании есть масса разных сфер, где можно быть частью процесса.
Грубо можно разделить на проектирование, производство и использование.
В каждом из трех есть свои подразделы конечно.
Проектирование — часть производственного процесса архитектуры, который для архитекторов неоправданно сильно важен, хотя по идее не должен быть отделим от производства архитектуры.

Есть ли что-то общее между программистом и архитектором.

Каких программистов и архитекторов рассматривать.
Но если мы говорим о тех которые работают в сфере “проектирования” новых “продуктов”, то их объединяет системный подход.
Разница в том что работа архитектора имеет другой временной и пространственный масштаб. От задумки до исполнения может проходить от двух трех дней до пара десятков лет. В среднем год-два.
Программист в этом плане раньше видит результат своей работы.
Но и один и второй являются как частью больших комплексных задач, так и могут быть самостоятельными творцами.
И также их работа “масштабируемая”, у программиста чуть больше, возможностей, правда, потому что, если архитектуру как физическую среду воспринимать, то она имеет существенные ограничения, пока результат программиста может выходить на планетарный масштаб.

Ну и напоследок — что можно почитать, чтобы понять, что такое архитектура на самом деле и почему это важно. Такой себе научпоп Architecture 101.

Наверное, можно начать от общих онтологических вещей, к примеру, любой книжки про историю архитектуры.
Или к тем, которые чуть более философские
Но я бы начал сразу с
“От постмодернизма — к нелинейной архитектуре. Архитектура в контексте современной философии и науки. Добрицына И.А. 2006
Чарлза Дженкса — Язык архитектуры постмодернизма
Вилияма Митчелла — “Я ++”,
Parametricism 2.0: Rethinking Architecture’s Agenda for the 21st Century

Или более прикладные — Кристофер Александер — Язык шаблонов.
Branko Kolarevic Architecture in the Digital Age: Design and Manufacturing

Для осведомленности о том что происходит в мире IT и архитектуры, следует скрее обращаться к журналам AD.

А при чем тут GoTo?

Недавно очередной шабаш GoTo прошел в стенах МАрхИ.

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

Из архитекторов в программисты.

На школе у нас было несколько ребят из МАрхИ, которые в первый раз окунулись в мир циклов, ифов и прочих goto (извините). Впечатлений было много.

Маша

Вообще безумно интересно было, до конца не понимали на какое направление хотим, и спонтанно вместе с Олей решили участвовать в последний момент и зацепили Кирилла с собой ) И в общем, это было круто, если раньше программирование пугало, то теперь в нем хочется разбираться и начать использовать, появилось понимание того, что вообще можно делать и как действовать на начальных этапах. Для архитекторов важно понимать, как работает информация и что скрывается за бесконечными цифрами. Благодаря этому курсу мы стали понимать, как работает питон, откуда можно скачать данные, и вообще как связать его с прогами типа грасса и что полезного можно сделать ) для меня было сложно, потому что англ плохо знаю, очень интересно было пообщаться с пирограмистами, думаю начинаться общаться нужно с самого начала школы )

Оля

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

Использовали сервис Face API от Microsoft, чтобы сделать фильтры для фотографий. Научились получать данные о пользователях социальной сети vk.com и попробовали анализировать эту информацию на выборке студентов мархи, визуализируя её разными способами: в виде круговых, столбчатых, пузырьковых диаграмм.

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

Проекты

Также мы сделали несколько проектов, связанных с архитектурной тематикой или направленных на нужды МАрхИ. Вот описания некоторых из них .

Изменение и генерирование фасадов.

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

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

Для этого мы натренировали VAE на фотографиях фасадов, натренировали классификатор, который бы предсказывал стиль фасада, и затем с помощью градиентного спуска изменяли вектор Hidden State’а с целевой функцией в виде кроссэнтропии по целевому распределению стилей и по фактическому.

Однако, данные с фотографиями фасадов оказались слишком разнообразными и малочисленными, чтобы нормально натренировать на них VAE, поэтому пришлось немного переформулировать задачу.

Мы генерировали новые буквы (аля смесь B c H) и изменяли одну букву в сторону других (например сделать F из E). Да, это задача кажется далекой от целевой, но здесь у нас были хорошие данные (notMNIST), и сама специфика задачи ничуть не отличается. Соответственно, после сборки хорошего датасета с фотографиями фасадов, можно будет эту же модель натравить на первую задачу.
Реализацию Proof of concept можно посмотреть здесь.

Сейчас мы планируем ещё несколько проектов по урбанистике. Так что stay tuned!

Генерирование чертежей по эскизам

Архитектура — творческая профессия.

Архитекторы постоянно генерят новые идеи для оформления фасадов, интерьеров и прочих буржуазных излишеств. Поток фантазии — это хорошо, но у него есть один неприятный сайд эффект — огромное количество недоделанных черновых чертежей, которое потом нужно долго и мучительно приводить в божеский вид. Мы решили прийти на помощь.

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

Архитектура сети: CycleGAN. Обучающую выборку мы сделали удалив целевые детали с готовых чертежей.

На проект можно посмотреть здесь.

РасписаниеБот

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

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

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

Прощание

Надеемся, что вы узнали что-то новое из этой статьи и, может, даже захотели приложить руку к этим вашим городам, сёлам и домам.

Мы в свою очередь будем открывать для себя новые области, в которых нужны аналитики и data scientist’ы, клепать на коленке проекты и рассказывать об этом вам.


ссылка на оригинал статьи https://habr.com/company/goto/blog/427489/

Как анализировать Thread Dump

В программе курса Разработчик Java довольно много тем,посвященных внутренностям работы JVM. Мы разбираемся в механизмах работы коллекций, байт-кода, сборщика мусора и т.д.
Сегодня предлагаем Вашему внимаю перевод довольно интересной статьи о thread dump-е. Что это такое, как его получить и как использовать.

Хотите узнать, как анализировать thread dump (дамп потоков)? Заходите под кат, чтобы узнать больше о том как в Java получить thread dump и что с ним потом делать.

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

В случае многопоточных приложений необходимо найти компромисс между усложнением программы и возможным повышением производительности, когда несколько потоков могут использовать все доступные (часто больше одного) ядра центрального процессора (CPU). Если сделать все правильно, то используя многопоточность (формализована в Amdahl’s Law), можно добиться существенного прироста производительности приложения. Однако при этом надо помнить об обеспечении синхронного доступа нескольких потоков к разделяемому ресурсу. В большинстве случаев, фреймворки, такие как Spring, инкапсулируют работу с потоками и скрывают от пользователей многие технические детали. Однако и в случае применения современных сложных фреймворков что-то может пойти не так, и мы, как пользователи, столкнемся со сложно решаемыми багами многопоточности.

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

Основная терминология

С первого взгляда Java thread dump-ы могут показаться «китайской грамотой», ключом к ее понимаю являются следующие понятия. В общем, давайте, повторим основные термины многопоточности, которые будем использовать для анализа дампов.

  • Thread или поток — дискретная единица многопоточности, управляемая Java Virtual Machine (JVM). Потоки JVM соответствуют потокам в операционной системе (OS) — native threads («естественные потоки»), которые и реализуют механизм выполнения кода.
    У каждого потока есть уникальный идентификатор и имя. Потоки могут быть «демонами» и «не демонами».Программа завершает свою работу, когда завершаются все потоки «не демоны» или вызывается метод Runtime.exit. Работающие «демоны» не влияют на завершение работы программы. Т.е. JVM ждем когда доработают все «не демоны» и завершает работу, на «не демонов» не обращает внимание.
    За более подробной информацией обращайтесь к документации класса Thread.
    Поток может находится в одном из следующих состояний:
    • Alive thread или «живой» — поток, который выполняет некоторую работу (нормальное состояние).
    • Blocked thread или «заблокированный» — поток, который попытался зайти в секцию синхронизации (synchronized), однако другой поток уже успел зайти в этот блок первым, и все следующие потоки, которые попытаются зайти в этот же блок оказываются заблокированными.
    • Waiting thread или «ожидающий» — поток, который вызвал метод wait (возможно, с указанием таймаута) и сейчас ждет, когда другой метод выполнит notify или nonifyAll на этом же объекте.
      Обратите внимание, поток не считается «ожидающим», если он вызвал wait с таймаутом и этот таймаут истек.
    • Sleeping thread или «спящий» — поток, который сейчас не выполняется, т.к. выполнил метод Thread.sleep (с указанием длительности «сна»).
  • Monitor — это механизм, используемый в JVM для обеспечения многопоточного доступа к одному объекту. Механизм запускается при помощи специального ключевого слова synchronized.Каждый объект в Java имеет монитор, при помощи которого поток может синхронизоваться, т.е. выставить блокировку, которая гарантирует, что ни один другой поток не получит доступ к этому объекту, пока блокировка не будет снята, т.е. поток — владелец блокировки не выйдет из блока synchronized.
    Более подробную информацию смотрите в Synchronization section (17.1) of the Java Langauge Specification (JLS).
  • Deadlock — это ситуация, в которой поток, скажем А, блокирует ресурс, ему нужен другой ресурс, который заблокирован другим потоком, скажем Б. Поток Б не отпускает этот ресурс, т.к. для завершения некой операции ему нужен ресурс, который заблокирован потоком А. Получается, что поток А ждет разблокировки ресурса потоком Б, который ждет разблокировку другого ресурса потоком А. И, таким образом, потоки ждут друг друга. В итоге, вся программа «висит» и ждет, когда потоки как-то разблокируются и продолжат работу. Во взаимной блокировке может быть много потоков. Эта проблема хорошо известна как «Проблема обедающих философов».
  • Livelock — это ситуация, когда поток A заставляет поток В выполнить некое действие, которое в свою очередь приводит в выполнению поток А первоначального действия, которое в очередной раз вызывает действие потока В. Получается циклическая зависимость. Это можно представить, как собаку, бегающую за своим хвостом. Аналогично Deadlock, в ситуации Livelock программа не совершает прогресс, т.е. не выполняет полезное действие, однако в этой ситуации потоки не блокируются.

Представленная терминология не является исчерпывающей для описания мира многопоточности, однако этого достаточно, чтобы начинать анализировать thread dump-ы.
Более детальную информацию можно найти в этих источниках: Section 17 of the JLS и Java Concurrency in Practice

Применяя эти простые понятия о потока в Java, мы можем создать тестовое приложение. Для этого приложения мы соберем thread dump. Полученный дамп проанализируем и извлечем полезную информацию о текущих потоках приложения.

Создание примера программы

Прежде, чем создать thread dump, нам надо разработать Java-приложение. Традиционный «hello, world!» для нашей цели слишком прост, а дамп среднего размера приложения может оказаться слишком сложным для демонстрации. Исходя из этого, мы создадим достаточно простое приложение, в котором создаются два потока. Причем потоки попадают в deadlock:

public class DeadlockProgram {     public static void main(String[] args) throws Exception {         Object resourceA = new Object();         Object resourceB = new Object();         Thread threadLockingResourceAFirst = new Thread(new DeadlockRunnable(resourceA, resourceB));         Thread threadLockingResourceBFirst = new Thread(new DeadlockRunnable(resourceB, resourceA));         threadLockingResourceAFirst.start();         Thread.sleep(500);         threadLockingResourceBFirst.start();     }     private static class DeadlockRunnable implements Runnable {         private final Object firstResource;         private final Object secondResource;         public DeadlockRunnable(Object firstResource, Object secondResource) {             this.firstResource = firstResource;             this.secondResource = secondResource;         }         @Override         public void run() {             try {                 synchronized(firstResource) {                     printLockedResource(firstResource);                     Thread.sleep(1000);                     synchronized(secondResource) {                         printLockedResource(secondResource);                     }                 }             } catch (InterruptedException e) {                 System.out.println("Exception occurred: " + e);             }         }         private static void printLockedResource(Object resource) {             System.out.println(Thread.currentThread().getName() + ": locked resource -> " + resource);         }     } } 

Эта программа создает два ресурса: resourceA и resourceB, и стартует два потока: threadLockingResourceAFirst и threadLockingResourceBFirst, которые блокируют ресурсы друг друга.Причиной возникновения deadlock-а является «перекрестная» блокировка ресурсов потоками.Причиной возникновения deadlock является попытка «взаимного» захвата ресурсов, т.е. поток threadLockingResourceAFirst захватывает ресурс resourceA, поток threadLockingResourceBFirst захватывает ресурс resourceB. После этого поток threadLockingResourceAFirst, не отпуская свой ресурс, пытается захватить resourceB, а поток threadLockingResourceBFirst, не отпуская свой ресурс, пытается захватить ресурс resourceA. В результате потоки блокируются. Задержка в 1с добавлена, чтобы гарантировать возникновение блокировки. Потоки ждут освобождение нужных ресурсов, но это никогда не случится.

Вывод программы будет таким (числа после java.lang.Object@ будут разные для каждого запуска):

Thread-0: locked resource -> java.lang.Object@149bc794Thread-1: locked resource -> java.lang.Object@17c10009

После вывода этих сообщений программа будет выглядеть как работающая (процесс, выполняющий эту программу, не завершен), при этом программа не выполняет никакой работы. Вот так вот и выглядит deadlock на практике. Чтобы решить проблему, нам надо вручную создать tread dump и проанализировать состояние потоков.

Генерация Thread Dump

На практике, Java-программа может аварийно завершиться и при этом создать thread dump. Однако в ряде случаев (например в случае deadlock-ов), программа не завершается и thread dump не создает, она просто зависает. Для создания дампа таких зависших программ, прежде всего надо выяснить идентификатор процесса программы, т.е. Process ID (PID). Для этого можно воспользоваться утилитой JVM Process Status (JPS), которая начиная с версии 7, входит в состав Java Development Kit (JDK). Чтобы найти PID процесса нашей зависшей программы, мы просто выполним jps в терминале (Windows или Linux):

$ jps11568 DeadlockProgram15584 Jps15636

Первая колонка — это идентификатор локальной виртуальной машины (Local VM ID, т.е. lvmid) для выполняемого Java-процесса. В контексте локальной JVM, lvmid указывает на PID Java-процесса. Надо отметить, что это значение, скорее всего, будет отличаться от значения выше. Вторая колонка — это имя приложения, которое может указывать на имя main-класса, jar-файла или быть равно «Unknown». Все зависит от того, как приложение было запущено.

В нашем случае имя приложения DeadlockProgram — это имя main-классы, который был запущен при старте программы. В примере выше PID программы 11568, этой информации достаточно для генерации thread dump’а. Для генерации дампа мы воспользуемся утилитой jstack, которая входит в состав JDK, начиная с версии 7. Чтобы получить дамп мы передадим в jstack в качестве параметра PID нашей программы и укажем флаг -l (создание длинного листинга). Вывод утилиты перенаправим в текстовый файл, т.е. thread_dump.txt:

jstack -l 11568 > thread_dump.txt

Полученный файл thread_dump.txt содержит thread dump нашей зависшей программы и содержит важную информацию для диагностики причин возникновения deadlock-а.
Если используется JDK до 7 версии, то для генерации дампа можно воспользоваться утилитой Linux — kill с флагом -3. Вызов kill -3 отправит программе сигнал SIGQUIT.
В нашем случае вызов будет такой:

kill -3 11568

Анализ простого Thread Dump

Открыв файл thread_dump.txt, мы увидим примерно следующее содержание:

  2018-06-19 16:44:44 Full thread dump Java HotSpot(TM) 64-Bit Server VM (10.0.1+10 mixed mode): Threads class SMR info: _java_thread_list=0x00000250e5488a00, length=13, elements={ 0x00000250e4979000, 0x00000250e4982800, 0x00000250e52f2800, 0x00000250e4992800, 0x00000250e4995800, 0x00000250e49a5800, 0x00000250e49ae800, 0x00000250e5324000, 0x00000250e54cd800, 0x00000250e54cf000, 0x00000250e54d1800, 0x00000250e54d2000, 0x00000250e54d0800 } "Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000250e4979000 nid=0x3c28 waiting on condition  [0x000000b82a9ff000]    java.lang.Thread.State: RUNNABLE     at java.lang.ref.Reference.waitForReferencePendingList(java.base@10.0.1/Native Method)     at java.lang.ref.Reference.processPendingReferences(java.base@10.0.1/Reference.java:174)     at java.lang.ref.Reference.access$000(java.base@10.0.1/Reference.java:44)     at java.lang.ref.Reference$ReferenceHandler.run(java.base@10.0.1/Reference.java:138)    Locked ownable synchronizers:     - None "Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000250e4982800 nid=0x2a54 in Object.wait()  [0x000000b82aaff000]    java.lang.Thread.State: WAITING (on object monitor)     at java.lang.Object.wait(java.base@10.0.1/Native Method)     - waiting on <0x0000000089509410> (a java.lang.ref.ReferenceQueue$Lock)     at java.lang.ref.ReferenceQueue.remove(java.base@10.0.1/ReferenceQueue.java:151)     - waiting to re-lock in wait() <0x0000000089509410> (a java.lang.ref.ReferenceQueue$Lock)     at java.lang.ref.ReferenceQueue.remove(java.base@10.0.1/ReferenceQueue.java:172)     at java.lang.ref.Finalizer$FinalizerThread.run(java.base@10.0.1/Finalizer.java:216)    Locked ownable synchronizers:     - None "Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000250e52f2800 nid=0x2184 runnable  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:     - None "Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000250e4992800 nid=0x1624 waiting on condition  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:     - None "C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x00000250e4995800 nid=0x4198 waiting on condition  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    No compile task    Locked ownable synchronizers:     - None "C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x00000250e49a5800 nid=0x3b98 waiting on condition  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    No compile task    Locked ownable synchronizers:     - None "C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x00000250e49ae800 nid=0x1a84 waiting on condition  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    No compile task    Locked ownable synchronizers:     - None "Sweeper thread" #9 daemon prio=9 os_prio=2 tid=0x00000250e5324000 nid=0x5f0 runnable  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:     - None "Service Thread" #10 daemon prio=9 os_prio=0 tid=0x00000250e54cd800 nid=0x169c runnable  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:     - None "Common-Cleaner" #11 daemon prio=8 os_prio=1 tid=0x00000250e54cf000 nid=0x1610 in Object.wait()  [0x000000b82b2fe000]    java.lang.Thread.State: TIMED_WAITING (on object monitor)     at java.lang.Object.wait(java.base@10.0.1/Native Method)     - waiting on <0x000000008943e600> (a java.lang.ref.ReferenceQueue$Lock)     at java.lang.ref.ReferenceQueue.remove(java.base@10.0.1/ReferenceQueue.java:151)     - waiting to re-lock in wait() <0x000000008943e600> (a java.lang.ref.ReferenceQueue$Lock)     at jdk.internal.ref.CleanerImpl.run(java.base@10.0.1/CleanerImpl.java:148)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844)     at jdk.internal.misc.InnocuousThread.run(java.base@10.0.1/InnocuousThread.java:134)    Locked ownable synchronizers:     - None "Thread-0" #12 prio=5 os_prio=0 tid=0x00000250e54d1800 nid=0xdec waiting for monitor entry  [0x000000b82b4ff000]    java.lang.Thread.State: BLOCKED (on object monitor)     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465b0> (a java.lang.Object)     - locked <0x00000000894465a0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844)    Locked ownable synchronizers:     - None "Thread-1" #13 prio=5 os_prio=0 tid=0x00000250e54d2000 nid=0x415c waiting for monitor entry  [0x000000b82b5ff000]    java.lang.Thread.State: BLOCKED (on object monitor)     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465a0> (a java.lang.Object)     - locked <0x00000000894465b0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844)    Locked ownable synchronizers:     - None "DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x00000250e54d0800 nid=0x2b8c waiting on condition  [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:     - None "VM Thread" os_prio=2 tid=0x00000250e496d800 nid=0x1920 runnable   "GC Thread#0" os_prio=2 tid=0x00000250c35b5800 nid=0x310c runnable   "GC Thread#1" os_prio=2 tid=0x00000250c35b8000 nid=0x12b4 runnable   "GC Thread#2" os_prio=2 tid=0x00000250c35ba800 nid=0x43f8 runnable   "GC Thread#3" os_prio=2 tid=0x00000250c35c0800 nid=0x20c0 runnable   "G1 Main Marker" os_prio=2 tid=0x00000250c3633000 nid=0x4068 runnable   "G1 Conc#0" os_prio=2 tid=0x00000250c3636000 nid=0x3e28 runnable   "G1 Refine#0" os_prio=2 tid=0x00000250c367e000 nid=0x3c0c runnable   "G1 Refine#1" os_prio=2 tid=0x00000250e47fb800 nid=0x3890 runnable   "G1 Refine#2" os_prio=2 tid=0x00000250e47fc000 nid=0x32a8 runnable   "G1 Refine#3" os_prio=2 tid=0x00000250e47fd800 nid=0x3d00 runnable   "G1 Young RemSet Sampling" os_prio=2 tid=0x00000250e4800800 nid=0xef4 runnable   "VM Periodic Task Thread" os_prio=2 tid=0x00000250e54d6800 nid=0x3468 waiting on condition   JNI global references: 2 Found one Java-level deadlock: ============================= "Thread-0":   waiting to lock monitor 0x00000250e4982480 (object 0x00000000894465b0, a java.lang.Object),   which is held by "Thread-1" "Thread-1":   waiting to lock monitor 0x00000250e4982380 (object 0x00000000894465a0, a java.lang.Object),   which is held by "Thread-0" Java stack information for the threads listed above: =================================================== "Thread-0":     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465b0> (a java.lang.Object)     - locked <0x00000000894465a0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844) "Thread-1":     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465a0> (a java.lang.Object)     - locked <0x00000000894465b0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844) Found 1 deadlock. 

Introductory Information

Хотя на первый взгляд этот файл может показаться слишком сложным и запутанным, в действительности он весьма прост, если разбирать его по частям шаг за шагом.
В первой строке указывается время, когда дамп был сформирован, во второй — диагностическая информация о JVM, на которой дамп был получен:

2018-06-19 16:44:44Full thread dump Java HotSpot(TM) 64-Bit Server VM (10.0.1+10 mixed mode):

В этой секции нет информации о потоках. Тут задается общий контекст системы, в которой был собран дамп.

Общие сведенья о потоках

В следующей секции представлена информация о потоках, которые выполнялись в системе в момент сбора дампа:

 Threads class SMR info: _java_thread_list=0x00000250e5488a00, length=13, elements={ 0x00000250e4979000, 0x00000250e4982800, 0x00000250e52f2800, 0x00000250e4992800, 0x00000250e4995800, 0x00000250e49a5800, 0x00000250e49ae800, 0x00000250e5324000, 0x00000250e54cd800, 0x00000250e54cf000, 0x00000250e54d1800, 0x00000250e54d2000, 0x00000250e54d0800 } 

В следующей секции приводится список Safe Memory Reclamation (SMR) information.В нем содержится информация о потоках за пределами JVM, т.е. это не потоки виртуальной машины и не потоки сборщика мусора. Если посмотреть на адреса этих потоков, то можно заметить, что они соответствуют значению tid — «естественному, железному» (native) адресу в операционной системе, а не Thread ID. Троеточия используются для сокрытия излишней информации:

 "Reference Handler" #2 ... tid=0x00000250e4979000 ... "Finalizer" #3 ... tid=0x00000250e4982800 ... "Signal Dispatcher" #4 ... tid=0x00000250e52f2800 ... "Attach Listener" #5 ... tid=0x00000250e4992800 ... "C2 CompilerThread0" #6 ... tid=0x00000250e4995800 ... "C2 CompilerThread1" #7 ... tid=0x00000250e49a5800 ... "C1 CompilerThread2" #8 ... tid=0x00000250e49ae800 ... "Sweeper thread" #9 ... tid=0x00000250e5324000 ... "Service Thread" #10 ... tid=0x00000250e54cd800 ... "Common-Cleaner" #11 ... tid=0x00000250e54cf000 ... "Thread-0" #12 ... tid=0x00000250e54d1800 ... "Thread-1" #13 ... tid=0x00000250e54d2000 ... "DestroyJavaVM" #14 ... tid=0x00000250e54d0800 ... 

Потоки

Сразу после блока SMR следует список потоков. Первый поток в нашем списке — Reference Handler:

 "Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000250e4979000 nid=0x3c28 waiting on condition  [0x000000b82a9ff000]    java.lang.Thread.State: RUNNABLE     at java.lang.ref.Reference.waitForReferencePendingList(java.base@10.0.1/Native Method)     at java.lang.ref.Reference.processPendingReferences(java.base@10.0.1/Reference.java:174)     at java.lang.ref.Reference.access$000(java.base@10.0.1/Reference.java:44)     at java.lang.ref.Reference$ReferenceHandler.run(java.base@10.0.1/Reference.java:138)    Locked ownable synchronizers:     - None 

Краткое описание потока

В первой строке для каждого потока приводится общее описание. Описание содержит следующие пункты:

Раздел Пример Описание
Name «Reference Handler» Человеко-читаемое имя потока. Имя можно задать, вызвав метод setName объекта Thread. А получить через вызов getName
ID #2 Уникальный ID, присвоенный каждому объекту класса Thread. ID генерируется для потоков в системе. Первоначальное значение 1. Каждому вновь созданному потоку присваивается свой ID, предварительно увеличенный на 1. Это свойство потока «только для чтения», может быть получено с помощью функции getId объекта класса Thread.
Daemon status daemon Флаг является признаком того, что поток является демоном. Если это демон, то флаг будет выставлен. Например, поток Thread-0 не демон
Priority prio=10 Числовой приоритет Java-потока. Обратите внимание, что этот приоритет не обязательно соответствует приоритету связанного потока в операционной системе. Для установки приоритета можновоспользоваться методом setPriority объекта класса Thread, а для полученияметодом getPriority.
OS Thread Priority os_prio=2 Приоритет потока в операционной системе. Этот приоритет может отличаться от того, который присвоен связному Java-потоку.
Address tid=0x00000250e4979000 Адрес Java-потока. Этот адрес представляет собой указатель на Java Native Interface (JNI) нативный объект класса Thread (объект C++ Thread который связан с Java-потоком через JNI). Это значение получается путем приведения указателя на this(объекта C++, который связан с этим Java-потоком) к integer. См. строку 879 в hotspot/share/runtime/thread.cpp:

 st->print("tid=" INTPTR_FORMAT " ", p2i(this)); 

Хотя ключ для этого объекта (tid) может быть похож на ID-потока,на самом деле, это адрес связного объекта JNI C++ Thread, и это не то значение, котороевозвращает метод getId Java-объекта Thread.

OS Thread ID nid=0x3c28 Уникальный идентификатор потока операционной системы, к которому привязан Java-поток.
Это значение выводится следующим кодом:
строка 42 в hotspot/share/runtime/osThread.cpp:

 st->print("nid=0x%x ", thread_id()); 
Status waiting on condition Человеко-читаемый статус текущего потока.Эта строка выводит дополнительную информацию к простому статусу потока (см.ниже), которая может бытьиспользована для понимания, что поток собирался делать (т.е. пытался ли поток получить блокировкуили ждал выполнения условия разблокирования).
Last Known Java Stack Pointer [0x000000b82a9ff000] Последний известный указатель на стек (SP), ассоциированный и данным потоком. Это значение получается с использованием нативного кода С++, перемешанного с кодом Java с использованием JNI. Значение возвращает функция last_Java_sp(), строка 2886 в hotspot/share/runtime/thread.cpp:

   st->print_cr("[" INTPTR_FORMAT "]",      (intptr_t)last_Java_sp() & ~right_n_bits(12)); 

Для простых thread dump-ов эта информация практически бесполезна. Однако в сложных случаях SP можетбыть использован для отслеживания блокировок.

Состояние потока

Вторая строка — это текущее состояние потока. Возможные состояния потока приведены в enum:Thread.State: NEW RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATEDБолее подробную информацию смотрите вдокументации.

Thread Stack Trace

Следующая секция содержит stack trace потока в момент снятия дампа. Этот stack trace очень похож на stack trace, который формируется не перехваченным исключением.И содержит имена классов и строк, которые выполнялись в момент формирования дампа.В случае потока Reference Handler мы не видим ничего интересного.Однако в трассировке потока Thread-02 есть кое-что интересное, отличное от стандартного трейса:

 "Thread-0" #12 prio=5 os_prio=0 tid=0x00000250e54d1800 nid=0xdec waiting for monitor entry  [0x000000b82b4ff000]    java.lang.Thread.State: BLOCKED (on object monitor)     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465b0> (a java.lang.Object)     - locked <0x00000000894465a0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844)    Locked ownable synchronizers:     - None 

В трассировке мы видим, что добавилась информация о блокировке. Этот поток ожидает блокировкуна объекте с адресом 0x00000000894465b0 (тип объекта java.lang.Object). Более того поток сам удерживает блокировку с адресом 0x00000000894465a0 (тоже объект java.lang.Object). Эта информация нам пригодится далее для диагностики deadlock-а.

Захваченные примитивы синхронизации (Ownable Synchronizer)

В последней секции приводится список примитивов синхронизации (synchronizers), захваченных потоком. Это объекты, которые могут быть использованы для синхронизации потоков, например, защелки (locks).В соответствии с официальной документацией Java, Ownable Synchronizer — этонаследники AbstractOwnableSynchronizer (или его подкласса), которые могут быть эксклюзивно захвачены потоком для целей синхронизации.ReentrantLock и write-lock, но не read-lock класса ReentrantReadWriteLock — два хороших примера таких «ownable synchronizers», предлагаемых платформой.
Для получения более подробной информации по этому вопросу можно обратиться к этому посту.

Потоки JVM

В следующей секции дампа содержится информация о технических потоках JVM, которые не являются частью приложения и связаны с потоками операционной системы. Т.к. эти потоки работают вне приложения, у них нет идентификаторов потока. Чаще всего это потоки сборщика мусора и другие технические потоки JVM:

 "VM Thread" os_prio=2 tid=0x00000250e496d800 nid=0x1920 runnable   "GC Thread#0" os_prio=2 tid=0x00000250c35b5800 nid=0x310c runnable   "GC Thread#1" os_prio=2 tid=0x00000250c35b8000 nid=0x12b4 runnable   "GC Thread#2" os_prio=2 tid=0x00000250c35ba800 nid=0x43f8 runnable   "GC Thread#3" os_prio=2 tid=0x00000250c35c0800 nid=0x20c0 runnable   "G1 Main Marker" os_prio=2 tid=0x00000250c3633000 nid=0x4068 runnable   "G1 Conc#0" os_prio=2 tid=0x00000250c3636000 nid=0x3e28 runnable   "G1 Refine#0" os_prio=2 tid=0x00000250c367e000 nid=0x3c0c runnable   "G1 Refine#1" os_prio=2 tid=0x00000250e47fb800 nid=0x3890 runnable   "G1 Refine#2" os_prio=2 tid=0x00000250e47fc000 nid=0x32a8 runnable   "G1 Refine#3" os_prio=2 tid=0x00000250e47fd800 nid=0x3d00 runnable   "G1 Young RemSet Sampling" os_prio=2 tid=0x00000250e4800800 nid=0xef4 runnable   "VM Periodic Task Thread" os_prio=2 tid=0x00000250e54d6800 nid=0x3468 waiting on condition 

Глобальные ссылки JNI

В этой секции указывается количество глобальных ссылок, используемых JVM через JNI.Эти ссылки не обслуживаются сборщиком мусора и в определенных обстоятельствах могут стать причинойутечки памяти.

 JNI global references: 2 

В большинстве простых случаев эта информация не используется. Однако важность глобальных ссылок надопонимать. Более подробную информацию смотрите в этом постепосте.

Взаимно заблокированные (Deadlocked) потоки

Последний раздел содержит информацию о найденных взаимных блокировках (deadlocks).Если такие не обнаружатся, то и раздел будет пустым. Т.к. мы специально разработали приложение сблокировками, в нашем случае этот раздел есть. Блокировка обнаружена во время формирования дампа и представлена следующим сообщением:

 Found one Java-level deadlock: ============================= "Thread-0":   waiting to lock monitor 0x00000250e4982480 (object 0x00000000894465b0, a java.lang.Object),   which is held by "Thread-1" "Thread-1":   waiting to lock monitor 0x00000250e4982380 (object 0x00000000894465a0, a java.lang.Object),   which is held by "Thread-0" Java stack information for the threads listed above: =================================================== "Thread-0":     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465b0> (a java.lang.Object)     - locked <0x00000000894465a0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844) "Thread-1":     at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34)     - waiting to lock <0x00000000894465a0> (a java.lang.Object)     - locked <0x00000000894465b0> (a java.lang.Object)     at java.lang.Thread.run(java.base@10.0.1/Thread.java:844) Found 1 deadlock. 

В первом подразделе описывается сценарий взаимной блокировки (deadlock):Поток Thread-0 ожидает возможность захватить монитор(это обращение к блоку synchronized(secondResource) в нашем приложении), в то же времяэтот поток удерживает монитор, который пытается захватить поток Thread-1 (это обращение ктому же фрагменту кода: synchronized(secondResource) в нашем приложении). Эта циклическая блокировка по другому называется deadlock. На рисунке нижеэта ситуация представлена в графическом виде:

Во втором подразделе для обоих заблокированных потоков приведен stack trace.Этот stack trace позволяет нам проследить за работой каждого потока до появления блокировки.В нашем случае, если мы посмотрим на строку: at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34), то увидим проблемный участок кода:

 printLockedResource(secondResource); 

Эта строка является первой строкой блока synchronized, который является причиной блокировки,и подсказывает нам, что синхронизация на secondResource и является причиной взаимной блокировки.

Чтобы исправить ситуацию, мы должны обеспечить в обоих потоках одинаковый порядок синхронизации на ресурсах resourceA и resourceB. Если мы сделаем это, то придем к следующему приложению:

public class DeadlockProgram {     public static void main(String[] args) throws Exception {         Object resourceA = new Object();         Object resourceB = new Object();         Thread threadLockingResourceAFirst = new Thread(new DeadlockRunnable(resourceA, resourceB));         Thread threadLockingResourceBFirst = new Thread(new DeadlockRunnable(resourceA, resourceB));         threadLockingResourceAFirst.start();         Thread.sleep(500);         threadLockingResourceBFirst.start();     }     private static class DeadlockRunnable implements Runnable {         private final Object firstResource;         private final Object secondResource;         public DeadlockRunnable(Object firstResource, Object secondResource) {             this.firstResource = firstResource;             this.secondResource = secondResource;         }         @Override         public void run() {             try {                 synchronized (firstResource) {                     printLockedResource(firstResource);                     Thread.sleep(1000);                     synchronized (secondResource) {                         printLockedResource(secondResource);                     }                 }             } catch (InterruptedException e) {                 System.out.println("Exception occurred: " + e);             }         }         private static void printLockedResource(Object resource) {             System.out.println(Thread.currentThread().getName() + ": locked resource -> " + resource);         }     } } 

Это приложение завершится без взаимной блокировки, и в качестве результата мы получим следующий вывод (обратите внимание на то, что адреса экземпляров класса Object изменились):

 Thread-0: locked resource -> java.lang.Object@1ad895d1 Thread-0: locked resource -> java.lang.Object@6e41d7dd Thread-1: locked resource -> java.lang.Object@1ad895d1 Thread-1: locked resource -> java.lang.Object@6e41d7dd 

В результате, используя только информацию, полученную из thread dump, мы смогли найти причину и исправить взаимную блокировку в нашем приложении. Предложенная техника достаточна для большинствапростых приложений (или приложений с небольшим количеством deadlock-ов). Чтобы разобраться с болеесложными ситуациями, потребуются другие методы.

Анализ более сложных Thread Dump-ов

Дампы настоящих приложений могут быть очень большими и сложнымиВ одной JVM одновременно могут быть запущены сотни тысяч потоков. И заблокированными могут оказаться больше чем два потока (или может быть несколько проблем многопоточности, вызванных одной проблемой).Анализ такого громадного объема информации может стать настоящей проблемой.

Для анализа больших дампов предназначены специальные утилиты-анализаторы — Thread Dump Analyzers (TDAs). Эти утилиты парсят Java thread dump-ы и выводят информацию в человеко-читаемом виде, часто с применением графических средств. Более того, некоторые из них могут выполнить статический анализ и найти причину проблемы. Конечно, выбор конкретной утилиты зависит от целого ряда обстоятельств.Тем не менее приведем список наиболее популярных TDA:

Это далеко не полный список утилит подобного рода. Каждая утилита из этого списка выполняет достаточно качественный анализ и упрощает ручной труд анализа дампов.

Заключение

Thread dump-ы — это отличное средство анализа состояния Java-приложения, особенно в случаях неожиданного поведения многопоточных приложений. Однако без надлежащего багажа знаний, дампымогут внести дополнительную сложность и в без того сложную ситуацию.
В этой статье мы разработали приложение с deadlock, сформировали дамп зависшего приложения.Проанализировали дамп и нашли причину блокировки и исправили её. Это не всегда так просто,для анализа большинства реальных приложений очень полезно использовать специальные утилиты — анализаторы.

Тем не менее, каждый профессиональный Java-разработчик должен понимать основы анализа thread dump-ов. Должен ориентироваться в их структуре, знать какую информацию можно извлечь и как ее использоватьдля решения проблем многопоточности.
Хотя, thread dump — это не «серебряная пуля» в мире многопоточности, тем не менее это важное средстводиагностирования сложных, но довольно распространенных проблем многопоточных Java-приложений.

В программе курса Разработчик Java вопросы многопоточности занимают заменую часть. Мы детально рассматриваем как разрабатывать программы так, чтобы не приходилось по ночам разбираться с deadlock-в продакшене.


ссылка на оригинал статьи https://habr.com/company/otus/blog/427513/

Веб-серверы: опыт и практика Southbridge

Сергей Бондарев ведет половину тем на интенсивах по Кубернетес Слёрм-2 и МегаСлёрм.
На Слёрм-2 еще не поздно зарегистрироваться онлайн, а на МегаСлёрм даже можно успеть приехать.


ссылка на оригинал статьи https://habr.com/company/southbridge/blog/427509/

Сеймур Пейперт: Hard Fun

image

Я слышал много критики от людей, считающих, что эта колонка (и другие работы, написанные мной) пропагандирует отсутствие дисциплины в обучении, а также идею того, что при обучении необязательно напрягаться и корпеть над учебниками. Не буду оспаривать их точку зрения. Я противник тех традиционных методов, с помощью которых сегодняшние школы заставляют детей учиться, а большинство попыток внедрить более занимательный и менее принудительный учебный план как раз и заканчиваются тем, что в конечном итоге выворачивают обучение наизнанку. Однако несправедливо обвинять меня в соучастии к этому преступлению. Весь мой карьерный путь в области образования был посвящен поиску такой деятельности, чтобы она подогревала интерес ученика к тяжелой работе, которая необходима для овладения сложным материалом и приобретением навыков самодисциплины. Но мне трудно подобрать правильные слова, чтобы передать насколько, в моём представлении, мой подход отличается от подхода «ути-пути, сюси-муси… пусть будет весело, чтобы было легко».

Еще в середине 80-х годов я услышал кое-что гениальное из уст первоклассника, и его слова до сих пор помогают мне объяснить суть моего подхода. Академия Гарднера (начальная школа в бедном районе Сан-Хосе в Калифорнии) была одной из первых школ, в которой достаточно компьютеров, чтобы студенты могли проводить за ними большое количество времени каждый день. Введением к использованию компьютеров для всех классов было обучение программированию на языке Лого, и причём на довольно неплохом уровне. Один из детей описал работу за компьютером словами, которые затем мне передал его учитель: «Это весело (fun), это сложно (hard), это Лого». Я не сомневаюсь, что этот мальчик назвал работу весёлой, «потому что» она была тяжёлой, а не «несмотря на то», что она была тяжелой.

Как только мне пришла в голову идея «тяжелого веселья» (hard fun), я начал прислушиваться к ней и слышал её снова и снова. Она выражается по-разному, но всё сводится к выводу, что всем нравятся тяжелые, заставляющие поднапрячься дела. Но они должны быть правильно подобраны под человека и культуру того времени. Сегодняшние быстро меняющиеся времена бросают вызов педагогам, которые ищут деятельность, которая была бы трудна в правильном смысле: она должна заинтересовать детей, но также должна преподносить знания, навыки и (давайте не будем забывать) нормы морали, которые понадобятся им, когда они повзрослеют.

Я писал в этой колонке о подростках в исправительном учреждении для несовершеннолетних в штате Мэн, которые преодолевали их глубокое внутреннее отвращение к любому виду школьного обучения, когда получали возможность изобретать и строить сложные механические / роботизированные устройства. Для этого требуется концентрация и дисциплина. В ситуации, когда что-то не работает, приходится учиться — выяснять, как исправить проблему, а не сдаваться и опускать руки. И для некоторых из этих детей это послужило толчком к тому, что они впервые захотели написать что-то — ведь они занимались чем-то, что их интересовало, и занимались этим сами.

Фраза «удовольствие от письма» заставляет меня остановиться. В этот самый момент писать не совсем приятно. Меня расстраивает тикание часов, которые отсчитывают время до приближающегося дедлайна. Мне больно из-за того, что пришлось выбросить целый абзац, потому что я видел, что он «не то», хотя в нём была фраза, в которую я влюбился. Поэтому, возможно, «удовольствие» — не совсем правильное слово. И не слово «веселье». Нам требуется более подходящее слово для этого, и, кто знает, возможно, первоклассник из Сан-Хосе произнёс лучший вариант. Мы говорим здесь об особом виде веселья… о «тяжёлом веселье».

Как нам сделать письмо «тяжёлым весельем»? Один из способов — разработать для детей «записываемые» виды занятий, которые им нравится делать. Создание роботизированных устройств является «лёгким в создании», поскольку его можно описать поэтапно. Его лёгкость в создании еще больше усиливается благодаря использованию текстовых процессоров и цифровых камер. Но помимо технологий важно и отношение к культуре обучения. Например, один учитель возражал против того, что детям должно быть разрешено писать о том, что им нравится: «Когда они пойдут на работу, им придется выполнять указания, а не придумывать свои». В этом заключается причина неудачи многих детей при обучении чтению. Конечно, мы должны научить детей навыкам самоконтроля, которые необходимы для выполнения указаний. Но смешивание процессов обучения этому навыку и навыку умения писать приводит к полному поражению в достижении того, и другого результата.

Перевод: Olya Mars

Еще

«Ни математика, ни человек не могут быть полностью поняты, будучи отделенными друг от друга.»
— Сеймур Пейперт


image

Про #philtech

#philtech (технологии + филантропия) — это открытые публично описанные технологии, выравнивающие уровень жизни максимально возможного количества людей за счёт создания прозрачных платформ для взаимодействия и доступа к данным и знаниям. И удовлетворяющие принципам филтеха:

1. Открытые и копируемые, а не конкурентно-проприетарные.
2. Построенные на принципах самоорганизации и горизонтального взаимодействия.
3. Устойчивые и перспективо-ориентированные, а не преследующие локальную выгоду.
4. Построенные на [открытых] данных, а не традициях и убеждениях
5. Ненасильственные и неманипуляционные.
6. Инклюзивные, и не работающие на одну группу людей за счёт других.

Акселератор социальных технологических стартапов PhilTech — программа интенсивного развития проектов ранних стадий, направленных на выравнивание доступа к информации, ресурсам и возможностям. Второй поток: март–июнь 2018.

Чат в Telegram
Сообщество людей, развивающих филтех-проекты или просто заинтересованных в теме технологий для социального сектора.

#philtech news
Телеграм-канал с новостями о проектах в идеологии #philtech и ссылками на полезные материалы.

Подписаться на еженедельную рассылку


ссылка на оригинал статьи https://habr.com/company/philtech/blog/427501/

О чем пишут в тех.поддержку видеостримера?

Всем привет. В нашу поддержку ежедневно открывают десятки различных обращений, от простых вопросов «помогите настроить кластер» до очень сложных «не работает поток, иногда заикается» поток, но есть вопросы, от которых уже глаз дергается и каждый сотрудник компании может подробно ответить.

А раз уж вопросы не прекращаются, а значит можно и тут ответить.

Почему видео вещается с задержкой?

У нас в блоге уже две статьи (раз, два) на эту тему, прочитайте их, если работаете с видео, а тут я дам короткий и исчерпывающий ответ:

Современный интернет стримминг — это HLS протокол. Иногда DASH, но это не принципиально, ведь они оба сегментные.

Как это работает? Потоковое видео «нарезается» на небольшие файлы (как правило, 2-8 секунд, в зависимости от динамичности контента), накапливается 3-10 таких сегментов и описываются специальным плейлистом, который автоматически обновляется при удалении старого сегмента и добавлении нового. Вот так просто. Больше сегментов — больше задержка, больше продолжительность каждого сегмента — больше задержка. 10-20 секунд — это нормально.

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

Что делать, если нужно видео без задержки? Выбирайте другой протокол, если вы собираетесь устраивать веб-чат, управлять коптером через интернет, смотреть видео IP-камеры. Вот примеры: WebRTC, MSE-LD, RTMP.

Как защитить видео? Вставить только на свой сайт

Задача очень простая — видео на сайте должно быть защищено от вставки на другие сайты, никто не хочет платить за чужой трафик, видео трафик дорогой. А еще видео может быть приватным и не должно попасть за пределы личного кабинета.

На все подобные обращения у меня всегда один ответ — вам нужно настроить Securelink на вашем сайте. Защита контента невозможна в одностороннем порядке — сайт должен сам генерировать ссылки, нельзя просто взять и вставить статическую ссылку на сайт.

Securelink — старая и весьма эффективная технология для защиты ссылок. Многим хабрачитателям известно про специальный модулья для Nginx — ngx_http_secure_link_module. У нас не используется Nginx, но есть аналогичная и не менее эффективная реализация, разница лишь в порядке параметров.

Как это работает? Сайт генерирует уникальную одноразовую ссылку на основе данных о пользователе. А что веб-серверу известно о клиенте? Правильно, это IP-адрес, User-Agent, Cookie, запрашиваемый URL. Если клиент авторизован, то в переменных сессии можно получить и другую информацию, например, уникальный ID клиент в базе сервиса, или, например, срок действия подписки.

Собираем параметры в одну строку и хешируем любимым алгоритмом, например, SHA1. Получается набор бесполезных символов. Например, хеш от строки «127.0.0.1Habr» будет: 70ebe94671dd21bd65f4a00dfd988adc83fe6bda.

Эта строка будет передаваться видеостримеру и его задача будет проверить валидность ссылки, что она сгенерировать именно вашим сайтом, не «протухла» и не передана третьем лицам. Обратной связи с сайтом нет, поэтому видео стример должен сгенерировать хеш, используя те же данные, что использовал веб-сайт. Видеостример тоже знает IP-адрес клиента, запрашиваемый контент, но никак может знать ни ID пользователя, ни срок жизни ссылки. Придется передавать эти данные прямо в ссылке и использовать секретный ключ, чтобы кто угодно не мог генерировать себе ссылки.

Берем строку «127.0.0.1Habr1540327100SECRET» и получаем SHA1 99fe961672c52aa3033b98b545ec2cdec93bf515, а теперь формируем ссылку вида:

example.com/Habr/index.m3u8?token=99fe961672c52aa3033b98b545ec2cdec93bf515-1540327100

example.com — ваш видеосервер, Habr — запрашиваемое видео, index.m3u8 — стандартное имя HLS плейлиста, значение token — строка от веб-сервера, которую мы с вами сгенерировали.

Видеостример легко извлекает из этих данных все, что нужно для получения такого же хеша: IP-адрес читается из переменной веб-сервера, запрашиваемый контент из URL, время жизни — из параметра token, единственное что ему не хватает — это секретного ключа, его придется прописать в конфиг файле и хранить в секрете.

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

Подводные камни

Очень хотелось описать в два абзаца, но короче не получилось. Это и есть первая проблема — не каждый готов вникать в такие детали, ведь намного проще вставить статическую ссылку. У нас на сайте есть готовые примеры, поэтому тут не должно быть проблемы.

Очень часто бывается, что сайт и веб-сервер неправильно определяют IP-адрес клиента, это нормально, если используются CDN сети, например, CloudFlare. В таком случае нужно забирать IP-адрес из правильного заголовка, может потребовать помощь провайдера CDN. Например, у CloudFlare это CF-Connecting-IP.

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

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

Вместо итога

Расскажите в комментариях, как обойти такой механизм защиты ссылок?


ссылка на оригинал статьи https://habr.com/company/erlyvideo/blog/427499/