-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

Внедрение инструментов Lean в командe Сервис Деск

Вторник, 06 Июня 2017 г. 19:54 + в цитатник

Предыстория


imageЛюбой сервис для конечных пользователей должен быть гибким, отражающим их текущие потребности. Бизнес развивается, качество сервиса тоже должно расти. Если этого не происходит, рано или поздно уровень услуг, заданных на старте проекта, перестает устраивать потребителей. Поэтому хочу поделиться с вами своим опытом внедрения новых методов работы в нашей команде Сервис Деск (SD).

В конце 2012 года мы запустили в работу услугу SD для одного из наших клиентов в режиме 24/7/365. Полноценной службы SD у заказчика до этого не было, вся поддержка оказывалась силами внутренних подразделений. Под этот проект была подобрана и обучена новая команда, состоящая из 7 сотрудников, включая меня. Сервис стартовал активно — передача знаний, знакомство со спецификой работы. У команды было много идей и энтузиазма. Сервис заработал как часы.

Почему сложно оказывать хороший сервис без перемен в работе?


Состав команды не сильно менялся в течение 3-х лет. Кто знаком с работой SD, тот представляет, как это много. Со временем энтузиазм стал угасать, рутинные задачи поглотили коллектив, а вовлеченность в проект снижалась.

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

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

Что такое Lean?


Бережливое производство (от англ. lean production, lean manufacturing — «стройное производство») — концепция управления производственным предприятием, основанная на постоянном стремлении к устранению всех видов потерь. Бережливое производство предполагает вовлечение в процесс оптимизации бизнеса каждого сотрудника и максимальную ориентацию на потребителя.

Lean подход в нашей компании — совокупность инструментов и принципов, помогающих сформировать и поддерживать культуру постоянного совершенствования.

Принципы Lean подхода следующие:

image

Инструменты и техники, которые мы уже используем на уровне компании:
  1. Communication Cell, или «кружки качества», — встречи команды с четкой программой, эффективный формат внутренней коммуникации.
  2. Demand analysis — способ поиска тенденций по входящим обращениям (например, инцидентам) для уменьшения их количества.
  3. Problem solving session — выявление корневых причин инцидентов и командная выработка мероприятий для их устранения.
  4. Workplace organization — оптимизация физического и виртуального рабочего пространства.
  5. Value stream mapping — инструмент оптимизации рабочих процессов, основанный на их детальном анализе.


Для оперативного исправления ситуации на проекте мы выбрали следующие инструменты:
  • «Кружки качества» — для вовлечения всей команды в процесс улучшения сервиса, визуализации текущих показателей эффективности сервиса, сбора обратной связи.
  • Demand analysis — оценка текущих трендов на сервисе, причин возникновения обращений, определения зон повышенных трудозатрат со стороны SD и клиента.
  • Problem solving session — для выработки действий по достижению новых целевых показателей сервиса, уменьшению трудозатрат, повышению эффективности работы.
  • Workplace organization — для реорганизации базы знаний и файлового хранилища, что поведет за собой снижение временных затрат на поиск информации, необходимой для решения обращений.


Внедрение инструментов на проекте разделили на три этапа:
  1. Запуск «кружков качества» .
  2. Практическое использование инструментов по выявлению, решению проблем.
  3. Организация виртуального рабочего места


Запуск «кружков качества»


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

image

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

Несмотря на необходимость этих перемен, первое, с чем мы столкнулись, — сопротивление со стороны команды.
Сотрудники не хотели принимать участие в собраниях, так как не видели в них смысла. Поэтому нашей задачей стало через «кружки качества» показать команде, как она работает, куда движется и на что нужно обратить внимание. Рассказать о выгодах, которые могут быть, например, сокращение затрат на обработку обращений, автоматизация рутинных задач, оптимизация внутренних процессов.

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

Постепенно интерес к собраниям возрастал.

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

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

Первой задачей команды стал фокус на количестве ошибок, возникающих при заполнении карточки заявки в ITSM-системе. Для определения корневых причин применили инструмент командной работы — сессию по решению проблем (problem solving session).

Проведение сессии по решению проблем


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

Инструмент достаточно прост и состоит из шести этапов:

image

Расскажу немного о каждом этапе:

  • В нашем случае проблемой стал один из показателей эффективности, вышедший за граничные значения.
  • Для определения корневых причин мы провели «тихий» мозговой штурм. Каждый сотрудник зафиксировал по его мнению все факторы, влияющие на появление ошибок в работе.
  • Далее мы распределили все варианты по 4-м зонам и выбрали те варианты, реализация которых даст нам максимальный эффект при минимальных затратах.
  • Совместно с руководителем команды сформировали план внедрения, который еженедельно оценивался на «кружках качества». Срок достижения цели может быть, как месяц, так и год. Зависит от сложности показателя, факторов, влияющих на его формирование. Например, компетенций команды в той или иной области, технических знаний и т.д. Мы выбрали полгода.
  • Определили шаги, в соответствии с которыми стали планомерно двигаться к достижению цели.
  • На промежуточных этапах оценивали тренд, при необходимости выполняли корректирующие процедуры.


image

За полгода процент ошибок в заполнении карточки обращения был снижен с 17% до стабильного уровня в 0.8-1% по отношению к общему числу закрытых обращений.
Мы визуализировали достигнутые значения:

image

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

Следующей целью стало повышение процента обращений, решенных на первой линии без передачи их на последующие (First time fix, FTF).
Для анализа входящих обращений и определения потенциально возможных, которые могут быть закрыты на нашей линии, мы использовали инструмент по выявлению трендов (demand analysis).

Запуск инструмента по выявлению трендов


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

Отсортировали их по количеству:
image

Далее построили диаграмму Парето.
Диаграмма Парето — инструмент, позволяющий распределить усилия для разрешения возникающих проблем и выявить основные причины, с которых нужно начинать действовать.
Принцип Парето (принцип 20/80) означает, что 20% усилий дают 80% результата, а остальные 80% усилий — лишь 20% результата.


image
Сосредоточимся на наших 20%.

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

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

На старте подсчета процент заявок, закрытых на первой линии, был равен 13%. Через полгода мы получили результат уже 23%. Практически каждое 5 обращение было закрыто на стороне SD.

Для клиента это выражается в сокращении трудозатрат второй линии поддержки.
image

Организация виртуального пространства(Workplace organization)


Для продуктивной и качественной работы над обращениями необходимо не только удобно организованное физическое рабочее место, но и виртуальное. За время работы проекта для хранения информации было перепробовано множество инструментов начиная от txt-файла, excel-ки, локальных файловых ресурсов и заканчивая sharepoint.
Чем для нас стало организованное виртуальное рабочее место: вся проектная информация распределена так, чтобы любой старый или новый сотрудник тратил не более минуты на поиск необходимых данных.

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

Для наведения порядка в информационном пространстве мы использовали подход 5S, состоящий из пяти этапов:
  1. Sift (отсеивание);
  2. Sort (сортировка);
  3. Shine (подсвечивание);
  4. Standardise (стандартизация):
  5. Sustain (поддержание).

Sift, Sort, Shine предназначены для изменений, а Standardise и Sustain —для поддержания и проверки соблюдения стандартов соответственно.

image«Sift»: мы провели анализ всех наших мест хранения проектной информации на предмет устаревших или неиспользуемых данных. Всю ненужную информацию переместили в соответствующую папку «Архив» на каждом ресурсе. Все инструкции, документация, хранящуюся на локальных компьютерах, были размещены в общем доступе команды и так же проанализирована. Это позволило оценить общий объем накопленных знаний на проекте. Информация, требующая уточнения, была помечена и постепенно прояснялась. На проекте используется 7 различных ресурсов, содержащих многогранную информацию.

image«Sort» запустил процесс перераспределения всей актуальной информации в соответствии с ее типом. Дубликаты файлов были удалены.

image«Shine»: совместно с командой определили новую файловую структуру хранилищ, а так же ответственных за внесение и изменение информации.

image«Standardise»: создали внутренний стандарт хранения и распределения входящей информации. Наименование файлов и папок, категории информации, периоды обязательной актуализации данных.

image«Sustain»: примение разработанных стандартов и подходов в ходе предоставления сервиса. Проверка соответсвия новых стандартов выполняемым рабочим операциям. Это позволило нам сформировать новый подход к хранению, распределению, актуализации информации.

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

Для клиента изменения стали заметны в точечном исправлении проблемных зон, снижении количества инцидентов, сокращении времени решения обращений, полученных рекомендациях по оптимизации внутренних ИТ-процессов.

Материал по теме.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330372/


Метки:  

Global DevOps Bootcamp + подборка видео

Вторник, 06 Июня 2017 г. 17:57 + в цитатник
Хабр, привет! В середине июня у нас начинается глобальный DevOps Bootcamp, который будет проходить, в том числе, в Москве. Конечно, мы приглашаем на него всех причастных! А пока он не начался, хотим поделиться подборкой свежих видео-материалов по DevOps от Microsoft с Build 2017 и запуска Visual Studio 2017.



Итак, поехали.

DevOps для каждой команды


Экскурсия по Microsoft Azure и Visual Studio Team Services. Вы узнаете о сервисах Microsoft, которые вам помогут в нелегком деле DevOps.



Быстрая настройка DevOps окружения с Azure Marketplace


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



Continuous delivery на Microsoft Azure


Вы научитесь использовать App Service, VMs, Scale Sets, Container Service, Service Fabric и многое-многое другое из Azure Services.



OSS-based DevOps — все дороги ведут в Azure, часть I: CI/CD с Jenkins и Netflix Spinnaker


А вот здесь начинается настоящая практика. Часть 1.



OSS-based DevOps — все дороги ведут в Azure, часть II: Infrastructure as Code с Terraform


А вот здесь начинается настоящая практика. Часть 2.



Agile planning с Visual Studio Team Services (VSTS)


Инструменты для гибкой методологии разработки в VSTS.



Visual Studio Mobile Center и Visual Studio Team Services: для вашего Mobile DevOps


Вы научитесь делать ваших юзеров счастливыми с Visual Studio Team Services и Visual Studio Mobile Center.



Настройте Continuous Integration и Continuous Delivery из Visual Studio 2017


Умеете использовать Visual Studio IDE? Если нет, вам сюда.



DevOps для БД — Redgate Data Tools в Visual Studio 2017


Вы увидите Redgate Data Tools в действии, а также узнаете об основных подводных камнях.



Global DevOps Bootcamp


До ката мы приглашали вас на мероприятие и конечно расскажем о нём подробнее.

Global DevOps Bootcamp – это однодневное мероприятие для разработчиков, которое проводится локальными сообществами DevOps по всему миру 17 июня.

Инициатива проведения принадлежит компаниями Xpirit и Solidify. В Москве организовывается сообществом Microsoft Most Valuable Professional и пройдёт в Digital October.

Global DevOps Bootcamp полностью посвящён практикам и инструментам DevOps, построенных на основе технологий Microsoft. Узнайте всё о новейших тенденциях DevOps, проникните в суть новых технологий и делитесь опытом с остальными членами сообщества, а также попробуйте свои силы в Global DevOps-хакатоне.

Ведущие эксперты по DevOps станут кураторами вашей команды и помогут в разработке проектов.

Мероприятие откроет Донован Браун (Donovan Brown) — Principal DevOps Program Manager в Microsoft – всемирно известный специалист по DevOps.

В жюри: Microsoft, Yandex, Сбербанк Технологии, Лаборатория Касперского, ABBYY

Программа:


09.30 – 10.00 – Приветственный кофе
10.00 – 10.15 – Вступительное слово от организаторов – сообщества MVP в России. Владимир Гусаров, MVP
10.15 – 10.30 – «Что такое DevOps?» — приветственное слово Donovan Brown, Principal DevOps Program Manager (Microsoft)
10:30 – 11:15 Пленарный доклад. От серверного к бессерверному – следующий шаг в облачных вычислениях. Владимир Гусаров, MVP
11.15 – 11.30 – Кофе-брейк
11.30 – 11.45 – Презентация целей и задач хакатона (эволюция архитектуры существующего приложения в контейнерную и далее в бессерверную с помощью практик DevOps).
MVP Community, менторы команд
11.45 – 13.00 – Хакатон
13.00 – 13.45 – Обед
13.45 – 16.00 – Хакатон
16-00 – 17-00 – Подведение результатов хакатона. Церемония награждения победителей и вручение призов.

Регистрация и дополнительная информация доступна по ссылке.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330226/


Метки:  

Android-митап в офисе Badoo 17 июня

Вторник, 06 Июня 2017 г. 17:45 + в цитатник


Привет! 17 июня в нашем офисе пройдет первый (для нас) Android-митап. С докладами будут выступать разработчики из Avito, Яндекса, Одноклассников, из Badoo – я, Аркадий Гамза. Начало – в 12:00. Описание докладов – под катом.


Программа митапа


11:00 – Начало регистрации (приходите, чтобы успеть выпить кофе и занять лучшие места)


12:00 – 12:40 – Филипп Уваров, Avito
12:40 – 12:55 – Вопросы


12:55 – 13:05 – Перерыв (вы успеете выпить по чашке кофе и задать еще пару вопросов спикеру)


13:10 – 13:50 – Аркадий Гамза, Badoo
13:50 – 14:05 – Вопросы


14:05 – 14:40 – Перерыв (обед)


14:40 – 15:20 – Андрей Сидоров, Яндекс.Браузер
15:20 – 15:35 – Вопросы


15:40 – 16:20 – Григорий Джанелидзе, OK.RU
16:20 – 16:35 – Вопросы


16:35 – 17:35 – Свободное общение


Спикеры и темы выступлений


Филипп Уваров, Avito



Тема: Компонентные тесты: как сделать жизнь вашего QA немного проще?


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


В частности поговорим о том:


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

Аркадий Гамза, Badoo



Тема: Android Studio умеет больше, чем вы думаете


Мы обсудим полезные функции Android Studio – основного инструмента каждого Android-разработчика.


Я буду говорить:


  • об эффективной навигации;
  • о нетривиальном поиске;
  • о режимах отображения;
  • о средствах отладки.

Андрей Сидоров, Яндекс.Браузер



Тема: Измерение энергопотребления мобильных и внедрение в Continuous Integration.


Во время выступления я буду говорить про:


  • проектирование устройства измерения энергопотребления;
  • применение устройства анализа энергопотребления смартфона;
  • автоматизацию процесса тестирования энергопотребления;
  • поиск энергозатратных функций браузера;
  • оптимизацию и контроль потребления энергии в браузере.

Григорий Джанелидзе, OK.RU



Тема: Как перестать беспокоиться и начать запускать фичи


Запуск новых фич для любого продукта – довольно опасная штука, ведь столько всего может пойти не так: может вылезти огромное число разных багов (от device specific до багов в самой фиче), могут не выдержать сервера и в конце концов пользователям может просто не понравиться фича.


Я расскажу о том, как мы запускаем новые фичи, какие проблемы, связанные с запусками, у нас возникали и как это всё работает в Android-клиенте.


Тезисы:


  • feature toggles: что это, зачем это и как мы сделали своё;
  • как мы мониторим и оцениваем запуски;
  • как feature toggles дружат с ручным тестированием и как учитываются в автотестах.

Регистрация и место


Регистрироваться на митап – здесь (пишите ваши фамилии и имена кириллицей, пожалуйста).


Адрес: Москва, Цветной бульвар, 2, БЦ «Легенда Цветного», подъезд А. Метро: Трубная/Цветной бульвар. Захватите с собой какой-нибудь удостоверяющий личность документ.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330328/


Метки:  

«Сломай голосовалку на РИТ++». Даёшь 1 000 000 RPS

Вторник, 06 Июня 2017 г. 17:13 + в цитатник


Прошёл второй день РИТ++, и по горячим следам мы хотим рассказать о том, как всем миром пытались сломать нашу голосовалку. Под катом — код, метрики, имена победителей и самых активных участников, и прочие грязные подробности.


Незадолго перед РИТ++ мы задумались, чем можно развлечь народ? Решили сделать голосовалку за самый крутой язык программирования. И чтобы результаты в реальном времени выводились на дашборд. Процедуру голосования сделали простой: можно было с любого устройства зайти на сайт ODN.PW, указать своё имя и e-mail, и проголосовать за какой-нибудь язык. Со списком языков не мудрили — взяли девять самых популярных по данным GitHub, десятым пунктом сделали язык “Other”. Цвета для плашек тоже взяли с GitHub.



Но мы понимали, что накрутки будут неизбежны, причём с применением «тяжёлой артиллерии» — все свои, аудитория продвинутая, это же не голосование на мамочкином форуме. Поэтому мы решили приветствовать накрутки всеми возможными способами. Более того, предложили попробовать сообществу положить нашу голосовалку большой нагрузкой. А чтобы участникам было ещё проще, выложили ссылку на API для накруток с помощью ботов. И заодно решили наградить поощрительными призами первых трёх участников с наибольшим количеством RPS. Отдельная номинация была заготовлена для того силача, который сможет поломать голосовалку в одиночку.


День первый


Голосовалку запустили почти с самого начала работы РИТ++, и работала она до 18 часов. Наше развлечение понравилось посетителям и докладчикам РИТ++. Специалисты по высокопроизводительным сервисам активно включились в гонку за RPS. Гости стенда живо обсуждали способы положить голосовалку. Стихийно возникали команды адептов того или иного языка, которые начинали придумывать стратегии продвижения. Кто-то тут же садился и начинал писать микросервисы или ботов для участия в голосовании.



Некоторые компании, участвующие в РИТ++ и предоставляющие услуги защищённых хостингов, тоже включились в наше соревнование. К самому концу дня совместными усилиями участники всё же смогли ненадолго положить систему. Ну как «положили» — сервис-то работал, просто мы упёрлись в потолок по количеству одновременно регистрируемых голосов. Поэтому к 18 часам мы приостановили голосование, иначе результаты были бы недостоверными.


По результатам первого дня мы получили 160 млн голосов, а пиковая нагрузка достигала 20 000 RPS. Любопытно, что в этот день первое и второе места заняли активный участник РИТ++
Николай Мациевский (Айри) и спикер Елена Граховац из Openprovider.


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


День второй


Многих заинтересовало наше предложение положить голосовалку, ведь гонка за RPS — задача увлекательная. Утром нас уже «ждали»: едва мы переключили DNS, как количество RPS взлетело до 100 000. И через полчаса нагрузка поднялась до 300 000 RPS.


