Напомним на всякий случай, если кто-то забыл, что GitHub – это одна из крупнейших платформ для разработки программного обеспечения и дом для многих популярных проектов с открытым исходным кодом. На страничке «Explore» GitHub вы можете найти информацию о проектах, которые набирают популярность, проектах, понравившихся людям, на которых вы подписаны, а также популярные проекты, объединенные по направлениям или языкам программирования.
Чего вы не найдете, так это персональных рекомендаций проектов, основанных на вашей активности. Это несколько удивляет, поскольку пользователи ставят огромное количество звезд различным проектам ежедневно, и это информация может быть с легкостью использована для построения рекомендаций.
В этой статье мы делимся нашим опытом построения системы рекомендаций для GitHub от идеи до реализации.
Каждый пользователь GitHub может поставить звезду приглянувшемуся ему проекту. Имея информацию о том, каким репозиториям каждый пользователь поставил звезды, мы можем найти похожих пользователей и рекомендовать им обратить внимание на проекты, которые они, возможно, еще не видели, но которые уже понравились пользователям со схожими вкусами. Схема работает и в обратную сторону: мы можем найти проекты, похожие на те, что уже понравились пользователю, и рекомендовать их ему.
Другими словами, идея может быть сформулирована так: получить данные о пользователях и звездах, которые они поставили, применить методы коллаборативной фильтрации к этим данным и обернуть все в веб-приложение, с помощью рекомендации станут доступны для конечных пользователей.
GHTorrent – замечательный проект, который собирает данные, полученные с помощью публичных GitHub API, и предоставляет к ним доступ в виду ежемесячных дампов MySQL. Эти дампы можно найти в разделе «Downloads» сайта GHTorrent.
Внутри каждого дампа можно найти SQL-файл с описанием схемы базы данных, а также несколько CSV-файлов с данными из таблиц. Как мы уже говорили в предыдущем разделе, наш подход основан на коллаборативной фильтрации. Этот подход подразумевает, что нам необходима информация о пользователях и их предпочтениях или, перефразируя это в терминах GitHub, о пользователях и звездах, которые они поставили различным проектам.
К счастью, упомянутые дампы содержат всю необходимую информацию в следующих файлах:
watchers.csv
содержит список репозиториев и пользователей, которые поставили им звездыusers.csv
содержит пары user id и имя пользователя на GitHubprojects.csv
делает то же самое для проектов.Давайте посмотрим на данные более внимательно. Ниже приведено начало файла watchers.csv
(названия колонок добавлены для удобства):
Можно видеть, что проект с id=1 понравился пользователям с id=1, 2, 4, 6, 7, … Колонка с временной меткой нам не понадобится.
Неплохое начало, но прежде чем переходить к построению модели, было бы неплохо посмотреть на на данные более пристально и, возможно, почистить их.
Интересный вопрос, который сразу же приходит в голову, звучит так: «Сколько звезд в среднем поставил каждый пользователь?» Гистограмма, показывающая количество пользователей, поставивших различное количество звезд, приведена ниже:
Хмм… Выглядит не очень информативно. Похоже, что абсолютное большинство пользователей поставили очень малое количество звезд, но некоторые пользователи поставили их более 200 тысяч (ого!). Визуализация данных ниже подтверждает наши предположения:
Все сходится: один из пользователей поставил более 200 тысяч звезд. Также мы видим большое количество выбросов – пользователей с более чем 25 тысячами звезд. Перед тем как продолжить, давайте посмотрим, кто этот пользователь с 200 тысячами звезд. Встречайте нашего героя – пользователь с ником 4148. В момент написания этой статьи страница возвращает 404-ю ошибку. Серебряный призер по количеству поставленных звезд – пользователь с «говорящим» именем StarTheWorld с 46 тысячами звезд (страница также возвращает 404-ю ошибку).
Теперь видно, что переменная подчинена экспоненциальному распределению (нахождение его параметров может оказаться интересной задачей). Важное наблюдение заключается в том, что примерно половина пользователей оценила менее пяти проектов. Это наблюдение окажется полезным, когда мы приступим к моделированию.
Давайте обратимся к репозиториям и взглянем на распределение количества звезд:
Как и в случае с пользователями, мы имеем один очень заметный выброс – проект freeCodeCamp с более чем 200 тысячами звезд!
Гистограмма случайной величины количества звезд у репозитория после логарифмического преобразования приведена внизу и показывает, что мы снова имеем дело с экспоненциальным распределением, но с более резким спуском. Как можно видеть, только малая часть репозиториев имеет более десяти звезд.
Чтобы понять, какие манипуляции с данными нам необходимо проделать, мы должны более пристально ознакомиться с методом коллаборативной фильтрации, который мы собираемся использовать.
Большинство алгоритмов коллаборативной фильтрации основаны на факторизации матриц и факторизуют матрицы предпочтений пользователей. В ходе факторизации находятся скрытые характеристики продуктов и реакция пользователя на них. Зная параметры продукта, который пользователь еще не оценил, мы можем предсказать его реакцию, основываясь на его предпочтениях.
В нашем случае мы имеем матрицу размером m x n
, где каждая строка представляет пользователя, а каждый столбец – репозиторий. r_ij
равно единице, если i
-ый пользователь поставил звезду j
-му репозиторию.
Матрица R
может быть легко построена с помощью файла watchers.csv
. Однако давайте вспомним, что большинство пользователей поставили очень мало звезд! Какую информацию о предпочтениях пользователя мы можем выяснить, имея так мало информации? По факту, никакую. Очень сложно делать предположения о чьих-то вкусах, зная только об одном предмете, который вам нравится.
В то же время «однозвездочные» пользователи могут существенно повлиять на предсказательную силу модели, внося неоправданный шум. Поэтому было решено исключить пользователей, о которых мы имеем мало информации. Эксперименты показали, что исключение пользователей с менее чем тридцатью звездами дает хорошие результаты. Для исключенных пользователей рекомендации строятся на основании популярности проектов, что дает неплохой результат.
Давайте теперь обсудим важный вопрос оценки эффективности модели. Мы использовали следующие метрики:
и пришли к выводу, что метрика «точность-полнота» не слишком помогает в нашем случае.
Но прежде, чем мы начнем, имеет смысл упомянуть о еще одном простом и эффективном методе оценки эффективности – построении рекомендаций для самих себя и субъективной оценки, насколько они хороши. Конечно, это не тот метод, о котором вы захотите упоминать в вашей докторской диссертации, но он помогает избежать ошибок на ранних стадиях. Например, построение рекомендаций для самих себя с использованием полного набора данных показало, что получаемые рекомендации не совсем релевантны. Релевантность значительно возросла после удаления пользователей с малым количеством звезд.
Вновь обратимся к метрике «точность-полнота». Говоря по-простому, точность модели, предсказывающей один из двух возможных исходов, – это отношение числа истинно-положительных предсказаний к общему числу предсказаний. Это определение можно записать в виде формулы:
Таким образом, точность – это количество попаданий в цель к общему количеству попыток.
Полнота – это отношение числа истинно-положительных предсказаний к количеству положительных примеров во всех данных:
В терминах нашей задачи точность может быть определена как отношение репозиториев в рекомендациях, которым пользователь поставил звезды. К сожалению, эта метрика дает нам не очень много, так как наша цель – предсказать не то, что пользователь уже оценил, а что он с большой долей вероятности оценит. Может случиться так, что некоторые проекты имеют набор параметров, делающих их хорошими кандидатами на роль следующих понравившихся пользователю проектов, и единственная причина, почему пользователь не оценил их, – это то, что он их еще не видел.
Можно модифицировать эту метрику с тем, чтобы сделать ее полезной: если бы мы могли измерить, сколько из рекомендованных проектов пользователь в последующем оценил, и разделить ее на число выданных рекомендаций, то мы бы получили более корректное значение точности. Однако в данный момент мы не собираем никакой обратной связи, так что точность – это не та метрика, которой бы мы хотели пользоваться.
Полнота, применительно к нашей задаче, – это отношение количества репозиториев в рекомендациях, которым пользователь поставил звезды, к количеству всех репозиториев, оцененных пользователем. Как и в случае с точностью, эта метрика не слишком полезна, потому что количество репозиториев в рекомендациях фиксировано и достаточно мало (100 в данный момент), и значение для точности близко к нулю для пользователей, оценивших большое количество проектов.
Принимая во внимание мысли, изложенные выше, было решено использовать среднеквадратическое отклонение в качестве основной метрики для оценки эффективности модели. В терминах нашей задачи метрика может быть записана так:
Иначе говоря, мы измеряем среднеквадратическую ошибку между пользовательским рейтингом проекта (0 и 1) и предсказанным рейтингом, который будет близок к 1 для репозиториев, которые, по мнению модели, пользователь оценит. Заметим, что w равно 0 для всех r_ij = 0
.
Как уже было сказано, наша система рекомендаций основана на факторизации матриц, а точнее на алгоритме alternating least squares (ALS). Стоит заметить, что согласно нашим экспериментам, любой алгоритм факторизации матриц также будет работать (SVD, NNMF).
Реализации ALS доступны во многих программных пакетах для машинного обучения (смотрите, например, реализацию для Apache Spark). Алгоритм пытается разложить оригинальную матрицу размера m x n на произведение двух матриц размера m x k
и n x k
:
Параметр k
определяет количество «скрытых» параметров проекта, которые мы пытаемся найти. Значение k
влияет на эффективность модели. Значение k
следует подбирать с помощью кросс-валидации. График, приведенный ниже, показывает зависимость величины RMSE от значения k
на тестовом наборе данных. Значение k=12
выглядит как оптимальный выбор, поэтому было использовано для финальной модели.
Давайте подведем итог и посмотрим на получившуюся последовательность действий:
watchers.csv
и удаляем всех пользователей, оценивших менее 30-ти проектов.k
, используя RMSE и тестовые данные.k
.Имея устраивающую нас модель, мы можем приступить к обсуждению вопроса о том, как сделать ее доступной для конечных пользователей. Другими словами, как построить веб-приложение вокруг нее.
Вот список того, что должен уметь наш бэкенд:
Поскольку мы хотели сделать все быстро и просто, выбор пал на следующие технологии: Django, Django REST framework, React.
Для того чтобы корректно обрабатывать запросы, необходимо хранить некоторые данные, полученные с GHTorrent. Основная причина в том, что GHTorrent использует свои собственные идентификаторы пользователей, не совпадающие с идентификаторами на GitHub. Таким образом, мы должны хранить у себя пары user id <-> user GitHub name
. То же самое касается репозиториев.
Поскольку количество пользователей и репозиториев достаточно велико (20 и 64 миллиона соответственно) и мы не хотели тратить большое количество денег на инфраструктуру, было решено попробовать «новый» тип хранилища с компрессией в MongoDB.
Итак, мы имеем две коллекции в MongoDB: users
и projects
.
Документы из коллекции users
выглядят следующим образом:
{
"_id": 325598,
"login": "yurtaev"
}
и проиндексированы по полю login
для ускорения обработки запросов.
Пример документа из коллекции projects
приведен ниже:
{
"_id": 32415,
"name": "FreeCodeCamp/FreeCodeCamp",
"description": "The https://freeCodeCamp.org open source codebase and curriculum. Learn to code and help nonprofits."
}
Как можно видеть, компрессия с использованием zlib дает нам двукратный выигрыш в плане использования дискового пространства. Одним из опасений, связанных с использованием сжатия, была скорость обработки запросов, но эксперименты показали, что время меняется в пределах статистической погрешности. Больше информации о влиянии сжатия на производительность можно найти тут.
Резюмируя, можно сказать, что компрессия в MongoDB дает существенный выигрыш с точки зрения использования дискового пространства. Другим преимуществом является простота масштабирования – это будет очень кстати, когда объем данных о репозиториях и пользователях перестанет помещаться на один сервер.
Существует два подхода к использованию модели:
Преимуществом первого подхода является то, что модель не будет «бутылочным горлышком» (в данный момент модель может обрабатывать от 30 до 300 запросов на рекомендации в секунду). Главный недостаток – объем данных, который необходимо хранить. Есть 20 миллионов пользователей. Если мы будем хранить 100 рекомендаций для каждого пользователя, то это выльется в 2 миллиарда записей! Кстати, большинство из этих 20 миллионов пользователей никогда не воспользуются сервисом, а это значит, что большая часть данных будет храниться просто так. И последнее, но не менее важное: построение рекомендаций занимает время.
Преимущества и недостатки второго подхода – зеркальное отображение преимуществ и недостатков подхода первого. Но что нам нравится в построении рекомендаций по запросу – это гибкость. Второй подход позволяет возвращать любое количество рекомендаций, которое нам необходимо, а также позволяет легко заменить модель.
Взвесив все «за» и «против», мы выбрали второй вариант. Модель была упакована в Docker контейнер, и возвращает рекомендации с помощью RPC вызова.
Ничего сверхинтересного: React, Create React App и Semantic UI. Единственная хитрость – React Snapshot был использован для предварительной генерации статической версии главной страницы сайта для лучшей индексации поисковиками.
Если вы пользователь GitHub, то вы можете получить свои рекомендации на сайте GHRecommender. Обратите внимание, если вы оценили менее 30 репозиториев, то вы получите в качестве рекомендаций самые популярные проекты.
Исходники GHRecommender доступны здесь.
✎ Соавтор текста @avli
]]>"... пора мигрировать код с Питона на Node.js ..."
Этот вопрос у себя в голове прокручиваю очень давно и прийти к однозначному ответу не могу, так как мыслей у меня достаточно много. Попытаюсь порассуждать вслух.
Что есть у нас:
Вопрос: Имеет ли смысл использовать язык JavaScript для новых проектов при текущем наборе людей/при обучение новых людей?
Для этого следует ответить на следующие вопросы:
Это один из самых критичных вопросов в ситуации, когда половина новых проектов представляет из себя сайты средней сложности. Что такое сайты средней сложности? Это сервисы вроде мини-instagram/pinterest, где есть социальный функционал или контентные сайты, для которых нужна только админка, что бы добавлять контент, и минимальная логика для обычных пользователей.
Я с уверенностью могу сказать, что реальных аналогов django/rails нет, и с каждым годом я в этом убеждаюсь всё больше, т.к время тут играет очень важную роль. Оба проекта были выпущены в начале 2000-х, и за десятилетние развитие разработчики фреймворков смогли отшлифовать и сбалансировать свой функционал почти до идеального состояния.
Да, если загуглить что-то типа аналог rails для языка {name}
, то можно заметить, что на каждом языке есть проекты, которые называют себя аналогом рельсов. Но, если следовать правилу 80/20, то они реализуют базовый набор необходимого функционала, а вот для реализации остальных 20% им потребуются годы.
С виду, если пройтись по туториалам всех популярных веб-фреймворкам, то покажется, что они все очень простые для изучения, но на деле просты только при написание хеллоу ворлдов, а начинать серьезный проект я бы не стал по нескольким причинам:
Проблемы базового функционала и предоставляемого API фреймворка
Как и django, так и рельсы обладают очень обширным внутренним API (на мой вкус, у django лучше, просто мне не нравится программирование, построенное на соглашениях), при помощи которого можно малыми силами реализовать функционал, которого из коробки нет во фреймворке. Например: отлавливать событие регистрации пользователя и отправки ему письма. Я уже не говорю, что можно использовать из самой коробки:
Есть ли решения на JavaScript со схожими возможностями? Нет! Все эти SailsJS/Express/Koa/etc тянут только на звание мини веб-фреймворков, но не как на аналог django/rails. Я не говорю что они плохи, они решают свою маленькую задачу, но это не альтернатива django, просто они из разных весовых категорий.
Количество и качество сторонних батареек.
Тут я даже не знаю какие примеры приводить. Из-за того, что нет четкого лидера, усилия сообщества размазаны по нескольким решениями, и опять же фактор времени играет важную роль.
Достаточно попробовать написать сайт с поддержкой авторизации через социальные сети, фоновыми задачами а-ля celery, прозрачной загрузкой файлов в S3, с ресайзом картинок, с социальными фитчами: фоловить/дружить/общаться и т.д. Да, возможно, для половины функционала найдутся батарейки, но возможности и качество их будут не на высоте. Достаточно изучить существующие решения для работы с очередями.
Выводы об альтернативах django/rails с одной стороны очевидны, но не стоит забывать о том, что веб двигается немного в другую концептуальную сторону в плане взаимодействия клиент/сервера, но об этом в выводах.
Тут коротко. Всё что угодно лечше pip'а!
Коммьюнити очень большое. Но у php коммьюнити тоже не маленькое! Таким образом, это не показатель. Но отмечу, что самые интересные новые решения появляются из этого коммьюнити. P2P торенты/звонки/чаты в браузере, изоморфные приложения, которые не привязаны к клиент/серверному представлению, десктоп приложения на основе Node.js и т.п. На мой взгляд сейчас от этого немного пользы, но тренд появления на js прикольных вещей только увеличивается из года в год.
Большое коммьюнити приводит к появлению большого количества библиотек. Но это снова не показатель. Очень много библиотек плохого качества. Много интересных библиотек, которые перестали поддерживаться. Хуже всего много раскрученных библиотек, которые форсируют плохую архитектуру (применение инструментов для неподходящих задач - бич всей разработки в целом). Библиотек много, но нет устоявшегося стека. Для большинства важных задач существует как минимум два решения, с одной стороны всегда хорошо, когда есть выбор, а с другой - это очень сильно разделяет сообщество. Можно каждый раз начинать новый проект и за основу брать еще не испробованные решения. Тут у любого начнут разбегаться глаза (при условии, что разработчик смотрит по сторонам, иначе до конца жизни будет писать SPA на jQuery), еще сложнее из этого разнообразия подобрать хороший набор повседневных инструментов. Черт возьми, да, только для сборки проектов существует 5+ решений, каждый из которых вполне достоин. Рассуждать и спорить на эту тему можно бесконечно, и всё будет сводится к большому ИМХО.
Количество сервисов для JavaScript будет только расти дальше. Недавний пример AWS Lambda в которой поддержка платформы Node.js была первой. Parse/Google Node.js/etc, их будет только больше. Я считаю это всё ерундой, я за движение noBackend, а это означает почти только JavaScript.
Язык для 2015 года отвратительный. Предоставляемый API для написания асинхронного кода - просто слезы, в сочетание с другой болью вроде передачей контекста исполнения, ... Все это просто превращается в кровавую бойню. Сейчас новый тренд - хвалить новый стандарт ~~ECMAScript 6~~ ECMAScript 2015 и кричать, что он решит ВСЕ проблемы. Да, возможно, что-то он и решит, но, во-первых, он решает всё с таким типичным привкусом js, а, во-вторых, принесет новые проблемы (дополнительные контексты при задании дефолтных значений аргументов SERIOUSLY?). Тема ECMAScript 2015 заслуживает отдельного поста, у меня есть запас ярости по этому вопросу.
Есть. Много. Больше чем надо. Есть ли достойные решения? Можно найти несколько решений уровня sqlalchemy
, но меня больше интересует интеграция ORM с веб-фреймворком для того, что бы генерировать формы, REST API, админки, отчеты и т.д. А так да, есть вполне достойные варианты, даже с миграциями. НО я только с ними игрался, и как поведут они себя в продакшене сказать не могу.
Обучать JavaScript'ту как первому языку я бы не стал. У меня по этому вопросу есть пара мыслей:
Но если нам нужны послушные обезьянки, которые 24/7/365 способны заниматься монотонной разработкой похожих друг на друга приложений, то не могу привести доводов против.
Но тут нужно понимать, что backend ≠ frontend разработке, и это совершенно разные сферы деятельности. Громкие слова о том, что один разработчик будет писать нам и сервер, и клиентское приложение, хороши только на бумаге, еще некоторые фантазируют, что на этом можно сэкономить, возьмем одного студента, и он будет работать за двоих. Так это не работает: либо на выходе будет получаться дольше и очень плохо, либо, если всё же найдете упоротого чувака, который будет способен всё делать, то ему придется платить за двоих или за полтора человека, но при этом ириски© будут больше. Но всё же, если целенаправленно планомерно развивать команду вширь, то можно добиться хороших результатов, это потребует ресурсов, и это не значит что с другим стеком это не сработало так же.
JavaScript - это платформа будущего. То, на что метила Java в свое время, теперь почти победил JavaScript. JavaScript это:
Я тут имею ввиду под JavaScript не просто язык, а платформу, на которой, например, можно запускать другие языки. Несмотря на то, что я просто ненавижу чистый JavaScript, стоит признать, что он побеждает, к сожалению. А побеждает он только за счет того, что ему посчастливилось быть интегрированным в браузер, а браузер сейчас есть везде и нужен всем.
Все пытались влезть в эту нишу языков в браузере. Microsoft => silverlight, который умер, поверх которого можно было даже писать на python в браузере. Google => dart, который скоро умрет. Sun => Java уже давно проиграли. Тут не надо быть большим аналитиком, чтобы понять, что все подобные попытки обречены на провал, потому что для победы нужно объединится всем, а это очень тяжелый шаг для гигантов. Только сейчас они делают попытки объединится и сделать общий стандарт для asm.js, и то под другим названием т.к изначально это разработка Mozilla. И это объединение не против JavaScript, а за его улучшение. Так что у JavaScript как минимум есть будущее.
Прежде чем делать какие либо выводы, сначала нужно обговорить несколько моментов.
Первая проблема всей индустрии - это неумение выбирать подходящие инструменты под каждую конкретную задачу. Тут не важно, на чем писать, JavaScript или python. Выбрать язык X и думать, что вы нашли идеальный инструмент под все свои задачи, является ошибкой. Нужно постоянно смотреть по сторонам, иначе обречены на боль и страдания.
Вторая проблема - это думать, что выбрав правильно технологию, всё будет хорошо. Но на мой взгляд, фактор людей намного, намного важнее. Т.е можно писать хоть на php, но если это делают отличные спецы, то результат будет предсказуемо хороший, а вот группа приматов... Т.к это всё новое направление без большой готовой базы решений, разработчику придется самому находить решения поставленных задач, а для этого он должен обладать хорошим скилом и умением тащить сложные задачи.
Далее нужно немного пофантазировать, куда будет двигаться индустрия хотя бы ближайшие 3-5 лет.
Django - это очень хороший инструмент, но это инструмент который решает задачи прошлого. Т.е это инструмент для создания сайтов web 1.0 (что бы это не значило), а всё постепенно двигается в другую сторону, когда у нас большие жирные приложения работают на стороне клиента в браузере, а сервер нужен только для того что бы получить данные, которые уже отобразятся нужным образом на стороне клиента. Т.е максимум от сервера нужен только REST API для получения данных и всё (хранения файлов, рассылка писем и т.п давно уже заменяются облачными сервисами).
Связка django + rest-framework - одна из лучших для клепания REST API. А вот делать реалтаймовые приложения с websockets на django - уже плохая идея. Тут либо уходить на решения типа tornado/twisted, вокруг которых батареек кот наплакал, либо приглядываться к решениям поверх Node.js, где с этим немного получше. Если посмотреть на roadmap django, то в ближайшем будущем кардинально ничего не поменяется.
С серверной частью немного разобрались, но JavaScript метит еще в несколько направлений. Это мобильная разработка и десктоп.
С десктоп всё просто, нативные приложения потихоньку вымирают, взамен у нас жирные веб приложения, а тем, кому лень еще и писать нативные приложения с нуля, пилят приложения поверх ~~node-webkit~~ nw.js. Почему? Да потому что это проще и быстрее. Когда есть уже готовые веб-приложения, то проще перенести наработки в виде js, чем писать под все платформы с нуля.
С мобильными всё примерно тоже самое. Т.к у меня на телефоне не стоит ни одной игрушки, то я не нашел ни одного приложения, которого я бы теоретически не смог бы написать на JavaScript. Т.е большая часть приложений заключается в том, что бы сходить дернуть REST API и показать что-то пользователю.
Выбор за вами...
]]>Теперь это не просто html страничка с ajax запросами на нажатия кнопочек, а полноценное развесистое приложение в браузере, с поддержкой WebSockets для двусторонней связи, с обработкой файлов прям из js на стороне клиента, да еще и оффлайн работой.
Каждую неделю выходит ~30 различных библиотек со схожим функционалом что и предыдущие 300. Каждый тянет одеяло на себя вместо того что бы объединить усилия и черт возьми наконец-то разгрести этот ад что творится во фронтенде. Мне сложно представить как в это время новенькие вообще могут успешно стартануть в веб разработке при таком количестве разнообразных путей для решения одной и той же задачи.
И не удивительно что люди уже не способны выбрать нужный инструмент под задачу, потому что искать в океане поделок можно очень долго, и не факт что найденное решение внутри окажется нормальным. Тут конечно еще играет свою роль факт что люди идиоты и когда читаешь наезды типа – «ангуляр плохой потому что тормозит на 2000-ях биндингах», да конечно тормозит! потому что ты идиот! в нормальном приложение не должно быть так. А потом появляется FLUX архитектура которая как раз вот для задач когда эти самые 2000 биндингов нужны, но нет! мы будем писать meduza.io на React для отображения 27 статических новостей на страничке (на самом деле это круто что кто-то может себе позволить так поиграться в продакшене).
Короче мой посыл вообще не об этом, а о том что даже самые простые библиотеки требуют большого количества телодвижений и знаний. Например вот нужно обычному человеку (он может быть отличным OCaml разработчиком, но ему нафиг не надо знать как писать фронтенд) встроить в свой бложик красивые графики. И что же сейчас для этого надо сделать:
<div id="my-cool-chart"></div>
с нужным idВ самом просто варианте выглядит это примерно так:
<script src="Chart.js"></script>
<canvas id="myChart" width="400" height="200"></canvas>
<script>
var data = {
labels: ['mon','tue','wed','thu','fri','sat','sun'],
datasets: [
{
data: [10,14,20,25,13,9,40]
},
{
data: [40, 9, 13, 25, 20, 14, 10]
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx).Line(data);
</script>
Человек просто хотел добавить графики в свой бложик, а в итоге вынужден программировать на html/css/javascript.
И тут врываются веб-компоненты, которые совсем не про создание полноценных приложения, а про удобные/универсальные кирпичики из которых можно строить логику, не тратив много сил на то что бы положить кирпич в нужное место, в нужный лунный цикл и без докторской степени по кирпичам 2014 года.
И так как уже существует миллион готовых библиотек на все случай жизни, ближайшее время веб-компоненты будут из себя представлять мостик между низкоуровневым API для разработчиков и Human API которым без больших усилий сможет воспользоваться несчастный OCaml программист.
Возвращаясь к примеру с графиками, с веб-компонентами это будет уже выглядеть намного проще:
<link rel="import" href="chart-elements.html">
<chart-line
width="400" height="200"
labels="['mon','tue','wed','thu','fri','sat','sun']"
values="[[10,14,20,25,13,9,40], [40, 9, 13, 25, 20, 14, 10]]">
</chart-line>
Никакого программирования, только необходимые данные (но как и весь фрондент => всё также уродливо ^_^ )
Коротко:
<tabs></tabs>
прямо в вёрсткеесли бы полицейские были, как программисты, то по ночам наряжались бы в бэтменов и боролись с преступностью в своё удовольствие
После обновления на OS X Yosemite мне захотелось избавится от зависимости homebrew, не от homebrew как такового, а от установки при помощи него всяких mysql, postgres, redis и т.д. На самом деле из-за homebrew уже давно не накатываю обновления поверх старой системы, а делаю полностью новою установку с форматированием диска. Для этого есть несколько причин:
Чаще всего у меня ломаются серверные пакеты из homebrew (о ужас когда-то это был macports), и после обновления в 90% случаев сервер mysql оказывается в положение кота шредингера, он вроде есть, и в тоже время его нет. Ситуацию еще усугубляет python, наверное каждый python разработчик сталкивался с болью установки mysql-python
под Mac OS (слава богам что для меня эти времена прошли).
Так вот, после обновления на Yosemite было решено попробовать docker для поднятия всех этих серверных «штук». Как поднимать docker под Mac OS подробно расписано в документации, я лишь скажу что использовать docker в сыром виде для этих целей не лучший вариант.
И тут на помощь приходит Fig который идеально прижился у меня. Всё что необходимо, это описать конфиг:
redis:
image: redis
ports:
- "6379:6379"
postgres:
image: postgres
ports:
- "5432:5432"
couchdb:
image: "klaemo/couchdb"
ports:
- "5984:5984"
И дальше манипулировать контейнерами как угодно:
$ fig up redis
# или запустить в фоне
$ fig up -d redis
# или запустить всё в фоне
$ fig up -d
$ fig ps
Name Command State Ports
-----------------------------------------------------------------------------
couchdb_1 /entrypoint.sh couchdb Exit 0 0.0.0.0:5984->5984/tcp
postgres_1 /docker-entrypoint.sh postgres Exit 0 0.0.0.0:5432->5432/tcp
redis_1 /entrypoint.sh redis-server Up 0.0.0.0:6379->6379/tcp
Fig
достаточно гибкий в настройке. Можно например указать какие папки примаунтить в контейнер (для Mac OS fig >= 1.0.0
), полезно для БД, или указать что контейнеру нужен privileged mode
, или поставить лимит на RAM, и т.п что можно указать напрямую для docker, только в удобном для редактирования yaml файле.
Единственная проблема которую решил не полностью, это отсутствие в хосте установленных клиентов типа redis-cli
или psql
, но обычно «хорошие» образы позволяют решить и это. Например для редиса я сделал себе alias:
$ alias redis-cli="docker run -it --link yurtaev_redis_1:redis --rm redis sh -c
> 'exec redis-cli -h
> \"\$REDIS_PORT_6379_TCP_ADDR\" -p \"\$REDIS_PORT_6379_TCP_PORT\"'"
$ redis-cli
172.17.0.12:6379> SET qwerty 213
А еще можно так:
$ alias f="fig -f $HOME/fig.yml"
$ f stop
и из любого места управлять контейнерами
/etc/hosts
отдельный хост который всегда указывает на boot2docker ip
Хотел написать 140 слов о Parallels adopts Docker in next Cloud Server release, но меня как то понесло...
Я представляю как parallels кусает себе локти. Я нисколько не уменьшаю их заслуги в разработке тулов вокруг виртуализации, они очень много вложили в опенсоурс, но кто из обычных смертных за последние 10-ть лет хоть что-то пробовал запустить от parallels (кроме решения для домохозяек)? Или хотя бы задумывался над тем что продукты parallels могут решить какую-то повседневную проблему?
Docker поэтому и стрельнул т.к любой слабоумный может взять, один раз завернуть свое приложение и запускать его на серверах без боли. А деплой любого приложения это боль, и я всегда смеюсь когда кто-то говорит – «осталось совсем немного, только задеплоть за 15 минут», т.к сам был тем кто это говорил.
Во-первых надо менять процесс разработки, и с первого коммита должен быть непрерывный процесс объединенный с деплоем, если не на dev сервер, то как минимум в бокс vagrant. Это избавит в будущем от проблем когда в последний момент всплывает зависимость типа libjpeg-dev
про которую забыли т.к её поставили один раз руками и всё. Плюс когда деплой интегрирован в разработку и происходит постоянно, так или иначе большинство проблем вылезут до этапа деплоя в продакшен, а так же при наличие ~~комплекса неполноценности~~ ~~неуверенности~~ перфекциониста, всегда будет не нравится то как это делается, и будет хоть понемногу, но улучшать этот процесс.
Во-вторых надо максимально упростить сам запуск приложения. Что происходило раньше:
Так вот второй этап всегда приносил больше всего боли, и причин этому много. Это и различные платформы, и зависимости которые требовали индивидуального подхода (костыли), и приложения соседи, и т.д.
Docker как раз решает эту проблему. Больше не надо нанимать «отдельного программиста» на chef для написания сотен строк рецепта для поднятия приложения. Деплой с docker упрощается и сводится только к тому как/чем распространить контейнер на сервера. В самом простом случае можно зайти руками на сервер и запустить пару команд для поднятия сложного приложения. Если инфраструктура сложнее то без какой либо системы управления не обойтись, но их конфигурация опять же упростится и будет сводится уже только к тому куда и какой контейнер залить.
Насколько сейчас видно, docker пытается пойти в нишу chef и сделать свои тулзы для управления кластерами, я это очень приветствую, хуже шефа они точно не сделают.
На словах это всё звучит как бред, но на практике меня это подкупило. Вот например как выглядит мой конфиг для запуска sentry сервера:
sentry:
image: slafs/sentry
ports:
- "80:9000"
links:
- redis
environment:
SENTRY_URL_PREFIX: "**********"
SECRET_KEY: "**********"
SENTRY_ADMIN_USERNAME: 'admin'
SENTRY_ADMIN_PASSWORD: "**********"
SENTRY_ADMIN_EMAIL: "**********"
DATABASE_URL: "**********"
SENTRY_REDIS_HOST: 'redis_1'
SENTRY_EMAIL_BACKEND: 'django.core.mail.backends.smtp.EmailBackend'
SENTRY_EMAIL_HOST: 'smtp.mailgun.org'
SENTRY_EMAIL_HOST_USER: "**********"
SENTRY_EMAIL_HOST_PASSWORD: "**********"
SENTRY_SERVER_EMAIL: "**********"
redis:
image: redis
Всё что мне надо сделать на сервере это выполнить fig up
и я получаю рабочее приложение.
Docker это не панацея и не решение всех проблем. Для больших проектов всё еще нужно средство для управления кластером и конфигурациями. Для сингл-сервер приложений, типа поднять сайтик на django + redis + postgres, docker сейчас самый мастхев.
Я бы очень хотел сказать что docker это самый лучший в мире инструмент, но я очень насторожено отношусь к людям который очень хвалят что либо. Поэтому сразу скажу что считаю docker еще тем говнищем, которое идет в ногу со временем и поощряет общую глупость массы людей. И мнимая простота docker вводит в заблуждения, и рано или поздно вдарит пользователю в щи, документацию ведь никто не читает, а на всех выступлениях нам показывают как супер просто за 5-ть минут поднять сложнейшее приложение, но никто не рассказывает про боль с которой можно столкнутся. Например каждый второй контейнер на https://registry.hub.docker.com/ вообще не предусматривает ситуации когда приложение крешнится (да я знаю что можно решить на стороне хоста, но про это тоже не рассказывают), или правильной настройкой логгирования для того что бы потом не искать по всей системе причины падения.
Как и любое помешательство на чем либо, всеобщая истерия про docker плохо, но она указывает на проблему которую до сих пор не решили. Еще кстати вопрос насколько это большая истерия, и сколько людей на самом деле это волнует, и сколько вообще слышало про docker, но это уже другая тема по поводу которой меня может занести еще дальше.
P.S я не имею реального опыта по управлению кластерами, все мой рассуждения для задач когда приложение не требует кластера из десятков серверов.
P.P.S и да я не осилил chef/puppet, я их считаю дерьмовыми продуктами для разворачивания приложения на один сервер. Варианты делать rpm/deb пакеты даже не хочу рассматривать, кажется что это решит проблемы, но будет n+1 проблема.
]]>undefined
and null
#js #frontend #null #undefined