Забавно, что когда мы только приступали к разработке голосовалки, то решили, что «неплохо было бы поддерживать 100 000 RPS». И на всякий случай заложили максимальную производительность в 1 млн RPS, но при этом даже всерьёз не рассматривали возможность приближения к такому показателю. А к середине второго дня уже практически делали ставки на то, пробьём ли потолок в миллион запросов в секунду. В результате мы достигли порядка 500 000 RPS.


Реализация


Проект мы запилили втроём за 1,5 дня, перед самым РИТ++. Голосовалку разместили в облачном сервисе Google Cloud Platform. Архитектура трёхуровневая:


• Верхний уровень: балансировщик, выступающий в роли фронтенда, на который приходит поток запросов. Он раскидывает нагрузку по серверам.
• Средний уровень: бэкенд на Node.js 8.0. Количество задействованных машин масштабируется в зависимости от текущей нагрузки. Делается это экономно, а не с запасом, чтобы не переплачивать впустую. К слову, проектик обошёлся в 8000 рублей.
• Нижний уровень: кластеризованная MongoDB для хранения голосов, состоящая из трёх серверов (один master и два slave’а).


Все компоненты голосовалки — open source, доступны на Github:


• Backend: https://github.com/spukst3r/counter-store
• Frontend: https://github.com/weglov/treechart


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


Что ж, как показал первый день, прикрутить кеш надо было сразу. Каждый воркер Node.js выдавал не больше 3000 RPS на каждый POST на /poll, а мастер MongoDB тяжело кашлял с LA >100. Не очень помогла даже оптимизация агрегации запросов для получения статистики путём изменения read preference на использование slave'ов для чтения. Ну ничего, самое время реализовать кеш для накрутки счётчиков и для проверки валидности email'а (который был завёрнут в простой _.memoize, ведь мы никогда не удаляем пользователей). Также мы задействовали новый проект в Google Compute Engine, с бОльшими квотами.


После включения кеширования голосов MongoDB чувствовала себя превосходно, показывая LA <1 даже в пике загрузки. А производительность каждого воркера выросла на 50% — до 4500 RPS. Для периодической отправки данных мы использовали bulkWrite с отключённым параметром ordered, чтобы оставить на стороне базы очередность исполнения запросов для оптимизации скорости.


В первый день на каждом воркере работал Node.js-сервер, создающий через модуль cluster четыре дочерних процесса, каждый из которых слушал порт 3000. Для второго дня мы отказались от такого сервера и отдали обработку HTTP «профессионалам». Опыты показали, что nginx, взаимодействующий с приложением через unix-сокет, даёт примерно +500 RPS. Настройка достаточно стандартная для большого количества соединений: увеличенный worker_rlimit_nofile, достаточный worker_connections, включенный tcp_nopush и tcp_nodelay. Кстати, отключение алгоритма Нейгла помогло поднять RPS и в Node.js. В каждой виртуалке потребовалось увеличить лимит на количество открытых файлов и максимальный размер backlog'а.


Итоги


За два дня ни одному участнику в одиночку не удалось положить наш сервис. Но в конце первого дня общими усилиями добились того, что система не успевала регистрировать все входящие запросы. На второй день мы поставили рекорд в нагрузке ~450 000 RPS. Различие в показаниях RPS на фронте (который высчитывал и усреднял RPS по фактическим записям в базе) и показания мониторинга Google пока остаётся для нас тайной.



И рады объявить победителей нашего маленького соревнования:



1 место — { "_id": "ivan@buymov.ru", "count": 2107126721 }
2 место — { "_id": "burik666@gmail.com", "count": 1453014107 }
3 место — { "_id": "256@flant.com", "count": 626160912 }


Для получения призов пишите kosheleva_ingram_micro!

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330368/


Первыми закрываются компании где ставится много задач. Статистика использования системы управления проектами YouGile

Вторник, 06 Июня 2017 г. 16:49 + в цитатник
Что самое важное в организации команды? Может построить планы?

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

Что делают успешные команды и чего не делают разваливающиеся за неделю? Можно ответить на глупые вопросы: что важнее — назначить на каждую задачу исполнителя или проставлять дедлайны, а может самое важное ставить приоритеты? Есть ли действие, которое значительно увеличивает срок жизни проекта?



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

Эксперимент


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

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

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

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

Но две группы дали принципиальные отличия от среднего.

Результаты


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


Компании, которые генерируют много задач (более 20 в день на человека в первую неделю), через 100 дней будут существовать только с вероятностью 4%.

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

Самый яркий положительный паттерн — это большое количество общения, вопросов.


Компании, которые в первые же дни набирают больше 10 сообщений на участника команды, через 100 дней выживают в системе с вероятностью 42%.

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

Вобщем — задать вопрос в десять раз лучше, чем поставить задачу.

Разворот в приоритетах разработки


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

В отличие от белой доски, система управления должна засасывать, как засасывает Facebook. Каждый день просматривать задачи по проекту, вовремя задавать вопросы, общаться — всё это должно быть нормой для всей команды. В идеальном мире такая система должна позволять организовать 100 человек с такой же легкостью, как стартап из 5.

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

Получилось интересно, нам и нескольким близким компаниям из числа тестирующих нравится. Все общение окончательно перешло в систему и стало идеально структурировано по задачам.

Вот так выглядит список всех проектов. При клике на какой-то конкретный открывается доска и можно просмотреть все задачи.


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


Третья кнопка в нижнем меню открывает список участников всей компании и позволяет вести личную переписку. Никто кроме вас и собеседника не имеет к ней доступ.


От запуска мобильной версии ждем роста показателя возвратов на 10%, на практике это означает, что компании будут на 10% дольше упираться, прежде чем бросить проект. Может кто-то и потратит больше времени впустую, работая над заведомо мертвой идеей, но наша задача сделать так, чтобы при этом вся команда была вовлечена в процесс.

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

Сайт системы — yougile.com
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329752/


Метки:  

Видео: инди-разработчики о провалах, успехе и монетизации

Вторник, 06 Июня 2017 г. 16:44 + в цитатник
В мае в Москве состоялась конференция DevGAMM — одно из крупнейших русскоязычных мероприятий в области разработки игр. Мы поймали инди-девелоперов c абсолютно разным опытом в индустрии — и задали несколько важных вопросов о монетизациях, сложностях и историях создания их проектов.


Студия One Dream из Ярославля в мае этого года получила грант в $20 000 от Epic Games. Ведущий разработчик Михаил Ваксман рассказал, как команде удалось создать свою Zelda — Be:Brave — с блэкджеком и переходом с Unity 3D на Unreal Engine после запуска игры.





Молодой разработчик Юра Саначев сделал простую, но стильную аркаду Hop — и успешно монетизирует ее.





Михаил Фарленков, cоздатель VR-шутера Hardcode от третьего лица: есть ли у таких игр будущее и зачем вообще нужен подобный VR? Ответы — в видео.





И на десерт — классные инсайты от Виталия Козлова, создателя детских игр по мотивам популярных мультфильмов (KB Production).




Совсем скоро мы опубликуем видео с экспертами по видеоблогам, аналитике приложений, художникам для игр и геймдизайну — оставайтесь на связи!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330354/


По дороге с облаками. Реляционные базы данных в новом технологическом контексте

Вторник, 06 Июня 2017 г. 16:40 + в цитатник
Привет, Хабр!

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

Об авторе:

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

Автор имеет сертификаты Microsoft в области создания приложений в среде Microsoft Azure: Microsoft Certified Professional и Microsoft Specialist: Developing Microsoft Azure Solutions.
В 2008 году закончил Белорусский Государственный Университет Информатики и Радиоэлектроники (БГУИР) по специальности “Моделирование и компьютерное проектирование радиоэлектронных средств”.
С 2007 по 2012-й годы автор работает в научно-исследовательском институте ядерных проблем БГУ на должностях техника, лаборанта, инженера.
С 2013 года по настоящее время автор работает в компании ISSoft Solutions на должности разработчика ПО и DevOps с специализацией в области создания облачных приложений на базе стека Microsoft

Под катом вы сможете оценить идеи и стиль автора. Не стесняйтесь голосовать и комментировать — и добро пожаловать под кат!


Введение или почему эту статью следовало написать.

В настоящее время облачные сервисы позволяют разработчикам и системным администраторам очень быстро создавать инфраструктуру приложения и так же быстро от нее избавляться, когда в этом отпадает необходимость. Плата взимается за время использования ресурсов облака и за их уровень производительности, именуемый еще «ценовой уровень» – pricing tier. Можно очень быстро создать ресурсы, «поиграться» с ними, «пощупать», освоить их, и при этом совершенно не нужно заботиться о покупке/администрировании серверов, чтении документации об инсталляции требуемого софта и пр. В облачных средах все типовые задачи администрирования и мониторинга сведены в удобные API или пользовательский интерфейс веб-портала управления. Но тут появляется одна сложность – если человек не разбирается или не до конца понимает, как работают облачные среды, задача «что мне надо сделать, чтобы получить базу данных и подключиться к ней из моего приложения» на первых порах озадачивает. Обилие облачных сервисов и различных «ценовых уровней» для каждого сервиса еще больше осложняет задачу выбора. Эта статья представляет краткий обзор одного из самых популярных облачных сервисов – сервисов реляционных баз данных.

Реляционные базы данных являются традиционным хранилищем данных. Информацию в них можно представить в виде набора таблиц, состоящих из строк. Эти таблицы связаны друг с другом с помощью «ключей» — специальных ограничений целостности, ставивящих строкам одной таблицы в соответствие строки другой. «Большие данные» зачастую удобнее хранить и быстрее обрабатывать в нереляционном виде (например, в базах данных типа ключ/значение), но данные, хранящиеся в виде взаимосвязанных таблиц, допускают эффективный анализ в любом измерении – по строкам связанных таблиц и по всей таблице, что для случая NoSQL баз данных сопряжено с большими трудностями. Кроме того, для реляционных баз данных имеется очень эффективный язык запросов – SQL. В облачных средах реляционные базы данных представлены в двух видах – SQL as a Service и в виде готовых образов для виртуальных машин. Базы данных, размещаемые на виртуальных машинах, по сути, мало отличаются от серверов баз данных, размещенных на традиционных виртуальных и физических хостах. При этом выбор типа виртуальной машины, виртуальных дисков, облачного хранилища для их размещения и сетевых интерфейсов существенно влияют на ее производительнсть, но это тема отдельной главы, а возможно и книги. У серверов баз данных, размещенных на виртуальных машинах в облаках, есть существенные ограничения, связанные с масштабированием, доступностью и отказоустойчивостью. Например, виртуальные машины Azure имеют SLA (service level agreement – соглашение об уровне доступности) на уровне 99,95% только в случае использовании кластера минимум из двух машин, размещенных в одной общей группе доступности (Availability Set), при этом у них будут физически разделены сетевые интерфейсы и источники питания. Для того, чтобы достичь уровня 99,99 необходимо конфигурировать кластер из нескольких виртуальных машин Always On.

В то же время SQL обладает SLA на уровне 99.99 без дополнительных трудностей, связанных с конфигурированием кластеров. С другой стороны, требованиям стандартов HIPPA соответствуют SQL-сервера, размещенные на виртуальных машинах, но не сервис Azure SQL. В остальном же облачный сервиc SQL имеет непревзойденные возможности в плане масштабирования, доступности и простоте администрирования (репликация, резервное копирование, экспорт, анализ производительности выполняемых запросов). Кроме того, SQL as a Service в ряде случаев существенно дешевле аналогичного по производительности сервера, размещаемого на виртуальной машине (автор сознает, что это очень спорное утверждение, особенно учитывая особенности использования ресурсов в SQL as a Service и SQL на виртуальных машинах). SQL as a Service, не поддерживает всех возможностей традиционных серверов баз данных. Например, выполнение запросов из таблиц в одной базе данных внутри другой в случае SQL сервиса сопряжено с рядом трудностей и ограничений. Рассмотрим примеры реализации SQL as a Service в разных облачных средах.

Служба реляционной базы данных Azure SQL от Microsoft.

Реализация SQL-As-A-Service от Microsoft представляет собой облачную службу реляционной базы данных на основе движка Microsoft SQL Server и называется Azure SQL. В языке запросов Azure SQL реализовано подмножество функций T-SQL. Экземпляры сервисов Azure SQL, являющиеся прямыми аналогами баз данных MS-SQL, логически группируются в «серверы» Azure SQL Server. Каждый сервер Azure SQL должен иметь уникальный URL, учетные данные (имя пользователя и пароль), а также набор допустимых IP адресов, которые могут иметь доступ к нему (этот список формируется в firewall сервера и регулирует правила доступа к нему).

Физически Azure SQL Server размещается в ЦОД–е, расположенном в определенном географическом регионе. В этом же регионе размещаются все экземпляры баз данных Azure SQL. Возможна также географическая репликация баз данных в несколько регионов по схеме Primary-Secondary или Primary-ReadOnly Replica (первичный сервер – реплика, доступная только для чтения). Благодаря широкой поддержке T-SQL в Azure SQL имеется возможность прямой миграции баз данных из Microsoft SQL Server в Azure SQL. Конечно, прямая миграция из одного типа базы данных в другую – далеко не простая и не быстрая задача, но в данном случае это принципиально возможно и напрямую поддерживается с помощью специальных программ от Microsoft, Red Gate и пр. Однако следует иметь в виду, что это программное обеспечение в ряде случаев просто «вырезает» несовместимые объекты базы данных, не пытаясь их адаптировать. И может получиться, что после такой миграции база данных «поднялась», но счастливые разработчики могут «внезапно» недосчитаться ряда объектов базы данных в Azure SQL. Каждый экземпляр баз данных имеет определенный «ценовой уровень» — pricing tier — который характеризуется своей производительностью, ограничениями по размеру, количеству точек восстановления и возможностями репликации. Все возможные ценовые уровни разделены на следующие уровни: базовые (“Basic”), стандартные (“Standard”) и премиум (“Premium”). Самое главное различие ценовых уровней проявляется в разном значении DTU – обобщенного параметра, характеризующего производительность базы данных. Что же это за параметр? DTU (eDTU) это обобщенная характеристика производительности базы данных, включающая в себя показатели производительности центрального процессора, памяти, устройств ввода-вывода и сетевого интерфейса. Этот показатель определяет своего рода «объем», который может «занимать» производительность Azure SQL. Если в данный момент в базе выполняется запрос, то этот запрос потребляет определенное количество ресурсов, которые занимают часть этого разрешенного объема (см рисунок 1). При этом следует иметь в виду, что ограничивается не только объем, но и конкретные значения каждого из показателей (т.е. не получится «обменять» крайне малое использование CPU на крайне большое значение памяти). Это проявляется в частности в том, что один «кривой» запрос может вызвать переиспользование одного из ресурсов и в итоге одвесить всю базу данных (экземпляр сервиса Azure SQL Database но не Azure SQL Server) и точно такой же запрос будет нормально отрабатывать в традиционной базе данных Microsoft SQL Server. Это происходит потому, то в Azure SQL срабатывает механизм защиты ресурсов базы от чрезмерного использования, который вынуждает процесс, вызвавший запрос, отключиться по таймауту, освободив тем самым ресурсы базы данных.



Итак, Azure SQL состоят из экземпляров Azure SQL Database, являющихся собственно реляционными хранилищами информации с определенными значениями размера и максимального DTU; экземпляра Azure SQL Server, который группирует базы Azure SQL Database, обеспечивая им общую строку соединения (connection string), правила доступа, прописанные в firewall и в ряде случаев предоставляя общий эластичный пул ресурсов (Elastic Database Pool, о котором– ниже).

Теперь познакомимся с Elastic Database Pool. Этот сервис встроен в состав Azure SQL Server и служит для объединения баз данных в один пул и назначения всем им общих разделяемых ресурсов. Зачем это нужно? Рассмотрим пример SaaS приложения, созданного для оказания неких услуг зарегистрированным в нем пользователям (например, это «облачная» CRM система). Каждому зарегистрированному пользователю такой системы выделяется своя база данных определенного уровня производительности, выражающегося конкретным значением DTU. Каждый уровень производительности имеет определенную месячную стоимость, которая в конечном итоге скажется на прибыли владельца SaaS – она будет равна суммарной месячной плате всех пользователей за вычетом расходов на облачные сервисы, лежащие в основе архитектуры системы. Теперь предположим, что активность пользователей, выражающаяся в использовании DTU каждой базы, носит некореллированный характер, т.е. они нагружают свои базы в различные случайные временные промежутки. Это приводит к тому, что появляются моменты времени, когда использование DTU базы конкретного пользователя очень мало, и моменты, когда оно велико. Таким образом, в момент малого использования DTU базы «простаивают» — но за них взимается плата со стороны Azure. А что если взять несколько таких баз данных, что интервалы активности каждой совпадают с интервалами недогруженности других, и объединить их в общий пул баз данных и распределить общие ресурсы DTU между базами таким образом, чтобы суммарная нагрузка была равномерна во времени; плата за ценовой уровень при этом будет существенно меньше, чем суммарная плата за все базы данных. Именна такая идея лежит в основе сервиса Azure Elastic Database Pool. Кроме того, ElasticDatabasePool позволяет реализовывать сценарии разделения одной большой базы данных на меньшие, но выполнять запросы в этой разделенной на «фрагменты» (shard) БД так, как будто это одна монолитная база данных.

Рассмотрим теперь случай, когда все же необходимо выполнить запрос к данным, расположенным в разных базах данных. Если имеется просто набор баз данных без фрагментирования, необходимо выбрать одну головную базу данных и создать в ней внешние источники данных и внешние таблицы (reference table), являющиеся «отражениями» реальных таблиц, размещенных в других базах данных. Можно также не использовать специализированную головную базу данных, а создавать таблицы в каждом экземпляре Azure SQL Database. Недостаток такого подхода в том, что при смене схем таблиц в базах данных, необходимо синхронно менять схемы во внешних таблицах (если отсутствует головная база данных, то необходимо проделать очень большую работу по смене схемы во всех внешних таблицах во всех базах, где они присутствуют). Кроме того, у реализации T-SQL в Azure SQL есть ограничения на типы данных для внешних таблиц (например, они не поддерживают Foreign Key и тип nvatrchar(max)) и в настоящее время присутствует целый ряд ограничений на выполнение подобных запросов и базы данных, где эти запросы будут выполняться – например невозможно выполнить экспорт базы данных в BACPAC файл в случае наличия в ней ссылок на внешние таблицы. Ну и не следует забывать и об снижении производительности для таких запросов. А как же это все выглядит?

Давайте для определенности предположим, что у нас две базы данных – база First и база Second. Теперь допустим, что из базы Second нам нужно выполнить запрос к базе First. Для этого в базе Second должны быть созданы учетные данные (credentials), которые будут служить для доступа к базе данных First:

CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<пар0ль>'; 
 CREATE DATABASE SCOPED CREDENTIAL FirstDBQueryCred   -- Это имя учетной записи
 WITH IDENTITY = '<ИмяПользователя>', 
 SECRET = '<пар0ль>';


Затем в базе данных Second создадим внешний источник данных, который будет использоваться для связи с таблицами внешней базы данных:

CREATE EXTERNAL DATA SOURCE FirstDatabaseDataSource WITH 
(
    TYPE = RDBMS, 
    LOCATION = '.database.windows.net', 
    DATABASE_NAME = 'First', 
    CREDENTIAL = FirstDBQueryCred
) 


После этого в базе Second надо создать «внешнюю таблицу» (External Table) – таблицу, являющуюся «отражением» аналогичной таблицы, размещенной в базе First:

CREATE EXTERNAL TABLE [dbo].[TableFromFirstDatabase] 
( [KeyFieldID] [int] NOT NULL, 
  [DataField] [varchar](50) NOT NULL
)
WITH ( DATA_SOURCE = FirstDatabaseDataSource)


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

Другой возможный случай выполнения запросов к различным базам данных – это использование Elastic Database jobs. Суть этой технологии в том, что группа баз данных объединяется и управляется централизованно из общего специализированного головного сервера ВМ. Взаимодействуя с этим сервером программно или через Azure Portal, можно управлять всеми подключенными базами данных с помощью создания заданий (jobs). Эти задания могут быть следующего характера:

  • административные (согласованное изменение схемы, выполнение перекомпиляции индексов);
  • периодическое обновление данных или сбор данных для систем BI, в т.ч. для выполнения анализа большого количеств данных.


Сервис Elastic Database jobs содержит следующие компоненты (рисунок 2):



  • головной сервер, размещаемый на экземпляре Azure Cloud Service Worker Role. По сути, это специализированное ПО, размещаемое (по состоянию на настоящее время) на виртуальной маший Azure Cloud Service. Для обеспечения высокой доступности, рекомендуется создавать минимум 2 экземпляра ВМ;
  • управляющая база данных. Это экземпляр Azure SQL, служащий для хранения метаданных всех подключенных баз данных;
  • экземпляр службы Azure Service Bus, служащий для объединения и синхронизации всех компонентов;
  • экземпляр облачного хранилища Azure Storage Account, служащий для хранения журналов всей системы.


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

Помимо одиночных баз данных, сервис AzureSQL позволяет создавать более сложные реляционные хранилища – фрагментированные базы данных – Sharded Databases и реляционные хранилища с широкой поддержкой массивно-параллельного выполнения запросов – Azure SQL DWH.

Рассмотрим сперва фрагментированные базы данных. Нужда во фрагментации базы данных появляется в случае, когда ее размер становится чрезмерно большим для размещения на одном экземпляре Azure SQL (в настоящее время это более 1 ТБ для Premium pricing tier). Конечно, можно разбить большую базу данных на меньшие базы логически, проведя анализ ее структуры (схемы). Как уже указывалось ранее, Azure SQL Server это логическая группировка экземпляров Azure SQL Database, а не физическое объединение на одном сервере. И прямые запросы к объектам базы данных из другой базы данных возможны только если эти объекты являются External table или эти базы объединены в Elastic Database Pool, и используются запросы Elastic Database Query или транзакции Elastic Transactions. В этом случае необходимо применить фрагментацию (sharding) базы данных. Фрагментация базы данных — это по сути горизонтальное масштабирование, отличное от вертикального масштабирования – увеличения «размера» базы данных в масштабе CPU, оперативной памяти, IOPs и пр. Разделение одного большого хранилища на несколько хранилищ меньшего масштаба и параллельная обработка в их всех с последующим сложением результатов обработки – ключевая концепция всех технологий обработки больших данных, с которой мы будем далее не раз встречаться.
Актуальность книги

Никто ещё не голосовал. Воздержался 1 человек.

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

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330364/


Метки:  

[Перевод] Понимание событийной архитектуры Node.js

Вторник, 06 Июня 2017 г. 16:38 + в цитатник

Метки:  

Катаем «смоляной шарик» или создание собственных правил сборки с помощью Qbs

Вторник, 06 Июня 2017 г. 16:37 + в цитатник
Qbs (Qt Build System) — система сборки, позволяющая описывать процесс сборки проектов на простом языке QML (javascript-подобный декларативный язык), ускоряющий процесс сборки продуктов за счет построения подробного графа зависимостей. Хоть эта система и создана разработчиками Qt, но она жестко не привязана к Qt и позволяет собирать любые продукты, для любых языков программирования и даже использоваться не для программирования, а например для администрирования. Как заявлено в официальной документации:
A product is the target of a build process, typically an application, library or maybe a tar ball

Сегодня и рассмотрим процесс создания своих продуктов. Поехали…

Знакомство с это системой сборки хорошо описал mapron в данной статье, мы же не будем на этом останавливаться и приступим сразу к делу.

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

Итак Qbs выполняет преобразования одних данных в другие с помощью элемента Rule. Данный элемент создает правило преобразования, которое преобразует входные данные inputs в выходные outputs при помощи набора команд, созданных в скрипте prepare. Каждая команда может как сама выполнять преобразования, так и делегировать эту работу внешней программе.

Входные артефакты


В качестве входных артефактов для правила преобразования выступают файлы собираемого продукта с тегом указанным в свойстве inputs, а также артефакты полученные из зависимостей собираемого продукта с тегом указанным в свойстве inputsFromDependencies (неявным является тег "installable", который присваивается всем файлам которые необходимо проинсталлировать, т.е. qbs.install: true).

Например:

---product1.qbs---
Application {
    name: "simpleApplication";
    targetName: "appSimple"
    files: ["main.cpp", "app.h", "app.cpp"]
    Depends {name: "cpp"}
}

---product2.qbs---
Product {
    type: "exampleArtefact"
    name: "example"
    targetName: "myArtefact"
    Depends {name: "simpleApplication" }
    Depends {name: "exampleModule" }
    Group {
        files: ["description.txt", "readme.txt"]
        fileTags: ["txtFiles"]
    }
    Group {
        files: ["imgA.png", "imgB.png", "imgC.png"]
        fileTags: ["pngFiles"]
    }
    Group {
        files: ["fontA.ttf", "fontB.ttf"]
        fileTags: ["fontFiles"]
    }
}

---exampleModule.qbs---
Module {        
    Rule {
        inputs: ["pngFiles", "fontFiles"]
        inputsFromDependencies: ["application"]
        Artifact {
            filePath: product.targetName + ".out"
            fileTags: ["exampleArtefact"]
        }
        ...
    }
    ...
}

В данном примере у нас есть 2 продукта и 1 модуль:

  1. Продукт с названием simpleApplication имеющий тип application (элемент Application по сути является Product {type: «application»}) содержащая 3 файла: main.cpp, app.h, app.cpp. Этот продукт зависит от модуля cpp, что указывает на то, что будет выполняться компиляция этого продукта компилятором C++ и на выходе получится артефакт помеченный тегом «application» и названием указанным в свойстве targetName, т.е. appSimple.exe (для windows или appSimple для unix платформ).

  2. Продукт с названием example имеющий тип exampleArtefact содержащий 7 файлов помеченных тремя тегами. Этот продукт зависит от продукта simpleApplication, что указывает на то, что он будет обрабатываться после создания продукта simpleApplication. А также от модуля exampleModule, что указывает на то, что для создания данного продукта будут браться правила преобразования и свойства из этого модуля. И на выходе ожидается артефакт с названием myArtefact типа (с тегом) exampleArtefact.

  3. Модуль exampleModule содержит правило преобразования файлов с тегами pngFiles и fontFiles, а также артефактов имеющих тег application, которые берутся из зависимостей собираемого продукта.

При сборке продукта будет определен список модулей от которых зависит продукт и сами модули. В них будет осуществлен поиск правил преобразования файлов помеченных входными тегами в выходные артефакты, которые соответствуют типу собираемого продукта. Сначала собирается продукт simpleApplication, т.к. он имеет зависимость только от модуля cpp. В нем ищутся правила преобразования файлов продукта в тип application. В модуле cpp есть элементы FileTagger которые по шаблону задают для файлов продукта теги. Преобразование входных файлов в выходной(ые) может быть выполнено как сразу, так и по цепочке преобразований файлов одного типа в другой, а затем в итоговый. На выходе обработки продукта simpleApplication, мы получим приложение appSimple имеющее тип (тег) application.

Затем начнется сборка продукта example. Для его файлов будет искаться правило, на выходе дающее артефакты типа exampleArtefact. Это правило требует для входа файлы типа (с тегом) pngFiles, fontFiles и application. При этом файлы типа application ищутся только в продуктах от которых зависит собираемый продукт. Так как продукт example уже содержит такие файлы, то на вход правила поступают файлы: imgA.png, imgB.png, imgC.png, fontA.ttf, fontB.ttf и appSimple.exe. А на выходе получим файл myArtefact.out типа exampleArtefact, который и будет являться нашим конечным продуктом.

Выходные артефакты


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

Artifact {
    filePath: input.fileName + ".out"
    fileTags: ["txt_output"]
}

Этот элемент описывает, какой артефакт получается на выходе правила. Через свойство filePath — указывается имя выходного файла. Если указывать относительный путь, то Qbs будет создавать этот артефакт относительно каталога сборки текущего собираемого продукта. Через свойство fileTags указывается список тегов, которые будет иметь артефакт после его создания. Это необходимо, для того чтобы другие правила сборки могли использовать выходные артефакты данного правила, как свои входные артефакты. Также если продукт будет иметь этот же тег в качестве своего типа, то эти артефакты будут являться результатом сборки этого продукта.

У каждого правила должен быть хоть один выходной тег, иначе правило работать не будет. Если артефактов несколько, то можно описать несколько элементов Artifact либо можно воспользоваться свойствами outputArtifacts и outputFileTags для элемента Rule.

Свойство outputArtifacts описывает список JavaScript объектов имеющих свойства, как у элемента Artifact. Используется это свойство для случаев, когда набор выходов не фиксирован, а зависит от содержания входных данных. Например:

outputArtifacts: [{
    var artifactNames = inputs["pngFiles"].map(function(file){
        return "pictures/"+file.fileName;
    });
    artifactNames = artifactNames.concat(inputs["fontFiles"].map(function(file){
        return "fonts/"+file.fileName;
    }));
    artifactNames = artifactNames.concat(inputs["application"].map(function(file){
        return "app/"+file.fileName;
    }));
    var artifacts = artifactNames.map(function(art){
        var a = {
            filePath: art,
            fileTags: ["exampleArtefact"]
        }
        return a;
    });
    return artifacts;
}]

В данном примере показано, что для входных файлов с тегом pngFiles, правило подготовит выходной артефакт с таким же названием и поместит его в папку pictures. Для тегов fontFiles и application, также поместив их соответственно в папки fonts и app. При этом т.к. пути будут относительные, то эти папки создадутся в папке сборки продукта.

Если мы решили использовать свойство outputArtifacts, то необходимо указать и свойство outputFileTags, которое является списком выходных тегов, которые правило потенциально производит. Для нашего примера:

outputFileTags:
 ["exampleArtefact"]

Все полученные при сборке продукта артефакты, помеченные выходным тегом совпадающим с типом продукта, при установке продукта, будут скопированы из каталога сборки в каталог установки.

Правило преобразования


Когда определены входные и выходные артефакты, необходимо подготовить саму последовательность команд для выполнения преобразования. Для этого используется свойство prepare элемента Rule. Это свойство является JavaScript сценарием, который возвращает список команд для преобразования входов в выходы. Код в этом скрипте рассматривается как функция с сигнатурой function(project, product, inputs, outputs, input, output).
Параметры input и output не определены (undefined), если для этого правила имеется несколько артефактов ввода (и вывода соответственно). Служат они как синтаксический сахар: input = inputs[0] и output = outputs[0] и являются списками с одним элементом. Параметры project и product, являются JavaScript объектами, через которые доступны свойства текущего проекта и продукта соответственно. Особый интерес вызывают объекты inputs и outputs. Рассмотрим их более подробно.

Объекты inputs и outputs


Параметры inputs и outputs являются объектами JavaScript, ключи свойств которых являются файловыми тегами, а значениями свойств — являются списки объектов, представляющих артефакты, соответствующие этим тегам. В нашем примере переменная inputs имеет 3 ключа: pngFiles, fontFiles, application. А каждый входной артефакт доступен через inputs[«pngFiles»] (или inputs.pngFiles что равнозначно). Каждый артефакт в этом списке имеет следующие свойства:

  • baseName — базовое имя файла (например для файла c:\123\test.plugin.dll это будет test)
  • completeBaseName — название файла без расширения (например для файла c:\123\test.plugin.dll это будет test.plugin)
  • fileName — название файла (например для файла c:\123\test.plugin.dll это будет test.plugin.dll)
  • filePath — полный путь до файла с его полным именем
  • fileTags — список тегов присвоенных артефакту

Помимо этого артефакты содержат в себе все свойства для каждого модуля, который используется в продукте. Эта особенность может использоваться для доступа к свойствам модуля. Например, свойство inputs.application[0].cpp.defines вернет для артефакта simpleApplication список определений, который будет передан при компиляции соответствующего файла. Это очень удобный и важный момент, позволяющий артефактам задать через свойства какого-нибудь модуля свои значения и группировать такие артефакты или обрабатывать их как-то по особенному.

* Было подмечено на Qbs версии 1.7.2, что если продукт подменяет свойства модуля в котором находится правило сборки, то эти свойства недоступны в артефакте. По этому эти свойства я выносил в отдельный модуль.

* Также inputs.application[0].cpp.defines не всегда срабатывает, по этому я использую функцию inputs.application[0].moduleProperty(«cpp», «defines»). Если эту функцию применять к входному артефакту, то будут возвращаться свойства которые использует артефакт в указанном модуле. Если же применять ее к продукту (например product.moduleProperty(«cpp», «defines»), то возвращаться будут свойства указанного модуля, которые использует собираемый в данный момент конечный продукт.

* Очень удобной функцией является dumpObject(object) из модуля ModUtils, которая выводит в консоль информацию о свойствах переданного в него параметра. Правда и она не всегда показывает свойства используемых в артефактах модулей.

Команды


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

  1. Command, который запускает внешний процесс
  2. JavaScriptCommand, который выполняет произвольный код JavaScript (хотя может также запускать внешние процессы)

Для обоих типов команд доступны свойства:

  • description — строка, показываемая в консоли при выполнении данной команды
  • extendedDescription — строка детальной информации, показываемой в консоли при расширенном выводе
  • highlight — тип (тег) команды. Влияет на то, как будет показываться description в консоли. Может быть: compiler, linker, codegen, filegen и пр.
  • silent — скрывать ли вывод description при выполнении команды

Для использования Command, необходимо создать объект передав в его конструктор полный путь до исполняемой программы и список аргументов.

var myCommand = new Command("dir", ["/B", "/O", ">>", output.filePath]);

Например данная команда запишет вывод команды dir в выходной файл правила сборки.
Полезными свойствами, позволяющими обойти ограничение Windows на длину командной строки являются свойства:

  • responseFileThreshold содержит значение. Если это значение больше нуля и меньше длины полной командной строки, и если responseFileUsagePrefix не пуст, то содержимое командной строки перемещается во временный файл, путь которого становится полным содержимым списка аргументов. Затем программа должна прочитать полный список аргументов из этого файла. Этот механизм будет работать только с программами, которые явно поддерживают его.
  • responseFileArgumentIndex — указывает индекс первого аргумента для включения в файл ответов.
  • responseFileUsagePrefix — содержит префикс, который сообщает программе, что остальная часть аргумента — это путь к файлу, содержащему фактическую командную строку.

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

  • stderrFilterFunction — функция с входным параметром равным выводу программы в stderr и которая должна вернуть преобразованную строку для дальнейшего вывода.
    Если не задана, то обработки не будет производиться.
  • stdoutFilterFunction — аналогичная stderrFilePath, только работающая с stdout
  • stdoutFilePath — название файла, кода направляется отфильтрованный ранее вывод stdout. Если не задан, то вывод будет производиться в консоль
  • stderrFilePath — аналогичная stdoutFilePath, только работает с stderr

JavaScriptCommand команда — представляет собой JavaScript функцию, которая будет выполняться при сборке. Задается это функция в свойстве sourceCode. В исходном коде функции доступны project, product, inputs и outputs (дающий доступ к свойствам проекта, продукта, входных и выходных артефактов соответственно). Чтобы передать в функцию произвольные данные, то для команды надо добавить произвольные свойства и присвоить им нужные значения. Например так:

var cmd = new JavaScriptCommand();
cmd.myFirstData = "This is 1 string";
cmd.mySecondData = "This is 2 string";
cmd.sourceCode = function() {
    console.info("String from source code");    // -->> "String from source code"
    console.info("Property 1: "+myFirstData);   // -->> "Property 1: This is 1 string"
    console.info("Property 2: "+mySecondData);  // -->> "Property 2: This is 2 string"
};

В функции, также можно использовать разные доступные сервисы:

  • Environment Service — для доступа к системной среде и среде разработки
  • File Service — для работы с файлами (копирование, перемещение, удаление файлов, проверки существования файла и даты модификации, создания путей и сканирования директории на содержимое)
  • FileInfo Service — операции обработки пути к файлу (получение базового имени файла, пути к нему, получение относительного пути и т.п.)
  • General Services — дополнительные функции расширяющие функционал обработки строк, массивов и т.п.
  • Process Service — функции позволяющие запускать и управлять внешними программами, а также работать с его входом и выходом
  • PropertyList Service — функции для работы со списками свойств в форматах JSON, XML, binaty и OpenStep для платформ Darwin (iOS, macOS, tvOS, и watchOS)
  • TemporaryDir Service — функции для создания и управления временным каталогом
  • TextFile Service — функции для работы с текстовыми файлами и позволяющие читать/писать из/в них.
  • Utilities Service — функции для получения хешей

Прочие свойства элемента Rule


У элемента Rule также есть несколько дополнительных свойств:

Свойство multiplex, необходимо для указания порядка обработки входных артефактов. При multiplex=true, создается одна копия правила для всех входных артефактов и они обрабатываются все скопом. Таким образом в свойстве inputs будут все входные артефакты. Применяется в случаях, когда надо производить групповую обработку входных артефактов. Если же multiplex=false, то для каждого входного артефакта будет создаваться отдельная копия правила преобразования и будет создаваться свой выходной артефакт. Таким образом свойство inputs будет содержать всегда один элемент. По умолчанию это свойство имеет значение false.

Свойство condition, указывает на условие выполнения правила. Например, указать, что преобразование будет выполняться только в режиме release и для платформы windows.

 qbs.buildVariant === "release" && qbs.targetOS.contains("windows") 

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

Свойство alwaysRun указывает, на условия выполнения команд в правиле. Если alwaysRun=true, то команды будут всегда выполняться, даже не взирая на то, что выходные артефакты уже обновлены. По умолчанию равно false.

Пример подготовки правила преобразования



В качестве примера правила приведу следующую задачу:

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

winDeployQt - деплой Qt библиотек для проекта
-- MyWindowsDeploy.qbs --
import qbs
import qbs.ModUtils

Module {
Rule {
        condition: qbs.targetOS.contains("windows") //запускается только для windows
        multiplex: true //обрабатываем все входные артефакты одним трансформером 
        alwaysRun: true //всегда выполнять правило

        inputsFromDependencies: ["installable"] //брать устанавливаемые артефакты от зависимостей собираемого продукта
        Artifact {
            filePath: "Copied_qt_libs.txt";
            fileTags: ["deployQt"];
        }

        prepare: {
            var cmdQt = new JavaScriptCommand();
            //определяем путь до windeployqt.exe
            cmdQt.windeployqt = FileInfo.joinPaths(product.moduleProperty("Qt.core", "binPath"), "windeployqt.exe");
            //задаем строку для вывода в консоли
            cmdQt.description = "Copy Qt libs and generate text file: "+output.fileName;
            //указываем развернутую информацию по выполняемой команде
            cmdQt.extendedDescription = cmdQt.windeployqt + ".exe " +
                    ["--json"].concat(args).concat(binaryFilePaths).join(" ");
            
            //путь до папки, куда надо копировать qt библиотеки ("<папка установки>/QtLibs")
            var deployDir = FileInfo.joinPaths(product.moduleProperty("qbs","installRoot"),
                                            product.moduleProperty("qbs","installDir"));
            deployDir = FileInfo.joinPaths(deployDir, "QtLibs");
            cmdQt.qtLibsPath = deployDir;
            
            //определяем аргументы запуска программы
            cmdQt.args = [];
            cmdQt.args.push("--libdir", deployDir);
            cmdQt.args.push("--plugindir", deployDir);
            cmdQt.args.push("--no-translations");
            cmdQt.args.push("--release");
            
            //полное имя файла для записи вывода.
            cmdQt.outputFilePath = output.filePath;
            
            //определяем список путей установки программ и библиотек, от которых зависит продукт
            cmdQt.binaryFilePaths = inputs.installable.filter(function (artifact) {
                return artifact.fileTags.contains("application")
                        || artifact.fileTags.contains("dynamiclibrary");
            }).map(function(a) { return ModUtils.artifactInstalledFilePath(a); });
          
            cmdQt.sourceCode = function(){
                var process;
                var tf;
                try {
                    //выводим значения параметров
                    console.info("windeployqtRule: outputFilePath: "+outputFilePath);
                    console.info("windeployqtRule: qtLibsPath: "+qtLibsPath);
                    console.info("windeployqtRule: windeployqt: "+windeployqt);
                    console.info("windeployqtRule: windeployqtArgs: "+windeployqtArgs.join(", "));
                    console.info("windeployqtRule: binaryFilePaths: "+binaryFilePaths.join(", "));
            
                    //создаем папку куда будут скопированы библиотеки Qt
                    File.makePath(qtLibsPath);
                    //создаем процесс
                    process = new Process();
                    //запускаем процесс
                    process.exec(windeployqt,
                                 ["--json"].concat(windeployqtArgs).concat(binaryFilePaths), true);
                    //читаем вывод программы
                    var out = process.readStdOut();  
                    //парсим выходной JSON
                    var inputFilePaths = JSON.parse(out)["files"].map(function (obj) {
                        //определяем полный путь доя скопированной библиотеки
                        var fn = FileInfo.joinPaths(
                                    FileInfo.fromWindowsSeparators(obj.target),
                                    FileInfo.fileName(
                                        FileInfo.fromWindowsSeparators(
                                            obj.source)));
                        return fn;
                    });
                    //создаем файл
                    tf = new TextFile(outputFilePath, TextFile.WriteOnly);
                    //пишем заголовок
                    tf.writeLine("Copied Qt files:");
                    inputFilePaths.forEach(function(qtLib){
                        tf.writeLine(qtLib); //записываем в выходной файл полный путь до скопированной библиотеки
                    });
                } finally {
                    if (process)
                        process.close();
                    if (tf)
                        tf.close();
                }
            }

            return [cmdQt];
        }
    }
}


Пример продукта
-- ProductDeploy.qbs --
import qbs

Product {
//продукт представляет собой результат деплоя Qt библиотек для продуктов от которых он 
//зависит в виде скопированных библиотек и текстового файла
    type: ["deployQt"] 

   // указываем зависимость от модуля в котором есть правило преобразования
    Depends { name: "MyWindowsDeploy" } 
   // указываем зависимость от продуктов, для которых 
   // надо подготовить Qt библиотеки, плагины и пр.
    Depends { name: "libratyA" }
    Depends { name: "libratyB" }
    Depends { name: "applicationA" }
    Depends { name: "applicationB" }
    Depends { name: "applicationC" }

    condition: qbs.targetOS.contains("windows")     // собирать только для windows
    builtByDefault: false // собирать ли продукт при общей сборке проекта

    qbs.install: true
    qbs.installDir: "MyProject/qtDeploy"
}


Ссылки


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330218/


Метки:  

[Из песочницы] Mikrotik. QoS для дома

Вторник, 06 Июня 2017 г. 16:31 + в цитатник
Сегодня я хотел бы немного рассказать о приоритетах.
image

Статья не претендует на охват всей информации по QoS на Mikrotik. Это демонстрация набора правил, позволяющих настроить несложную схему приоритезации трафика и пополнять её по мере необходимости.

Надеюсь, коллеги помогут советами в комментариях.

Говоря о QoS, обычно подразумевают два направления — более или менее равномерное деление канала по количеству пользователей, либо приоритезацию трафика. Направления эти вполне дополняют друг-друга, но для дома, для семьи заниматься делением канала я смысла не вижу и, если вас интересует эта тема, сошлюсь на исчерпывающе раскрывающую тему статью «MikroTik QoS — развенчание мифов».

Я же сосредоточусь на приоретизации трафика, благо это несколько проще.

Ограничение скорости передачи данных может быть выполнено двумя способами:

1. Отбрасываются все пакеты, превышающие лимит скорости передачи (шейпер).
2. Задержка превысивших заданное ограничение скорости передачи пакетов в очереди и отправка их позже, как только появляется такая возможность, т.е. выравнивание скорости передачи (шедулер).

Principles of rate limiting and equalizing

Как видно на иллюстрации, шейпер режет всё, что не влезло, а шедулер просто притормаживает.
Соответственно, именно шедулер нам и нужен.

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

Самый простой вариант такого решения, который зачастую и используется — просто пустить приоритетом VoIP-трафик, а весь остальной по остаточному принципу, но я сделаю чуть сложнее.

Итак, план таков:

prio_1: DNS, ICMP, ACK — в первую очередь идёт служебный трафик. Установка и разрыв соединений, резолвинг имён и т.п.
prio_2: SIP — VoIP очень любит минимальные задержки.
prio_3: SSH и игры — удалённый доступ важен для работы. Игры — для отдыха.
prio_4: RDP и HTTP/HTTPS — веб, видео и т.п.
prio_5: всё, что не опознано выше — в принципе, можно принудительно загнать сюда торренты. Благо дома порты с которых работают клиенты вполне известны..

Маленькое лирическое отступление:

Если мы поищем информацию о QoS в Mikrotik, то найдём несколько вариантов скриптов, начиная от монструозного QOS script by Greg Sowell или явно основанного на нём The Mother of all QoS Trees, заканчивая Traffic Prioritization Script (кстати, советую отнестись к нему с большой осторожностью, автор явно довольно смутно понимает, что делает и поэтому скрипт делает явно не то, что было задумано). У всех этих скриптов есть одна общая проблема — они написаны довольно давно и в значительной степени устарели по одной простой причине — мир изменился.

Сегодня, благодаря всеобщему шифрованию трафика, мы не можем так запросто взять и с помощью L7-regexp отловить трафик youtube, например, или Skype. Поэтому, используя такие скрипты, внимательно отнеситесь к вопросу определения трафика. Это, на мой взгляд, единственная сложность в этом вопросе.

Теперь разметим трафик согласно плана выше. В коде я использую interfaceBandwidth, т.е. ширину канала. У меня он симметричный и равен 100М. Если у вас отличается ширина канала, то необходимо изменить значение interfaceBandwidth на необходимое. Если канал асинхронный, то скрипт будет сложнее за счёт необходимости отдельно маркировать пакеты для входящего и исходящего трафика. Это несложно, но значительно увеличит скрипт, ухудшив его читаемость и, в целом, выходит за рамки статьи.

В address-list я демонстрирую возможность массовой вставки адресов из FQDN (для примера взяты адреса кластеров из wiki Мира Танков). Разумеется, можно просто прописать необходимые IP вручную.

#Set bandwidth of the interface
:local interfaceBandwidth 100M

# address-lists
:for i from=1 to=10 do={/ip firewall address-list add list=WoT address=("login.p"."$i".".worldoftanks.net")}
#
/ip firewall mangle
# prio_1
    add chain=prerouting action=mark-packet new-packet-mark=prio_1 protocol=icmp
    add chain=prerouting action=mark-packet new-packet-mark=prio_1 protocol=tcp port=53
    add chain=prerouting action=mark-packet new-packet-mark=prio_1 protocol=udp port=53
    add chain=prerouting action=mark-packet new-packet-mark=prio_1 protocol=tcp tcp-flags=ack packet-size=0-123
# prio_2
    add chain=prerouting action=mark-packet new-packet-mark=prio_2 dscp=40                                     
    add chain=prerouting action=mark-packet new-packet-mark=prio_2 dscp=46
    add chain=prerouting action=mark-packet new-packet-mark=prio_2 protocol=udp port=5060,5061,10000-20000 src-address=192.168.100.110
    add chain=prerouting action=mark-packet new-packet-mark=prio_2 protocol=udp port=5060,5061,10000-20000 dst-address=192.168.100.110
# prio_3
    add chain=prerouting action=mark-packet new-packet-mark=prio_3 protocol=tcp port=22
    add chain=prerouting action=mark-packet new-packet-mark=prio_3 address-list=WoT
# prio_4
    add chain=prerouting action=mark-packet new-packet-mark=prio_4 protocol=tcp port=3389
    add chain=prerouting action=mark-packet new-packet-mark=prio_4 protocol=tcp port=80,443
# prio_5
    add chain=prerouting action=mark-packet new-packet-mark=prio_5

Аккуратно уложим размеченный трафик в очередь:

queue tree add max-limit=$interfaceBandwidth name=QoS_global parent=global priority=1
:for indexA from=1 to=5 do={
   /queue tree add \ 
      name=( "prio_" . "$indexA" ) \
      parent=QoS_global \
      priority=($indexA) \
      queue=ethernet-default \
      packet-mark=("prio_" . $indexA) \
      comment=("Priority " . $indexA . " traffic")
}

И последнее, коль скоро Mikrotik поддерживает WMM, было бы логично разметить трафик и для него.

Делается это тем же mangle-ом с помощью команды set_priority. Согласно wiki Mikrotik'а, таблица приоритетов WMM выглядит довольно причудливо:

1,2 — background
0,3 — best effort
4,5 — video
6,7 — voice.

Разметим приоритеты, используя те же правила, что и для маркировки пакетов:

/ip firewall mangle
# prio_1
    add chain=prerouting action=set-priority new-priority=7 protocol=icmp
    add chain=prerouting action=set-priority new-priority=7 protocol=tcp port=53
    add chain=prerouting action=set-priority new-priority=7 protocol=udp port=53
    add chain=prerouting action=set-priority new-priority=7 protocol=tcp tcp-flags=ack packet-size=0-123
# prio_2
    add chain=prerouting action=set-priority new-priority=6 dscp=40                                     
    add chain=prerouting action=set-priority new-priority=6 dscp=46
    add chain=prerouting action=set-priority new-priority=6 protocol=udp port=5060,5061,10000-20000 src-address=192.168.100.110
    add chain=prerouting action=set-priority new-priority=6 protocol=udp port=5060,5061,10000-20000 dst-address=192.168.100.110
# prio_3
    add chain=prerouting action=set-priority new-priority=5 protocol=tcp port=22
    add chain=prerouting action=set-priority new-priority=4 address-list=WoT
# prio_4
    add chain=prerouting action=set-priority new-priority=3 protocol=tcp port=3389

В принципе, на этом всё.

В будущем, при необходимости, можно подумать о формировании динамических адресных листов, периодически формируемых из кэша DNS скриптами типа:

:foreach i in=[/ip dns cache all find where (name~"youtube" || name~"facebook" || name~".googlevideo")]
    do={:put [/ip dns cache get $i address]}

для отбора онлайнового видео.

Или детектить Skype с помощью поиска upnp-правил:

:foreach i in=[/ip firewall nat find dynamic and comment~"Skype"]
    do={:put [/ip firewall nat get $i dst-port]}

Но пока у меня такой необходимости нет.

Скрипты из статьи доступны на GitHub'е. Если у вас что-то не заработало, есть идеи или комментарии — пишите.

Спасибо за внимание!

UPD: В исходной версии статьи в скриптах была ошибка (неверно выбранная цепочка). Скрипты исправлены.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330362/


Метки:  

Браузеры на основе Chromium — теперь и в ReactOS

Вторник, 06 Июня 2017 г. 15:51 + в цитатник
Привет, Хабр!

Вот и настал тот момент, когда одна картинка лучше тысячи слов.

image

Теперь в ночных сборках ReactOS можно установить и даже запустить хромоподобные браузеры.
Стоит отметить, что пока требуется использовать следующие ключи запуска:
--allow-no-sandbox-job —disable-preconnect —disable-translate —disable-accelerated-video —disable-gpu —disable-plugins —no-sandbox
При этом, вероятно, не все они жизненно необходимы, и от некоторых уже можно избавится, Напишите нам об итогах своих экспериментов.

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

image

Зато играет видео!

image

image

Скриншоты прислал юзер телеграма @a1anwake.

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

И еще маленькая новость для забравшихся под кат:


В ReactOS с недавних пор активирована поддержка файловой системы UDF!
ФС UDF примечательна тем, что изначально являлась полностью открытым стандартом и обладала невероятной кросс-платформенностью и универсальностью. UDF разработали специально для DVD-дисков, но ее можно использовать даже для флешек и разделов жестких дисков.
Четыре года назад проекту пожертвовали исходные коды проприетарного драйвера UDF, два года назад его импортировали в древо исходных кодов проекта, и вот наконец драйвер «поженили» с ОС и системой сборки дистрибутива.

Reading a file from an UDF volume in @reactos (yes, it's something like the MS-PSDK setup DVD) pic.twitter.com/6iYEiOWOFI

— Pierre Schweitzer (@HeisSpiter) June 3, 2017


Экспериментируйте с браузерами и оптическими дисками, мы ждем ваших впечатлений в комментариях!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330356/


Метки:  

Предоставляем анализатор PVS-Studio экспертам безопасности

Вторник, 06 Июня 2017 г. 15:44 + в цитатник
Неожиданно для самих себя мы поняли, что можем взаимовыгодно сотрудничать с экспертами в сфере информационной безопасности. Те из них, кто занимается поиском уязвимостей в коде приложений, могут воспользоваться бесплатной версией анализатора PVS-Studio для своих исследований. В свою очередь, если будут найдены уязвимости, наш анализатор приобретёт большую популярность. PVS-Studio может быть использован для исследований проектов, написанных на языке C и C++.

Всё началось с открытого письма "Команда PVS-Studio готова поработать над проектом Tizen", которым мы хотели привлечь интерес компании Samsung Electronics. Компания Samsung заинтересована в надёжности и безопасности операционной системы Tizen, и проводит различные исследовательские изыскания, связанные с этой темой. Например, компания вложила более $10 миллионов в статический анализатора Svace, разрабатываемый в ИСП РАН. Мы решили, что анализатор PVS-Studio также может быть полезен разработчикам Tizen, раз находит ошибки в этом проекте.

Кстати, по моим расчётам мы можем выявить и устранить в Tizen около 27000 ошибок. Но это отдельная история, про которую я буду рассказывать позже, а пока можно просто взглянуть на презентацию с расчётами: RU: pptx, slideshare; EN: pptx, slideshare.

После этого с нами связался Amihai Neiderman (@AAAAAAmihai), который заинтересовался возможностями анализатора PVS-Studio. Amihai Neiderman месяц назад как раз выступал на конференции с докладом, посвященным уязвимостям в операционной системе Tizen: Breaking Tizen.

Мы пообщались с ним и выдали лицензию на анализатор PVS-Studio для его дальнейших изысканий в сфере поиска уязвимостей. Неизвестно, повезёт ли ему найти какие-то уязвимости с помощью нашего анализатора или нет, но почему бы не попробовать, ведь все только выигрывают. У Amihai Neiderman появится новый инструмент, выявляющий подозрительный код, в котором могут скрываться уязвимости. Если повезёт и уязвимость будет найдена, то на следующем выступлении у него будет повод упоминать анализатор PVS-Studio. Это будет отличная дополнительная реклама нашего инструмента.

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

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

Желающие получить лицензию и поддержку, должны будут подтвердить, что они занимаются вопросами безопасности и ведут публичную деятельность, например, пишут статьи. Впрочем, думаем, это уточнится в ходе общения. Тем, кому интересна данная тема, просим написать нам на support [@] viva64.com.

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

Примечание. Раньше мы не позиционировали свой анализатор как инструмент для предотвращения уязвимостей. Мы писали статьи о поиске обыкновенных ошибок. Теперь нам хочется, чтобы программисты воспринимали PVS-Studio не только как инструмент поиска опечаток и прочих ляпов, но и как инструмент, помогающий предотвратить многие уязвимости. Анализатор PVS-Studio находит множество ошибок, классифицируемых согласно CWE (пример). При стечении определённых обстоятельств CWE может превратиться в CVE. Поэтому, используя PVS-Studio, программист не только избавляет код от ошибок и тем самым сокращает стоимость разработки, но и дополнительно предотвращает многие уязвимости.

Ссылки:
  • Анализатор PVS-Studio. Скачать версию для: Windows, Linux.
  • Обновляемый список статей, в которых мы рассказываем об ошибках, найденных с помощью PVS-Studio в открытых проектах.
  • Ошибки, обнаруженные в Open Source проектах разработчиками PVS-Studio с помощью статического анализа: база ошибок.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330352/


Метки:  

[Перевод] Пять шагов к спасению Linux-сервера, который рухнул

Вторник, 06 Июня 2017 г. 15:42 + в цитатник
Мне доводилось видеть множество Linux-серверов, которые, без единой перезагрузки, работали годами, в режиме 24x7. Но ни один компьютер не застрахован от неожиданностей, к которым могут вести «железные», программные и сетевые сбои. Даже самый надёжный сервер может однажды отказать. Что делать? Сегодня вы узнаете о том, что стоит предпринять в первую очередь для того, чтобы выяснить причину проблемы и вернуть машину в строй.

image

И, кстати, в самом начале, сразу после сбоя, стоит ответить на весьма важный вопрос: «А сервер ли виноват в том, что случилось?». Вполне возможно, что источник проблемы совсем не в нём. Но, не будем забегать вперёд.

Поиск и устранение неполадок: раньше и теперь


Когда, в 1980-х, я начал работать системным администратором Unix — задолго до того, как Линус Торвальдс загорелся идеей Linux — если с сервером было что-то не так, это была реальная засада. Тогда было сравнительно мало инструментов для поиска проблем, поэтому для того, чтобы сбойный сервер снова заработал, могло понадобиться много времени.

Теперь всё совсем не так, как раньше. Как-то один системный администратор вполне серьёзно сказал мне, говоря о проблемном сервере: «Я его уничтожил и поднял новый».

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

Сюда надо добавить инструменты DevOps, такие, как Chef и Puppet, используя которые легче создать новый сервер, чем диагностировать и «чинить» старый. А если говорить о таких высокоуровневых средствах, как Docker Swarm, Mesosphere и Kubernetes, то благодаря им работоспособность отказавшего сервера будет автоматически восстановлена до того, как администратор узнает о проблеме.

Данная концепция стала настолько распространённой, что ей дали название — бессерверные вычисления. Среди платформ, которые предоставляют подобные возможности — AWS Lambda, Iron.io, Google Cloud Functions.

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

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

Помню разговор с одним системным оператором. Вот что он говорил о том, как надо поступать после сбоя: «Переустановка сервера — это путь вникуда. Так не понять — что стало с машиной, и как не допустить такого в будущем. Ни один сносный администратор так не поступает». Я с этим согласен. До тех пор, пока не обнаружен первоисточник проблемы, её нельзя считать решённой.

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

Шаг первый. Проверка аппаратного обеспечения


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

Я и сосчитать не смогу, сколько раз поиски причины проблемы приводили к кабельным соединениям. Один взгляд на светодиоды — и становится ясно, что Ethernet-кабель выдернут, или питание сервера отключено.

Конечно, если всё выглядит более-менее прилично, можно обойтись без визита к серверу и проверить состояние Ethernet-соединения такой командой:

$ sudo ethtool eth0

Если её ответ можно трактовать, как «да», это значит, что исследуемый интерфейс способен обмениваться данными по сети.

Однако, не пренебрегайте возможностью лично осмотреть устройство. Это поможет, например, узнать, что кто-то выдернул какой-нибудь важный кабель и обесточил таким образом сервер или всю стойку. Да, это до смешного просто, но удивительно — как часто причина отказа системы именно в этом.

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

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

Для того, чтобы увидеть, что BIOS/UEFI сообщают об аппаратном обеспечении компьютера, включая память, используйте команду dmidecode:

$ sudo dmidecode --type memory

Даже если всё тут выглядит нормально, на самом деле это может быть и не так. Дело в том, что данные SMBIOS не всегда точны. Поэтому, если после dmidecode память всё ещё остаётся под подозрением — пришло время воспользоваться Memtest86. Это отличная программа для проверки памяти, но работает она медленно. Если вы запустите её на сервере, не рассчитывайте на возможность использовать эту машину для чего-нибудь другого до завершения проверки.

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

$ sudo modprobe edac_core

Подождите какое-то время и посмотрите, удастся ли что-нибудь увидеть, выполнив такую команду:

$ sudo grep "[0-9]" /sys/devices/system/edac/mc/mc*/csrow*/ch*_ce_count

Эта команда даст вам сводку о числе ошибок, разбитых по модулям памяти (показатели, название которых начинается с csrow). Эти сведения, если сопоставить их с с данными dmidecode о каналах памяти, слотах и заводских номерах компонентов, помогут выявить сбойную планку памяти.

Шаг второй. Поиск истинного источника проблемы


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

Например, друг однажды рассказал мне, как его пользователи сообщили о том, что не могут работать с IBM Tivoli Storage Manager. Сначала, конечно, казалось, что виновен во всём сервер. Но в итоге администратор выяснил, что проблема вообще не была связана с серверной частью. Причиной был неудачный патч Windows-клиента 3076895. Но то, как сбоило это обновление безопасности, делало происходящее похожим на проблему серверной стороны.

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

Для начала — самое очевидное. Работает ли приложение? Есть множество способов проверить это. Вот два моих любимых:

$ sudo ps -ef | grep apache2
$ sudo netstat -plunt | grep apache2

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

$ sudo service apache2 start

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

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

Шаг третий. Использование команды top


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

Для того, чтобы обнаружить процесс, потребляющий больше всего памяти, список процессов надо отсортировать в интерактивном режиме, введя с клавиатуры M. Для того, чтобы выяснить приложение, потребляющее больше всего ресурсов процессора, отсортируйте список, введя P. Для сортировки процессов по времени активности, введите с клавиатуры T. Для того, чтобы лучше видеть колонку, по которой производится сортировка, нажмите клавишу b.

Кроме того, данные по процессам, выводимые командой в интерактивном режиме, можно отфильтровать, введя O или o. Появится следующее приглашение, где предлагается добавить фильтр:

add filter #1 (ignoring case) as: [!]FLD?VAL

Затем можно ввести шаблон, скажем, для фильтрации по конкретному процессу. Например, благодаря фильтру COMMAND=apache, программа будет выводить только сведения о процессах Apache.

Ещё одна полезная возможность top заключается в выводе полного пути процесса и аргументов запуска. Для того, чтобы просмотреть эти данные, воспользуйтесь клавишей c.

Ещё одна похожая возможность top активируется вводом символа V. Она позволяет переключиться в режим иерархического вывода сведений о процессах.

Кроме того, можно просматривать процессы конкретного пользователя с помощью клавиш u или U, или скрыть процессы, не потребляющих ресурсы процессора, нажав клавишу i.

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

Я не жду, что top сообщит мне — в чём проблема. Скорее, я использую этот инструмент для того, чтобы найти нечто, что заставит подумать: «А это уже интересно», и вдохновит меня на дальнейшие исследования. Основываясь на данных от top, я знаю, например, на какие логи стоит взглянуть в первую очередь. Логи я просматриваю, используя комбинации команд less, grep и tail -f.

Шаг четвёртый. Проверка дискового пространства


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

Разобраться с дисковым пространством нам поможет старая добрая команда df, имя которой является сокращением от «disk filesystem». С её помощью можно получить сводку по свободному и использованному месту на диске.

Обычно df используют двумя способами.

  • $ sudo df -h

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

  • $ sudo df -i

    выводит число использованных inodes и их процент к файловой системе.

Ещё один полезный флаг df — T. Он позволяет вывести данные о типах файловых систем хранилищ. Например, команда вида $ sudo df -hT показывает и объём занятого пространства диска, и данные о его файловой системе.

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

Вероятно, самый полезный способ вызова этой команды выглядит так:

$ iostat -xz 1

Такая команда выводит сведения об объёме прочитанных и записанных данных для устройства. Кроме того, она покажет среднее время операций ввода-вывода в миллисекундах. Чем больше это значение — тем вероятнее то, что накопитель перегружен запросами, или перед нами — аппаратная проблема. Что именно? Тут можно воспользоваться утилитой top для того, чтобы выяснить, нагружает ли сервер MySQL (или какая-нибудь ещё работающая на нём СУБД). Если подобных приложений найти не удалось, значит есть вероятность, что с диском что-то не так.

Ещё один важный показатель можно найти в разделе %util, где выводятся сведения об использовании устройства. Этот показатель указывает на то, как напряжённо работает устройство. Значения, превышающие 60% указывают на низкую производительность дисковой подсистемы. Если значение близко к 100%, это означает, что диск работает на пределе возможностей.

Работая с утилитами для проверки дисков, обращайте внимание, что именно вы анализируете.

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

Шаг пятый. Проверка логов


Последнее в нашем списке, но лишь по порядку, а не по важности — проверка логов. Обычно их можно найти по адресу /var/log, в отдельных папках для различных сервисов.

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

Данные в файлах журналов обычно выглядят довольно таинственно, но вам всё равно придётся с ними разобраться. Вот, например, хорошее введение в эту тему от Digital Ocean.

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

$ dmesg | tail

Хотите следить за происходящим в реальном времени? Мне, определённо, это нужно, когда я занимаюсь поиском проблем. Для того, чтобы этого добиться, используйте команду tail с ключом -f. Выглядит это так:

$ dmesg | tail -f /var/log/syslog

Вышеприведённая команда наблюдает за файлом syslog, и когда в него попадают сведения о новых событиях, выводит их на экран.

Вот ещё один удобный сценарий командной строки:

$ sudo find /var/log -type f -mtime -1 -exec tail -Fn0 {} +

Он сканирует логи и показывает возможные проблемы.

Если в вашей системе применяется systemd то, вам нужно будет использовать встроенное средство для работы с журналами — Journalctl. Systemd централизует управление логированием с помощью демона journald. В отличие от других логов Linux, journald хранит данные в двоичном, а не в текстовом формате.

Бывает полезно настроить journald так, чтобы он сохранял логи после перезагрузки системы. Сделать это можно, воспользовавшись такой командой:

$ sudo mkdir -p /var/log/journal

Для включения постоянного хранения записей понадобится отредактировать файл /etc/systemd/journald.conf, включив в него следующее:

[Journal] Storage=persistent

Самый распространённый способ работать с этими журналами — такая команда:

journalctl -b

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

$ journalctl -b -1

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

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

Мне, например, нравится система для управления логами с открытым кодом Graylog. Она собирает, индексирует и анализирует самые разные сведения. В её основе лежат MongoDB для работы с данными и Elasticsearch для поиска по лог-файлам. Graylog упрощает отслеживание состояния сервера. Graylog, если сравнить её со встроенными средствами Linux, проще и удобнее. Кроме того, среди её полезных возможностей можно отметить возможность работы с многими DevOps-системами, такими, как Chef, Puppet и Ansible.

Итоги


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

Уважаемые читатели! А как вы обычно поступаете с упавшими серверами?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330350/


Метки:  

Мониторинг Linksys SPA8000 через Zabbix

Вторник, 06 Июня 2017 г. 15:16 + в цитатник


С чего все начиналось


У части наших клиентов установлены VoIP-шлюзы Linksys (Cisco) SPA8000. Неплохие по-своему железки, несмотря на некоторые странности, например, прибитый гвоздями NAT на slave-портах и странное поведение в некоторых ситуациях. Все хотелось наложить на них свои потные ручонки и замониторить по самое немогу. Но вот беда: мониторинг у них предельно бедный — только web-интерфейс для визуальной оценки творящегося там беспредела да внешний Syslog-сервер, на который не сильно-то много и сыпется: данные о статусе регистрации разве. В общем, неприступная такая железочка, суровая, как монголо-татарское иго. В итоге, было решено применить обходной маневр и схватить противника за… web-интерфейс. Что из этого получилось – читайте дальше.

Что берем?


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

# Hostname шлюза. Его же надо как-то называть.
spa8000.name = SPA8000
# Серийный номер. Это больше для инвентаризации.
spa8000.serial = CFH01N704858
# Версия ПО.
spa8000.software = 6.1.12(XU)
# Версия платы, насколько я понимаю.
spa8000.hardware = 1.0.0
# MAC-адрес сетевого интерфейса. Без него никуда.
spa8000.mac = D0C789784BE4
# Есть ли сертификат.
spa8000.cert = Installed
# Открыт ли шлюз для изменения конфигурации.
spa8000.customization = Open
 
# Время и аптайм. Не забывайте про NTP, товарищи.
spa8000.time = 1/12/2003 14:15:42
spa8000.system.uptime = 11 days and 02:15:42
 
# Средства для рисования красивых графиков, разнообразные счетчики
# сообщений, пакетов и байт.
spa8000.rtp.packets.sent = 3463097
spa8000.rtp.bytes.sent = 646834968
spa8000.rtp.packets.recv = 3435569
spa8000.rtp.bytes.recv = 641524220
 
spa8000.sip.msg.sent = 76279
spa8000.sip.bytes.sent = 36830167
spa8000.sip.msg.recv = 73969
spa8000.sip.bytes.recv = 30078139
 
# Autodiscovery линии.
# Статус линии.
spa8000.line{#LINE}.hook.state = On
# Статус регистрации линии.
spa8000.line{#LINE}.reg.state = Registered
# Дата и время последней регистрации.
spa8000.line{#LINE}.reg.time = 1/12/2003 14:08:01
# Количество секунд до перерегистрации.
spa8000.line{#LINE}.reg.next = 1321 s
# Состояние уведомления о голосовой почте.
spa8000.line{#LINE}.mvi = No
# Состояние уведомления о callback.
spa8000.line{#LINE}.callback = No
# Последний номер, на который звонили с этой линии.
spa8000.line{#LINE}.last.called = 8965ХХХХХХХ
# Последний номер с которого звонили на линию.
spa8000.line{#LINE}.last.caller = +7911ХХХХХХХ

Так как линии транков на SPA не настраивались, то и забор данных по ним не делался.

Как берем?


Все вышеперечисленные данные предполагалось извлекать из web-интерфейса путем его прямого запроса скриптом и последующего парсинга. Так как нет возможности контролировать, с какой периодичностью Zabbix будет опрашивать web-интерфейс (вдруг гений коллег решит, что опрашивать интерфейс раз в пять секунд – это очень весело), а тот, как известно, у SPA очень нетороплив, то было решено ввести в скрипт простенькую кэширующую систему, запрашивающую интерфейс не чаще одного раза в 30 секунд. Сам кэш представляет собой обычный CSV-файл, который лежит в папке /tmp и содержит в себе данные в следующем формате:

"info","SPA8000","CFH01N704858","6.1.12(XU)","1.0.0","D0C789784BE4","Installed","Open","1/12/2003 14:15:42","11 days and 02:15:42",3463097,646834968,3435569,641524220,76279,36830167,73969,30078139
"line1","On","Registered","1/12/2003 14:08:01",1321,"No","No","8965ХХХХХХХ","+7911ХХХХХХХ"
"line2",
. . .

Первое поле в каждой строке – это идентификатор строки кэша. В первой строке располагается общая информация, во второй и последующих — информация по всем линиям по порядку.

Так как это первый вариант скрипта, то он не поддерживает авторизацию, но добавить ее, если надо, будет несложно. При запуске скрипта без параметров получается autodiscovery для линий. Если требуется конкретное значение параметра, то скрипт вызывается в формате zabbix_spa8000.py $1 $2, где $1 – это группа данных которые запрашиваются, первое значение в строке кэша, $2 – конкретное значение, которое надо получить.

zabbix_spa8000.py
#!/usr/bin/python
# Get Cisco SPA status for Zabbix.
 
# codecs импортируется, если происходит отладка скрипта с открытием локального Файла.
#import codecs
import csv
import datetime
import os.path
import re
import sys
import tempfile
import time
import urllib
 
 
# Ссылка на интерфейс.
url = 'http:///voice/'
# Путь до файла кэша.
temp = tempfile.gettempdir()
base = temp + '/spa.csv'
 
# Генератор кэша.
# Если файл кэша не существует или старее 30 секунд, то получаем данные из web-интерфейса.
# Кэш проверяется и создается всегда самым первым, потому что все данные возвращаются
# на основе выборок из файла кэша, то есть напрямую со страницы данные читаются только
# в кэш.
if(not(os.path.exists(base)) or ((int(time.time()) - os.path.getmtime(base)) > 30)):
	# Читаем HTML страницу.
	html = urllib.urlopen(url).read()
	# Отладочная секция - читает файл с диска.
	#f = codecs.open("text.html", 'r', "utf-8")
	#html = f.read()
	#f.close()
 
	# Нормализуем и парсим HTML.
	# Приводим текст к одной строке.
	html = re.sub(r"\n+", " ", html)
	# Убираем пробелы между тегами.
	html = re.sub(r">\s+<", "><", html)
	# Страница очень длинная - там все вкладки интерфейса. Чтобы уменьшить вероятность
	# выборки не того отрезаем нужный нам кусок страницы.
	html = re.search(r".+?Trunk", html).group(0)
	# Получаем количество линий.
	count  = len(re.findall(r"]+>]+>Line\s(\d+)\sStatus",html))
	# Извлекаем все данные вперемешку. Так как в HTML формат всех полей с данными
	# одинаковый, то просто ищем все совпавшие кусочки данных и считаем их по
	# умолчанию значениями. дальше разберутся.
	data = re.findall(r"([^<:>]+):.+?]+>([^<]*)",html)
 
	# Создаем CSV файл.
	number = 0
	rows = []
 
	# Создаем заголовки строк.
	rows.append(['info'])
	count += 1
	for i in range (1, count):
		rows.append(['line' + str(i)])
	count -= 1
 
	# Заполняем строки. Выбираем из собранных данных все по одному и внимательно
	# присматриваемся. Так как данные лежат в массиве в том порядке, в котором
	# они отображаются на странице, то можем считать, что все значения до определенного
	# относятся к общей информации, а все что дальше, относится к линиям. Так все и устроено
	# первое значение каждой линии - это Hook State. Все что находится до первого такого значения
	# относится к общей информации, все что после - к линиям.
 
	# Цикл по извлеченным данным.
	for entry in data:
		# Значение, по которому разделяются данные общей информации и линий.
		if(entry[0] == 'Hook State'):
			number += 1
		# Обрабатываем все нужные данные, кроме всяких Call 1 Forward и иже с ними.
		if(not(re.match(r'Call\s\d+\s', entry[0]))):
			value = entry[1]
			# Преобразуем время в соответствующих полях. В Zabbix время уходит в виде unixtime.
			if(((entry[0] == 'Current Time') or (entry[0] == 'Last Registration At')) and (value)): # 1/13/2003 14:03:52
				if(value != '0/0/0 00:00:00'):
					value = int(time.mktime(datetime.datetime.strptime(entry[1], "%m/%d/%Y %H:%M:%S").timetuple()))
				else:
					value = 0
			# Извлекаем количество секунд.
			if((entry[0] == 'Next Registration In') and (value)): # 1263 s
				value = int(entry[1].split()[0])
			# Сохраняем значение в соответствующей строке массива.
			rows[number].extend([value])
 
	# Сохраняем кэш.
	with open(base, 'w') as csvfile:
		writer = csv.writer(csvfile)
		writer.writerows(rows)
		csvfile.close()
 
# Ну вот, кэш сохранен, можно теперь его использовать для вывода данных. Проверяем
# наличие параметров. Если они переданы, значит мы хотим чего-то конкретного. 
if(len(sys.argv) > 1):
 
	# Открываем файл кэша и ищем строку, которую мы запрашиваем первым параметром.
	with open(base, 'rb') as csvfile:
		reader = csv.reader(csvfile)
		for row in reader:
			# TODO: Прерывание цикла, если строка нашлась.
			if(row[0] == sys.argv[1]):
				line = row
		csvfile.close()
 
	# Проверяем, что запрошенная строка вообще есть в кэше.
	if('line' in locals()):
		# Определяем, что у нас спрашивают вторым параметром, и что вообще возвращать.
		# Блок общей информации.
		if(line[0] == 'info'):
			try:
				print({
					'name': line[1],
					'serial': line[2],
					'software': line[3],
					'hardware': line[4],
					'mac': line[5],
					'cert': line[6],
					'customization': line[7],
					'time': line[8],
					'uptime': line[9],
					'rtp.packets.sent': line[10],
					'rtp.bytes.sent': line[11],
					'rtp.packets.recv': line[12],
					'rtp.bytes.recv': line[13],
					'sip.msg.sent': line[14],
					'sip.bytes.sent': line[15],
					'sip.msg.recv': line[16],
					'sip.bytes.recv': line[17]
				}.get(sys.argv[2]))
			# Если запрошенного поля не нашлось, так и говорим.
			except IndexError as e:
				print('ZBX_UNSUPPORTED')
		# Блок линий.
		else:
			try:
				print({
					'hook.state': line[1],
					'reg.state': line[2],
					'reg.time': line[3],
					'reg.next': line[4],
					'mvi': line[5],
					'callback': line[6],
					'last.called': line[7],
					'last.caller': line[8],
				}.get(sys.argv[2]))
			except IndexError as e:
				print('ZBX_UNSUPPORTED')
	# Если запрашиваемая строка не нашлась в кэше, то тоже возвращаем ошибку.
	# Это позволяет не смущать Zabbix пустым результатом.
	else:
		print('ZBX_UNSUPPORTED')
else:
# Получаем autodiscovery для линий.
	# Выходная строка.
	s = ""
 
	# Открываем файл кэша и читаем его, формируя выходную строку.
	with open(base, 'rb') as csvfile:
		reader = csv.reader(csvfile)
		for row in reader:
			# Проставляем разделители.
			if(len(s) > 0):
				s = s + ","
			# Формируем JSON строку вручную.
			if(row[0] != 'info'):
				s = s + '{"{#LINE}":"' + str(row[0]) + '"}'
		csvfile.close()
	# Выводим сформированную строку.
	print('{"data":[' + s + ']}')
 
# Завершаем работу скрипта.
quit()


Скрипт надо положить в /share/zabbix/externalscripts. Если такой папки нет, надо ее создать и дать доступ пользователю Zabbix в нее.

Делаем скрипт исполняемым.

sudo chmod +x /share/zabbix/externalscripts/zabbix_spa8000.py

Тестируем правильность работы Autodiscovery.

/share/zabbix/externalscripts/zabbix_spa8000.py

Если все правильно на выходе получим примерно это:

{"data":[{"{#LINE}":"line1"},{"{#LINE}":"line2"},{"{#LINE}":"line3"},{"{#LINE}":"line4"},{"{#LINE}":"line5"},{"{#LINE}":"line6"},{"{#LINE}":"line7"},{"{#LINE}":"line8"}]}


Тестируем правильность передачи значений параметров.

/share/zabbix/externalscripts/zabbix_spa8000.py info serial

Если все правильно на выходе получим примерно это:

CFH01N704858

Добавляем в Zabbix UserParameter для получения данных агентом.

/etc/zabbix_agentd.conf.d/spa8000.conf
UserParameter=spa[],/share/zabbix/externalscripts/zabbix_spa.py $1 $2
UserParameter=spa.lines,/share/zabbix/externalscripts/zabbix_spa.py

Перезагружаем Zabbix-агент.

sudo service zabbix-agent restart

Проверяем, что Zabbix-агент может получать данные скрипта.

zabbix_agentd -t spa.lines
spa.lines                                 [t|{"data":[{"{#LINE}":"line1"},{"{#LINE}":"line2"},{"{#LINE}":"line3"},{"{#LINE}":"line4"},{"{#LINE}":"line5"},{"{#LINE}":"line6"},{"{#LINE}":"line7"},{"{#LINE}":"line8"}]}]
zabbix_agentd -t spa[info,serial]
spa[info,serial]                          [t|CFH01N70
4858]


Куда кладем?


Шаблон для Zabbix-сервера. Присоединяется к тому узлу, откуда есть доступ к web-интерфейсу SPA.

Шаблон для Zabbix-сервера


    3.0
    2016-09-09T11:04:05Z
    
        
            Шаблоны общие
        
    
    
        
    
    
        
            {Template_Cisco_Linksys_SPA:spa[info,uptime].last()}<180
            SPA перезагружен
            
            0
            2
            Время работы SPA менее 3 минут.
            0
            
        
    




Что в итоге?


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

P.S. Надеюсь, кому-нибудь пригодится. Буду рад вашим комментариям.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330346/


Метки:  

Без заголовка

Вторник, 06 Июня 2017 г. 14:39 + в цитатник
Конференция PG Day проводится уже в четвертый раз. За это время у нас накопилась большая база полезных материалов от наших докладчиков. Уровень докладов в индустрии с каждым годом становится все выше и выше, но есть темы, которые, как хорошее вино, не теряют своей актуальности.

На одном из прошлых PG Day Валентин Гогичашвили, возглавляющий департамент Data Engineering в Zalando, рассказал, как PostgreSQL используется в компании с большим штатом разработчиков, высокой динамичностью процессов, и как они пришли к такому выбору.

Не секрет, что Zalando является постоянным гостем PG Day. На PG Day'17 Russia мы представим вам три замечательных доклада от немецких коллег. Мурат Кабилов и Алексей Клюкин расскажут про внутреннюю разработку Zalando для развертывания высокодоступных кластеров PostgreSQL. Александр Кукушкин поведает о практике эксплуатации PostgreSQL в AWS. Дмитрий Долгов поможет разобраться c внутренностями и производительности типа данных JSONB в контексте эксплуатации PostgreSQL как документо-ориентированного хранилища.



Я первый раз за всю свою жизнь буду презентовать по-русски. Не обессудьте, если какие-то переводы и термины окажутся очень смешными для вас. Начну с себя. Я Валентин, возглавляю департамент Data Engineering в Zalando.





Zalando – это очень известный в Европе онлайн-магазин по продаже обуви и всего, что связано с одеждой. Вот так он выглядит приблизительно. Узнаваемость бренда около 98% в Германии, очень хорошо поработали наши маркетологи. К сожалению, когда маркетологи работают хорошо, становится очень плохо технологическим департаментам. В момент, когда я пришел в Zalando 4 года назад, наш отдел состоял из 50 человек, и мы росли на 100% в месяц. И так продолжалось очень долго. Теперь мы одни из самых больших онлайн-магазинов. У нас три складских центра, миллионы пользователей и 8 тысяч сотрудников.



За ширмой интерфейса, вы прекрасно представляете, страшные вещи творятся, включая такие склады: у нас таких три штуки. И это только один маленький зал, в котором идет сортировка. С технологической точки зрения, все намного более красиво, очень хорошо рисовать схемы. У нас есть замечательный человек, который умеет рисовать.



Postgres занимает одну из самых важных ниш в нашей структуре, потому что в Postgres записываются все, что связано с данными пользователей. На самом деле, в Postgres записывается все, кроме поисковых данных. Ищем мы в Solar’ах. В нашем технологическом офисе на данный момент работает 700 человек. Мы растем очень быстро и постоянно ищем людей. В Берлине большой офис. Поменьше офисы в Дортмунде, Дублине и Хельсинки. В Хельсинки открылся буквально в прошлом месяце, там сейчас идет hiring.




Что мы делаем как технологическая компания?

Раньше мы были Java и Postgres компанией: все писалось на Java и записывалось в Postgres. В марте 2015 года мы объявили концепцию radical agility, которая дает нашим командам бесконечную автономию с возможностью выбора технологии. Поэтому для нас очень важно, чтобы Postgres все еще оставался для наших девелоперов технологией, которую они будут выбирать сами, а не я буду приходить и говорить «А ну, давайте пишите в Postgres». Шесть терабайт занимает база для «транзакционных» данных. Самая большая база, которая не включена туда, — это event-лог, который мы используем для записи наших timeseries, business events (около 7 терабайт). Интересно с этими данными работать. Много чего нового узнаешь обо всем.



Какие проблемы у нас?

Постоянный рост, быстрые, недельные циклы разработки: каждую неделю выкатываются новые фичи. И простои не поощряются. В последнее время у нас проблема – автономные команды разработчиков утаскивают базы данных в свои амазоновские аккаунты AWS, и у DBA-шников нет доступа к этим базам.



Расскажу о том, как мы меняем схему данных, так, чтобы производство не простаивало. Как мы работаем с данными (доступ к базам данных в Zalando осуществляется через слой хранимых процедур). Очень коротко объясню, почему я считаю это важным. И как мы шардим, как мы ломаем базы данных, тоже расскажу.



Итак, в Postgres одна из самых важных способностей – это возможность менять схемы данных практически без локов. Проблемы, которые существуют в Oracle, в MySQL и во многих других системах и, которые по существу привели к тому, что NoSQL базы поднялись как полноправные члены нашей дружной семьи баз данных, заключаются в том, что другие базы данных не могут так быстро и хорошо менять схемы данных. В PostgreSQL не нужны локи для того, чтобы добавить колонку или переименовать ее, дропнуть или добавить дефолтные значения, расширить каталоги.

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

Проблемы все-таки существуют с констрейнтами. До сих пор нет возможности добавить constraint NOT NULL на большую гигантскую таблицу без необходимости проверить, что в таблице действительно нет нулевых значений в столбцах. Это правильно, потому что мы доверяем constraints. Но, к сожалению, есть пара исключений, которые нужно применять для того, чтобы все это работало хорошо, не было страшных локов, которые остановят всю систему.



Как мы это организовали? Когда я начинал, в Zalando я был единственным DBA. Я писал все скрипты, которые меняют структуру баз данных. Потом мы поняли, что это ужас, потому что нужно это делать на каждом staging-окружении. Я начал дампить каталоги в разных environment’ах и сравнивать их diff’ами. Возникла идея автоматизировать создание dbdiffs. Я понял, что не получается тратить время на такой tool, и легче все-таки писать руками скрипты перехода с одной версии на другую. Но название dbdiff так и осталось.

С тем ростом, который у нас был, становилось невозможно писать dbdiff самим. Поэтому нам пришлось учить разработчиков писать SQL, тренировать их и сертифицировать по основам PostgreSQL, чтобы они понимали, как вообще работает база данных, почему возникают локи, где возникают регрессии и т.д. Поэтому мы ввели сертификацию для «релизеров». Только человек с таким сертификатом нашей команды получает административные права на базу и может останавливать систему. Мы, конечно же, приходим на помощь и помогаем, консультируем, делаем все, для того чтобы у ребят не было проблем.




Вот это пример того, как выглядит очень простой dbdiff: добавляется таблица order_address и foreign key. Проблема заключается в том, что, если во время разработки таблицу меняют, каждый раз надо менять и source этой таблицы. Поскольку каждый объект, каждая таблица лежит в отдельном файле в git, нужно каждый раз заходить и менять dbdiff, можно использовать прекрасную возможность pl/pgsql подгружать файлы из директории.



Что интересно, операция добавления foreign key constraint проблематична, поскольку требуется заблокировать всю таблицу, что может занимать много времени. Для того, чтобы обезопасить себя, мы рекомендуем всем устанавливать statement_timeout — количество секунд, в течение которых для вашей системы допустимо держать локи. Если таблица помещается в память, 3 секунд обычно хватает. Если не помещается, за 3 секунды ее уже не просканируешь.




Что нам помогает еще? Нам помогают tool'ы, которые мы написали. pg_view собирает всю информацию о базе, которая нам нужна, включая локи, заполняемость партиции с xlog. Выглядит приблизительно как top. Этот tool собирает информацию о том, сколько осталось места на дисках, чтобы можно было вовремя остановить миграции, если что-то идет не так, и показывает локи, которые возникают в базе данных.

nice_updater – это программа, которая контролирует базу, смотрит ее нагрузку, загруженность xlog-партиций, медленно, по 10-100 тысяч записей, выполняет update statements, периодически запускает вакуум. Таким образом мы проводим большие миграции. Если нужно добавить какую-то таблицу или записать новые значения в дополнительные колонки, при помощи nice_updater это очень легко сделать. Выкатили какую-то операцию, из-за которой несколько гигабайт неправильных данных образовалось, их нужно переписать — nice_updater нам очень хорошо помогает. По-моему, он уже в open source. Мы стараемся все наши tool'ы “опенсорсить”: качество кода очень сильно растет, появляется документация.

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

Наличие возможности отключить базу на 30 секунд для того, чтобы провести upgrade или что-нибудь еще сделать с базой, – это, на самом деле, первое что должно быть. Сегодня мы с Андресом [прим. ред.: Andres Freund] говорили, что вообще нужно сделать режим, который будет отключать случайным образом connections, чтобы разработчики учились писать нормальный код. У нас есть скрипт, который убивает все, что занимает больше пяти минут. Statement timeout у нас выставлен в 30 секунд по-умолчанию. Если кто-то пишет процедуру, которая занимает больше, чем 30 секунд, ему нужно привести веские основания.





Что нам дают хранимые процедуры?

Самое большое преимущество — возможность подменять данные на ходу: добавить новый пустой столбец, читая данные из старой колонки. Потом включить запись в обе колонки и делать чтения из новой, осуществляя fallback на старую с помощью coalesce. Потом провести миграцию данных в новую колонку. И потом можно уже выкинуть старую. Пару раз мы делали нормализацию таблиц так, что application code вообще не знал об этом. Это возможность важна для поддержания системы в работоспособном состоянии.

С хорошим тренингом и с хорошими tool'ами у нас получилось в принципе избежать простоев, вызванных миграциями или изменениями структуры данных. Для того, чтобы понять масштаб количества изменений: у нас в базе около 100 dbdiffs в неделю выкатывается. И они, в основном, меняют таблицы. Регулярно говорят о том, что реляционным базам данных не хватает гибкости в изменении структур данных. Это неправда.

Мы стараемся делать транзакции dbdiff, но, к сожалению, есть команды, которые не транзакционны, например, изменение enum.





Как обычно обращаются к данным?

Здесь у нас классическая структура — иерархия объектов: customer, у него есть bank account. Существует много разных заказов, в заказах перечислены позиции. Что хорошего в этой иерархии? Объекты, которые привязаны к customer'у, связаны только с ним. В большинстве случаев нам не нужно выходить за пределы этой иерархии. Нам совершенно не интересно, при оформлении заказа у Customer A, какие заказы имеются у Customer B, и наоборот. Все прекрасно знают, что тут очень много преимуществ: остаешься в своей зоне комфорта, пользуешься тем же языком, на котором пишешь бизнес-логику.

Но у нас были большие проблемы с hibernate, научить девелоперов писать код, который будет хорошо работать с транзакциями. Девелоперы пытаются загрузить всю таблицу в память, потом что-то с ней сделать и закоммитить какие-то части через пару минут. Остается длинная транзакция, и чем она длиннее, тем сложнее делать миграции в схемах. Таблицы надо постоянно отображать в коде. У нас нет такого понятия как база отдельно от application. Мы называем это data-логикой. По сути, это constraints, которые накладываются на данные, и их удобно держать в хранимых процедурах. Такое невозможно сделать с помощью миграций. По сути, это отдельный data layer.

Если нет хранимых процедур, лучше иметь abstract layer внутри application. Netflix, например, тоже так делают. У них есть специальная библиотека, с помощью которой они полностью абстрагируют через data layer доступ к данным. Таким образом они мигрировали с Оracle на Cassandra: они разделяют логику на business и data, и потом подменяют бизнес-логику другой базой данных. Но изменение схемы в такой ситуации может стать кошмаром.



NoSQL — прекрасная штука, можно взять всю эту иерархию вместе со всеми заказами и создать один документ. Ничего не нужно инициализировать, все прямо в JSON записывается. Транзакции не нужны: что записал, то записал. Возникают implicit схемы. Как с этим работать, когда структура документа начинает меняться и куда всю эту логику пихать? Это страшно. На данный момент, к сожалению, нет ни одной NoSQL базы, кроме PostgreSQL, которая в ACID и не теряет данных.

И, соответственно, в NoSQL нету SQL. SQL — очень мощный язык для аналитических операций, преобразовывает данные очень быстро. Все это делать, например, в Java — тоже как-то страшно.



Какие альтернативы ORM?

Прямые SQL запросы. Можно вытаскивать агрегаты с базы данных, не используя хранимые процедуры. Есть четкие границы транзакции — один SQL запускается, не тратится время на обработку данных между транзакциями. Очень хороший пример: YeSQL на Clojure работает, практически как хранимая процедура. И Scala Slick — если вы занимаетесь Scala и еще не видели Slick, то надо обязательно смотреть source code, это один из самых impressive pieces of code, которые я когда-либо видел.




Хранимые процедуры. Четкие границы транзакции. Абстрагирование от слоя данных. Это рецепт классического приложения, написанного на Java.

У нас есть бизнес-логика, JDBC Driver и таблицы с данными. Что мы сделали? Сначала мы внедрили слой хранимых процедур. Допустим, мы возвращаем row, например, getFullCustomerInformation, в которой есть массив, его заказы сериализуются Посгресом, внутри еще массив с позициями, внутри которого еще массив с банковскими данными. Получается очень хорошо типизированная иерархическая структура. Если это все написать в Java, в какой-то момент у нас по 50 страниц members в классах. Это приводило к настолько ужасным последствиям, что мы решили написать свою собственную библиотеку. Назвали ее Sproc Wrapper, которая работает как APC Layer в базе данных. Она, по сути, делает базу данных application server’ом.






Как это выглядит?

Пишется хранимая процедура, затем пишется вот такой маленький интерфейс с аннотациями. Вызов register_customer проходит совершенно прозрачно для приложения, вызывается хранимая процедура в базе данных, как и сериализация/десериализация всех ужасных вложенных array, hash maps и т.д. В том числе, структуры order address, которые map’ятся как list of orders.



Какие проблемы?

Проблемы с хранимыми процедурами заключаются в том, что нужно писать слишком много кода. Если надо делать много CRUD operations (вы пишите новый Excel), я бы не советовал пользоваться хранимыми процедурами. Если у вас таблицы по 100 столбцов, приходится вписывать изменение каждого столбца как отдельную хранимую процедуру, то можно сдуреть. У нас были люди, которые написали bootstrapper, генерирующий эти хранимые процедуры. Но потом мы сказали, что лучше в данной ситуации использовать hibernate и редактировать эти таблицы. У нас, например, в команде закупок, которая вбивают информацию о продуктах, есть инструмент, он написан на hibernate. Эти инструментом пользуются 500 человек, а нашим основным сайтом пользуется 15 миллионов.

Что положительного? Нужно учить SQL. Это очень помогает разработчикам. Разработчики, которые начали сейчас учить Closure и Scala, периодически ко мне прибегают и говорят «Scala — это практически как SQL, вау!!!». В принципе, да. Pipeline’ы данных, которые протекают снизу вверх через функциональные фильтры — именно то, что SQL делал всегда. К сожалению, в Scala до сих пор нет execution planner.



Автоматизируйте все.

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




Как мы версионируем?

Вначале, когда мы только начали использовать хранимые процедуры, у нас при изменении процедуры менялся тип данных, которые она возвращает. Нужно дропать старую процедуру, выкатывать новую. Все это в одной транзакции. Если есть какие-то зависимости между хранимыми процедурами, приходилось искать их ручками. Drop’ать полностью и выкатывать заново. Когда я был единственным DBA в компании, я только и делал, что занимался написанием этих страшных dbdiff, обновляющих хранимые процедуры. Потом мы как-то сели и придумали, что можно использовать потрясающую возможность PostgreSQL search_path, которая регулирует пути для поиска объектов в сессии. Если ваше приложение с версией 15.01 открывает и выставляет search_path, то объекты, которые оно будет находить, будут располагаться в этой схеме.

Наш deployment tool во время выкатки приложения с этим набором хранимых процедур создает схему нужной версии и туда все загружает. Application их затем использует. Что происходит, когда мы выкатываем новую версию? Deployment tool выкатывает новую схему со всем набором хранимых процедур, которые у нас есть, и, в момент пока происходит roll out новой версии, у нас работают обе версии на самом деле, каждая со своим набором хранимых процедур. Здесь нет ничего, что связано с данными. Это так называемые схемы API, которые обеспечивают data access layer и больше ничего. И все миграции, которые происходят, они происходят здесь. Поэтому, когда миграция происходит, она должна быть совместима с предыдущей версией, которая еще работает.

Вопрос из зала: Сколько времени вы учили разработчиков, чтобы они работали по такому flow? Как добиться, чтобы все делали именно так и не делали миграции, которые не совместимы с прошлыми версиями? Вы как-то тестируете дополнительно, что миграция действительно корректна, что новое API правильно читает старые данные и не падает при этом?

Валентин: Это, конечно, вопрос того, насколько хорошо test coverage работает, и насколько хорошо тестируется все. У нас разработчики работают на локальных базах, потом у нас есть integration staging, test staging, release staging и продакшен.

Вопрос из зала: Кто пишет API, DBA или разработчики? Как осуществляется разделение прав доступа?

Валентин: Пишут разработчики. Вариант, когда это делает DBA, не является масштабируемым. Я знаю несколько маленьких компаний, в которых DBA пишут вообще все API. Когда меня звали, то тоже считали, что я буду писать API. Но это невозможно. Мы нанимали сперва по пять человек в месяц, сейчас нанимаем по 40 человек в месяц. Поэтому легче потратить время на то, чтобы разработчики научились работать с базой. Это очень просто на самом деле, если объяснить как все физически хранится и устроено.



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




Каковы положительные моменты в том, что у нас есть одна большая база?

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





Но проблема возникает, когда данных у вас больше, чем оперативной памяти. Все становится медленнее: миграции, бекапы, maintenance, апгрейды. Чем больше база, тем больше головной боли. Мы разделяем данные: берем одну большую логическую базу и кладем ее на много инстансов PostgreSQL.





Что в этом хорошего?

Опять-таки, базы у нас становятся маленькими. С ними можно быстро работать, но проблема, конечно, состоит в том, что уже невозможно делать join’ы. Для аналитиков требуется больше инструментов. Для работы с данными требуется больше инструментов. Если вы думаете, что вы сможете работать с большими количествами данных, не вкладываясь в развитии инфраструктуры, которая автоматизирует ваши процессы, то вы ошибаетесь. Это невозможно сделать. Нужно писать много тулзов.






У нас было преимущество. У нас уже был Sproc Wrapper, который предоставляет нам data layer. Мы просто научили его обращаться к разным базам.

Как это выглядит? У нас есть вызов функции findOrders с параметром runOnAllShards = true. Он вызывает хранимую процедуру на всех шардах, которые у него были зарегистрированы. Или у нас есть CustomerNumber, и мы говорим, что это shard key. В конфигурации можно указать, какую стратегию поиска (Lookup Strategy) можно использовать: параллельный поиск по шардам, shard aware ID, и hashing тоже, по-моему, поддерживается. Самая широко используемая стратегия поиска объектов на шардах — так называемый Virtual Shard ID.



Идея очень простая на самом деле. У нас есть ключ партиционирования (partitioning key) — в иерархии, которую я показывал, это будет CustomerNumber. Partitioning key — это ключ, который определяет для каждого объекта границы связей между вашими объектами.






Формирование ключа.

Главное понять, что такое partitioning key. Например, у нас есть пользователи. У пользователя есть его заказы, и к этим заказам привязано много всяких позиций. Partitioning key — общий ключ, который выделяет группу объектов, которые принадлежат к одному пользователю. У нас это будет customer number, уникальный номер пользователя. Его нужно таскать вместе со всеми объектами типа Order, нижележащими объектами в иерархии, для того, чтобы понимать где находится мой Customer. Я всегда должен иметь возможность узнать, где лежит родитель для объектов из иерархии. Я боюсь говорить Customer ID, потому что ID — это технический ключ. Мы не говорим про технические ключи. Мы говорим про логические ключи. Потому что технические ключи будут не уникальны в рамках логической базы.

Вполне нормально использовать UUID для Customer ID. Мы различаем понятия Customer Number и Customer ID. Один Customer ID существует восемь раз в нашей системе, в восьми базах. А Customer Number — всегда один. Мы хешируем с помощью MD5, но вы можете сделать лучше. Главное, чтобы хеши распределялись равномерно. Это делается на уровне sharding-стратегии. На самом деле хеш нужно имплементировать везде, где приложению требуется быстро найти местоположение иерархии объектов. В нашей ситуации со Sproc Wrapper это будет просто Sharding Strategy для объекта Customer.

По размеру хеша у этого ключа мы определяем количество виртуальных шардов. Что происходит, когда мы хотим разделить базу? Мы просто говорим, что мы разделяем базу и начинаем использовать первый бит в нашем хеше. Таким образом, когда разделена база, мы можем указать, это был master, это стал slave, и в такой-то момент у нас будет очень короткое отключение системы. На данный момент этот так. Можно было бы полностью автоматизировать, чтобы было прозрачно. Отключаем систему, меняем sharding strategy и говорим, что с этого момента у нас доступ идет сюда и сюда, но мы пишем данные, у которых первый бит — единица, в другую базу, в которой уже были данные. Единственное, что нам после этого нужно сделать – стереть с этой базы все объекты, которые относятся к единице, а с другой — стереть все данные, которые относятся к нулю. И так далее. Даже можно несимметрично разделять. Sharding strategy может знать, что если у тебя хеш начинается с нуля, то еще есть пара шардов. Так лучше не делать, потому что можно с ума сойти. В принципе, мы разделяли так уже два раза.



Мы сейчас экспериментируем с потрясающей возможностью PostgreSQL — логической репликацией. Это multi-master — возможность апгрейдов на major версии без необходимости останавливать систему, делать все медленно и болезненно. Частичное реплицирование — можно будет вытаскивать из баз данных только одну таблицу или часть таблицы. Делать обновление кешей.




Мы работаем очень интенсивно, чтобы вытащить PostgreSQL в AWS с теми большими возможностями, что сейчас предоставляет RDS. Наша рабочая группа, которая занимается AWS, разработала систему, которая называется STUPS. Она позволяет выкатывать docker images в Spilo, traceable и monitorable way. Spilo при помощи трех команд может выкатить кластер PostgreSQL на AWS, который будет high available, сам переключаться при выключении одного из узлов, выбирать мастера. Но это тема для отдельного разговора.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/326246/


Метки:  

[Перевод] Эволюционные стратегии как масштабируемая альтернатива обучению с подкреплением

Вторник, 06 Июня 2017 г. 14:38 + в цитатник
Изложение статьи от том, что давно известные эволюционные стратегии оптимизации могут превзойти алгоритмы обучения с подкреплением.
Преимущества эволюционных стратегий:

  • Простота реализации
  • Не требуется обратного распространения
  • Легко масштабируется в распределенной среде вычислений
  • Малое число гиперпараметров.

Это исследование продолжает современный тренд, когда высокие результаты достигаются с помощью идей десятилетней давности. Например, в 2012 г. вышла статья об AlexNet, показавшая, как сконструировать, масштабировать и обучить сверточную нейронную сеть (СНН) для получения необычайной точности в задаче распознавания образов. Аналогично, в 2013 г. показано, что комбинация давно известного алгоритма Q-learning со сверточной нейронной сетью позволяет успешно обучить машину играть в игры для Atari. Алекснет возродил интерес к нейронным сетям в то время, когда большинство ученых считали, что СНН неперспективны в задачах компьютерного зрения. Так и эта работа демонстрирует, что эволюционная стратегия (ЭС) позволяет достичь высоких результатов на бенчмарках обучения с подкреплением, разрушая всеобщее мнение о том, что ЭС неприменима в задачах большой размерности.

ЭС легко реализовать и масштабировать. Наша имплементация способна обучить 3D гуманоида MuJoCo хождению на кластере из 80 машин (1440 ядер ЦПУ) всего за 10 минут (А3С на 32 ядрах требует около 10 часов). На 720 ядрах мы также получаем производительность для Atari, сравнимую с А3С, при сокращении времени обучения с 1 дня до 1 часа.

Обучение с подкреплением


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


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

Процесс обучения состоит в следующем. Начиная со случайной инициализации параметров, агент взаимодействует с игровым миром в течение какого-то времени, и накапливает эпизоды взаимодействия (например, каждый эпизод — это одна игра в теннис). Так мы получаем полную запись всего происходившего: какие состояния нам встретились, какие действия мы предприняли в каждом состоянии, какое вознаграждение получили на каждом шаге. Рецепт улучшения политики: все, что агент делал, и что приводило к улучшению награды, хорошо. К уменьшению награды — плохо. Мы можем использовать обратное распространение для вычисления малых изменений параметров сети, которые приведут к увеличению положительной награды и уменьшению отрицательной награды в будущем. Процесс повторяется итеративно: накапливаем новую порцию эпизодов, обновляем параметры, и повторяем.

Поиск в пространстве политик за счет внедрения шума


В ОП обычно используются стохастические политики, т.к. мы вычисляем лишь вероятности выполнения каждого из действий. Таким образом, за время обучения агент может оказаться в одном и том же состоянии много раз, но каждый раз он предпримет разные действия в соответствии с вероятностным сэмплированием. Это дает сигнал для обучения: некоторые из этих действий приведут к улучшению, а другие — к уменьшению вознаграждения. Таким образом мы внедряем шум в действия агента для поиска в пространстве политик, за счет сэмплирования распределения действий в каждый момент времени. Это отличается от ЭС, которая будет описана далее.

Эволюционные стратегии


Эволюция


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

Оптимизация методом черного ящика


Забудем об агенте, игровом мире, нейронных сетях, времени… В ЭС рассматривается черный ящик с 1 миллионом чисел на входе (параметрами функции политики), 1 числом на выходе (суммарное вознаграждение). Мы просто хотим найти наилучшее значение этих 1 млн. чисел.

Алгоритм эволюционной стратегии


Интуитивно, оптимизация — это процесс «загадай и проверь». Мы начинаем со случайного набора параметров, и затем последовательно:

1) случайно изменяем слегка значения параметров
2) перемещаемся чуть-чуть в сторону улучшения параметров.

Конкретно, на каждом шаге мы берем вектор параметров w, и генерируем популяцию, например из 100 чуть отличающихся векторов w1… w100, прибавляя гауссовский шум. Затем оцениваем каждый из 100 кандидатов независимо путем запуска агента в своем мире в течение некоторого времени, и складываем значения вознаграждения в каждом случае. Тогда обновленный вектор параметров равен взвешенной сумме всех 100 векторов, где весовые коэффициенты пропорциональны сумме вознаграждения (т.е. более успешные кандидаты получают более высокий вес). Математически это эквивалентно оценке градиента ожидаемого вознаграждения в пространстве параметров, только мы делаем оценку лишь по 100 случайно выбранным направлениям.

Пример кода


Для конкретизации алгоритма, посмотрите на короткий пример оптимизации квадратической функции с помощью ЭС.

# simple example: minimize a quadratic around some solution point
import numpy as np  
solution = np.array([0.5, 0.1, -0.3])  
def f(w): return -np.sum((w - solution)**2)

npop = 50      # population size  
sigma = 0.1    # noise standard deviation  
alpha = 0.001  # learning rate  
w = np.random.randn(3) # initial guess  
for i in range(300):  
  N = np.random.randn(npop, 3)
  R = np.zeros(npop)
  for j in range(npop):
    w_try = w + sigma*N[j]
    R[j] = f(w_try)
  A = (R - np.mean(R)) / np.std(R)
  w = w + alpha/(npop*sigma) * np.dot(N.T, A)

Внедрение шума в параметры


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

Сравнение обучения с подкреплением и эволюционной стратегии


Некоторые преимущества ЭС над ОП:

  • Не требуется обратное распространение. В ЭС есть только прямое распространение политики, что делает код проще и выполняется в 2-3 раза быстрее. В случае ограниченной памяти также нет необходимости хранить эпизоды для будущего обновления. Нет также проблемы взрывного роста градиентов, характерной для реккурентных сетей. Наконец, можно исследовать более широкий класс функций политики, например дифференцируемых (таких как двоичные сети) или содержащих сложные модули (поиск пути или разнообразные оптимизации).

  • Высокая степень параллелизма. В ЭС требуется лишь незначительный обмен данных между процессами — скалярные данные о вознаграждении. В ОП требуется синхронизация полных векторов признаков (миллионы чисел). Поэтому в ЭС наблюдается линейный рост производительности по мере добавления вычислительных ядер.

  • Устойчивость к выбору гиперпараметров. ОП чувствителен к масштабу, например при обучении для Atari мы наблюдали даже провалы в зависимости от выбора частоты кадров. ЭС в этом эксперименте практически нечувствителен к частоте кадров игры.

  • Структурированное исследование. Некоторые алгоритмы ОП приводят к тому, что агент обучается «дребезгу» в управлении. Например, в игре в теннис часто нужно непрерывно давить на кнопку «вверх» в течение нескольких тактов игры. Q-обучение преодолевает этот недостаток ОП, и ЭС не страдает этим недостатком за счет использования детерминированной политики.

  • Горизонт планирования шире. Анализ ЭС и ОП показал, что ЭС более предпочтителен когда количество тактов времени в эпизоде большое, т.к. действия придают более длительный эффект. Например, в игре Seaquest агент успешно обучается тому, что подводная лодка должна всплывать, когда уровень кислорода повышается.

ЭС также несвободна от недостатков. На практике, случайный шум в пространстве параметров должен приводить к различающимся результатам, чтобы сформировался обучающий сигнал. Например, в игре Montezuma’s Revenge практически невозможно получить ключ на первом уровне с помощью случайной сети, в то время, как это становится возможным при случайных действиях.

Подробное описание экспериментов и сравнение с лучшими алгоритмами ОП приведены в статье Evolution Strategies as a Scalable Alternative to Reinforcement Learning.

Исходный код опубликован на гитхабе.
В предложении «Исходный код опубликован на гитхабе» где правильнее поставить гиперссылку на репозиторий?

Проголосовало 63 человека. Воздержалось 16 человек.

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

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330342/


Метки:  

Как не дать алгоритму продать банк

Вторник, 06 Июня 2017 г. 14:38 + в цитатник
Привет, Хабр! Наша команда в Москве занимается разработкой внутренней алгоритмической торговой платформы. Сегодня нам бы хотелось рассказать о механизмах, которые мы добавляем в нашу архитектуру для защиты от возможных сбоев.

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

Три года назад у всех была на слуху история о Knight Capital Group. В результате «успешного» обновления их системы они потеряли около 460 миллионов долларов из-за того, что их торговая система выставила и купила 397 миллионов акций разных компаний по нерыночным ценам.  Отчет о расследовании данного события должен, наверное, лежать на столе каждого COO любой финансовой компании — как напоминание, к чему может привести недостаточный уровень технического развития процессов в компании и отсутствия автоматических систем защиты.

Архитектура любой торговой системы должна иметь в том или ином виде подсистему для контроля финансовых рисков от торговли. Случай с KCG на нашем внутреннем жаргоне можно классифицировать как «вышедшая из-под контроля стратегия». При проектировании нужно понимать, что это только одна из возможностей, которая может случиться с вашей системой. Кроме технологических рисков, существует, конечно, еще большой набор различных «человеческих ошибок», которые могут стать следствием невнимательности или быть преднамеренными, вызванными желанием личного обогащения у людей, которые будут пользоваться вашей системой. Но в данной статье мы хотим только обсудить возможные механизмы защиты против технических рисков, связанных со случаями, когда алгоритм выходит из-под контроля и ведет себя не так, как задумано.

В нашей платформе торговые стратегии (или, по-другому, торговые алгоритмы) запускаются в рамках некоторого контейнера. В контейнере находятся 'circuit breaker' компоненты, которые стоят на пути от торгового алгоритма к внешнему миру. Ближайшая аналогия из физического мира — это «плавкие предохранители». Основная цель этих 'circuit breaker' - принимать автоматическое решение об отключении стратегии в случае срабатывания правил, которые в них заложены. У них есть два состояния: «замкнутое» — проводят все сообщения между стратегией и внешним миром, и «разомкнутое» — когда они блокируют любые новые заявки (aka ордера) от стратегии на биржу. При этом они в любом состоянии всегда передают сообщения от биржи внутрь стратегии.


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

Контейнер, в котором запускается алгоритм, должен гарантировать, что стратегия не сможет обойти эту защиту. Можно еще добавить из практики, что разработкой стратегий и 'circuit breaker' компонентов должны заниматься разные команды.

Каждый 'circuit breaker' — это некое простое правило, которое должно ограничивать свободу действий контролируемой стратегии. Типичное правило может звучать так: «стратегия может послать не более 100 ордеров на рынок за все время». Как только стратегия попробует послать на рынок 101 ордер, 'circuit breaker' перейдет в разомкнутое состояние и перестанет передавать новые ордера от стратегии дальше на рынок.

Как только срабатывает любое правило, запускается следующая цепочка событий: а) стратегия получает сообщение о том, что 'circuit breaker' перешел в открытое состояние и она обязана завершить свою работу; б) удалятся все активные ордера с рынков, которые были поставлены этой стратегией; с) трейдер получает уведомление на свой торговый терминал об ошибке в алго-стратегии и ее принудительной остановке; д) такое же сообщение получает команда поддержки, которая должна незамедлительно начать расследование произошедшего.

Давайте посмотрим, какие, на наш взгляд, 'circuit breakers' должны присутствовать в любой торговой системе:

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

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

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

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

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

  • Too good to be true — иногда алгоритм может пытаться купить или продать инструмент по цене, которая ну слишком хороша, чтобы быть реальной. Обычно для реализации таких проверок у вас должен быть источник цен, которые вы примете за средние для торговли данного актива на рынке. В случае, если стратегия пытается купить/продать актив по ценам, которые выходят за рамки обозначенного вами коридора, это снова значит, что происходит что-то подозрительное и нужно остановить торговлю до момента, когда вы сможете однозначно сказать, чем это вызвано.

  • Fat fingers — данная проверка ограничивает размер ордера, который стратегия может выставить в одном распоряжении за один раз на рынок. Проверка скорее предназначена для защиты от трейдеров, если они запустят стратегию с какими-то очень большими распоряжениями на покупку или продажу активов.

  • Dead-man switch — любые алгоритмы запускается трейдерами, которые и несут в конечном итоге ответственность за финансовый результат. Главное правило заключается в том, что за алгоритмом всегда должен наблюдать человек, следить за открытой позицией, финансовым результатом. Он принимает решение о том, что алгоритм работает в рамках заданной программы или что-то идет не так. Данная проверка призвана скорее бороться с человеческой небрежностью или забывчивостью, результатом которых могут стать большие финансовые потери для вашего банка. В нашем случае, если трейдер не совершает никаких активных действий на компьютере (нажатия клавиатуры, мыши) длительное время, выводится окошко с предупреждением. Если он не реагирует, то UI закрывает активные соединения с алго-контейнером. И алго-контейнер, уже видя, что сессия с UI закрылась, останавливает свои стратегии, которые были связанны с данной сессией (в алго-контейнере могут быть запущены стратегии от нескольких разных трейдеров).

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

Также важно еще раз отметить, что наличие 'circuit breaker' в вашей системе не гарантирует отсутствия проблем. Это только одна из линий обороны, которые вы должны построить внутри вашей торговой платформы. Ошибки могут прокрасться и внутрь алго-контейнера и 'circuit breaker' компонентов. О том, как мы боремся с техническими рисками данных возможных ошибок, мы расскажем в следующих статьях, если вас заинтересовала эта.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330008/


Метки:  

Телефония в офис за палку колбасы

Вторник, 06 Июня 2017 г. 14:29 + в цитатник


Многие представители бизнеса еще живут в предрассудках, мол телефония для офиса — это дорого. Мы хотим избавить от разочарований и показать пример, как можно телефонизировать свой офис любых размеров: подключить облачную АТС, да еще и привязать телефонию к бесплатной CRM-системе и тратить на всё про всё 300-500 рублей в месяц. Кстати палку сырокопченой колбасы за такие деньги найти очень сложно.

Еще раз про облачную АТС


Быстро пробежимся по теории. Облачная АТС — альтернатива физической офисной телефонной станции, то есть нужное оборудование находится у оператора, а клиент получает все услуги посредством интернета. Удивительно, но по своим возможностям виртуальная АТС не уступает аппаратной, все под боком и настраивается за считанные минуты. Объясняем работу АТС посредством простой схемы.



Настраиваем АТС


Если уж заговорили про колбасу, то возьмем пример небольшой рязанской фермы.
Итак, руководитель рязанской фермы Максим Краснов на первых этапах бизнеса решил разобраться с настройкой облачной АТС Zadarma лично. Он зарегистрировался на сайте и купил прямой телефонный номер в Рязани, после этого он описал задачу телефонии и принялся настраивать АТС. Задача следующая: создать внутренние номера (для него, бухгалтера, технолога и секретаря), добавить голосовое меню, настроить сценарии звонков, принимать звонки только в рабочее время.

В личном кабинете Максим включил АТС и перешел в мастер настройки.
  • Создание внутренних номеров АТС — Для поставленной задачи Максиму нужно три внутренних номера, 101 для него, 102 для бухгалтера, 103 для технолога, 104 автоответчик для нерабочего времени
  • Голосовое меню-приветствие (приветствие можно набрать текстом, а можно загрузить аудио-файлом, Максим не стал тратить время и просто набрал буквы в нужной строке, система же сама начитала текст. “Здравствуйте, вас приветствует животноводческая ферма. По вопросам партнерства и оптовых продаж нажмите кнопку 1, для связи с финансовым отделом нажмите кнопку 2, для связи с отделом технологии производства нажмите 3”
  • Сценарии обработки входящих звонков — В этом разделе можно создать пункты, которые используются в голосовом меню. Максим выбирает нужные сценарии: Без нажатия — секретарь, Кнопка 1 — Максим Краснов, Кнопка 2 — Отдел бухгалтерии, Кнопка 3 — Главный технолог Фермы)
  • Настройка входящих звонков — В этом пункте Максим задает непосредственно сами сценарии — на какие внутренние линии будут приходить звонки, и в какой очередности. Например, если он не берет телефон в течение 15 секунд, звонок переводится на секретаря.




На этом этапе настройка АТС успешно завершена (у Максима ушло на первую настройку АТС Zadarma — 8 минут). Чтобы купленный рязанский номер телефона отображался у абонента, нужно установить рязанский номер в качестве CallerID. CallerID — это номер, который определится при звонке. Так как рязанский номер — первый, который купил Максим и других не подтверждал, он автоматически установился в качестве CallerID. Далее CallerID можно менять в настройках АТС, выбирая из купленных/подтвержденных номеров.

В каждый кабинет звонки приходят на IP-телефоны, сам же Максим принимает вызовы на мобильный через приложение, так как все время находится в разъездах и вне офиса. Если вдруг он оказывается вне интернета, то звонок переадресуется на его мобильный номер (условная переадресация настраивается в разделе Моя АТС-внутренние номера)

Московское представительство


В начале 2017 года дела у Максима пошли в гору, объем производства увеличился и ферма открыла для себя новые горизонты — решила открыть московское представительство, только открывать физический офис на первых этапах оказалось делом затратным. Ферма нашла опытного сотрудника с автомобилем, добавили на главный сайт словосочетание “Представительство в Москве” и номер телефона. Теперь в московский “офис” можно звонить напрямую или просить чтобы вас переключили рязанские коллеги. Менеджер принимает звонки из дома или в пути прямо на свой мобильный, а дистрибьюторы и будущие партнеры не видят никакого подвоха (да какая вообще им разница). Кроме того, чтобы не хранить данные о клиентах и партнерах в экселевской табличке, бизнес решает перейти совсем на серьезный уровень и обзавестись CRM-системой.
Для новой задачи Максим подключает московский номер, и расширяет созданные ранее сценарии. Теперь для того, чтобы выйти на московского менеджера в голосовом меню нужно нажать кнопку 5. Причем на сайте можно найти и прямой московский номер, по которому менеджер в Москве примет звонок напрямую.



Имея два разных офиса можно привязать два разных голосовых меню к каждому телефонному номеру и настроить календарь работы офисов в виртуальной АТС по-разному. Так и делает Максим, ведь его московский офис продаже на телефоне 9 часов в день (с 10 утра до 19.00), в то время как рязанская ферма работает и принимает звонки с 7 утра до 5 вечера.

Интеграция с СRМ


Словосочетание “Интеграция с СRМ-системой” пугает только новичков. Связка облачной АТС с СRМ-системой происходит посредством нажатия двух (именно так) кнопок. Максим решает не откладывать дело в долгий ящик и выбирает CRM-сиcтему под свои потребности (для ознакомления Максим выбрал бесплатную версию Битрикс 24). В итоге интеграция АТС с CRM решает множество задач — московский менеджер звонит из CRM в один клик, при первом звонке клиента система создает карточку этого клиента, а Максим видит не только полную статистику звонков, но и может прослушать все разговоры опять же прямо из CRM-системы.



Бюджеты


В итоге, считаем бюджеты на телефонию рязанской фермы — абонентские платы за два номера — 330 рублей в месяц (120 рублей номер в Москве и 210 рублей номер в Рязани). Исходящую связь использует в первую очередь менеджер в Москве, в среднем он наговаривает 100 исходящих минут на стационарные номера Москвы и 70 минут на мобильные номера регионов. Максим выбрал стандартный тарифный план, в который включены бесплатные 100 минут на стационарные номера Москвы. Тарификация кстати посекундная. В итоге 70 минут на мобильные = 140 рублей (стоимость минуты на мобильные российские номера на тарифе “Стандарт” — 1,98 рубля, да вообще любой вызов по России обойдется не дороже 2 рублей за минуту).



Получаем = 330 + 140. За 470 рублей в месяц рязанская ферма (лишний раз отметим, что фирма рязанская, а охват российский) решила телефонный вопрос в компании и главное — она не заботится о качестве связи, о поддержке оборудования и не тратится на администратора, который за всем следит. Плюс в любой момент ферма может расширить свою географию (даже выйти на мировой рынок) и это не встанет в “копеечку”.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329092/


15 лучших рецептов для Умного Дома с ioBroker

Вторник, 06 Июня 2017 г. 14:18 + в цитатник
ioBroker — это конструктор с помощью которого можно собрать свой Умный Дом.



Но ведь каждому нужно что-то своё, и у каждого разные предпосылки и возможности, бюджет, доступное свободное время на планирование и реализацию, вкусы и предпочтения. Равнодушному к процессу автоматизирования соседу, но ценящему комфорт, скорость и дизайн элитных приборов — это одно, а увлеченному автоматизацией и экспериментами, другое.
ioBroker — это универсальный конструктор, позволяющий реализовать самые сумасшедшие и невероятные идеи в области Домашней Автоматизации.
Для большей наглядности, приведу Вам 15 лучших рецептов из “Кулинарной книги” от ioBroker
Мои любимые рецепты, в которых речь идёт о коммуникации между приборами, когда они свободно общаются между собой, обмениваясь данными и информацией о своём текущем состоянии, передают друг другу команды, выполняют сложные сценарии. Вобщем речь идёт об автоматизации, о которой мы знаем в основном из промышленного производства.

  1. Электический подогрев полов в ванной автоматически включается в 6 часов.
  2. Жалюзи на окнах считывают информацию из календаря о времени восхода солнца и именно тогда открываются, пока хозяин еще мирно спит в кровати.
  3. Просыпаемся, встаём, идем по коридору, свет автоматически включается. Одновременно сенсор движения сообщает эту информацию чайнику и кофеварке.
  4. Коферка включается, чайник начинает кипятить воду. Включается музыка или телевизор, а также определенная сцена для освещения, которую мы сами предварительно настроили и назвали “Доброе утро”
  5. Пока мы чистим зубы, варится кофе, потом, зайдя на кухню, нас уже будет ожидать свежесваренный кофе или чай.
  6. В ванной мы спрашиваем Alexa или Siri об актуальной погоде, пробках на дорогах, или ценах на бензин, или на акции, или диктуем ей список продуктов, или просим ее найти наш потерянный мобильник, рассказать анекдот, заставить самоуничтожиться, предложить рецерты на ужин
  7. Просим Алеху соединить нас по скайпу с мамой. Про Алексу будет отдельная книга.
  8. С помощью Алексы мы можем полностью управлять домом одним только голосом: включать, выключать, убавлять свет, открывать и закрывать окна, включать и выключать термостаты, музыку итд. Это очень удобно, если готовишь еду и руки заняты.
  9. Выходя из дома, важно нажать одну единственную кнопку, и Умный Дом выключит везде свет, отключит приборы, убавит отопление, выключит музыку, телевизор и сообщит о том, что вы забыли закрыть окна или внутреннюю дверь в сад.
  10. Умный Дом вышлет сообщение с фото в телеграмм о том, кто и во сколько ушел, пришел, звонил в дверь. Очень удобно, если приходит уборщица, или соседка полить цветы, за котом наблюдать, за детьми, которые ушли в школу или вернулись из школы с толпой друзей и готовы разнести квартиру.
  11. Если кто-то забыл ключ, то можно дистанционно открыть дверь. Если кто-то забыл закрыть дверь, то Умный Дом обязательно свяжется с вами или соседями, чтобы они проконтроллировали ситуацию.
  12. Естественно о любой, непредусмотренной регламентом активности в доме, Умный Дом сразу будет сообщать удобным способом. Может напугать грабителя громкой сиреной и яркокрасным мигающим освещением, заставляя покинуть помещение и вызывая полицию.
  13. Когда семья уезжает в отпуск, Умный Дом симулирует присутствие человека в доме, поэтому грабителям невозмодно понять, что он пустой.
  14. Можно из отпуска наблюдать за любимым цветком в горшке, если установить туда сенсор, который будет сообщать об освещенности, составе почвы и влажности.
  15. Перед сном, за час, всё освещение в доме убавляется и переключается на цвета заката, чтобы организм настраивался на сон. Уже лежа в постели можно попросить Алексу поставить будильник на 6 часов и выключить все приборы в доме, не вставая с кровати.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330332/


Yii 2.0.12

Вторник, 06 Июня 2017 г. 14:01 + в цитатник

Вышла версия 2.0.12 PHP фреймворка Yii. Инструкции по установке и обновлению ищите на странице
http://www.yiiframework.com/download/.



Версия 2.0.12 является минорным релизом Yii 2.0. Она включает в себя более сотни улучшений и исправлений.


В релиз вошли несколько изменений, которые могут повлиять на существующие приложения. Эти изменений описаны в UPGRADE.md file.


Спасибо сообществу Yii за поддержку проекта!


За разработкой фреймворка можно следить поставив звёздочку на GitHub. Также можно подписаться на Twitter и Facebook.


Данный релиз задержался так как команда была занятна дргими вещами. Например, мы работаем над новым сайтом и YiiConf
— конференции по Yii
, которая пройдёт совсем скоро в Москве.


Так как Yii 2.1 уже разрабатывается, убедитесь, что версия в вашем composer.jsonпрописана как ~2.0.12, а не >= или *. Так при релизе 2.1 ваш проект точно не сломается.


Ниже мы рассмотрим самые интересные изменения релиза. Полный список можно посмотреть в CHANGELOG.


Тесты


Покрытие тестами очень важно для своевременного обнаружения проблем.
К релизу @vladis84, @boboldehampsink, @Kolyunya и
другие члены сообщества Yii помогли нам расширить покрытие кода.


@schmunk42 настроил дополнительное тестирование на базе docker и развернул его в GitLab. Некоторые тесты там всё ещё падают. Главным образом из за отличий в данных для интернационализации. Это будет исправлено немного позже.


Базы данных


Слой работы с базами получил несколько улучшений в работе с выражениями. Теперь из можно использовать в \yii\db\QueryTrait::limit(), \yii\db\QueryTrait::offset() и \yii\data\Sort.


MSSQL


Поддержка MSSQL существенно улучшилась. Значительно возросла скорость чтения схемы и был реализован метод yii\db\mssql\QueryBuilder::resetSequence().


Безопасность


  • yii\base\Security::hkdf() был улушен. Теперь, если это возможно, используется hash_hkdf() из PHP >= 7.1.2.
  • В yii\captcha\CaptchaAction теперь используется mt_rand() вместо rand() .

Юзабилити


Шаблон миграций теперь по умолчанию использует safeUp() и safeDown(). В том случае, когда изменения схемы в транзакции не поддерживаются (например, MySQL), изменения применяются без транзакций.


Различные компоненты фреймворка обзавелись значениями по умолчанию:


  • \yii\data\SqlDataProvider теперь считаем записи самостоятельно в том случае, когда totalCount не указан.
  • Провайдеры данных автоматически выставляют ID. Больше нет необходимости указывать его для случая когда несколько провайдеров с постраничной разбивкой используется на одной странице.
  • Фильтр для yii\grid\DataColumn автоматически генерится как выпадающий список в том случае, если format выставлен в boolean.

Команда yii cache начала предупреждать о том, что она не может очистить кеш APC из консоли.


yii\filters\AccessRule теперь позволяет передать параметры в функцию проверки роли.


Производительность


  • В yii\web\UrlManager добавлена поддержка кеширования вызовов yii\web\UrlRule::createUrl() в случае использования правил с умолчаниями.
  • В DB command Добавлена опция для отключения логирования и профайлинга.
  • yii\data\ActiveDataProvider не делает запросы в том случае, когда количество моделей равно нулю.

Всякое


StringHelper научился работать с URL-безопасным base64 через методы encode()/decode(). Это может быть полезно для различных токенов.


yii\helpers\Html::img() теперь позволяет указать srcset:


[php]
echo Html::img('/base-url', [
    'srcset' => [
        '100w' => '/example-100w',
        '500w' => '/example-500w',
        '1500w' => '/example-1500w',
    ],
]);

У yii\widgets\LinkPager можно рендерить кнопку текущей страницы как disabled. Для этого необходимо выставить disableCurrentPageButton в true.


Контроль доступа и валидаторы стали требовать меньше зависимостей:


  • yii\filters\AccessControl теперь может использоваться без компонента user.
  • Валидаторы больше не требуют Yii::$app.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330324/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 995 994 [993] 992 991 ..
.. 1 Календарь