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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

Лог файлы Linux по порядку

Пятница, 07 Июля 2017 г. 13:40 + в цитатник

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





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


Основные лог файлы


Все файлы журналов, можно отнести к одной из следующих категорий:


  • приложения;
  • события;
  • службы;
  • системный.

Большинство же лог файлов содержится в директории /var/log.


  • /var/log/syslog или /var/log/messages содержит глобальный системный журнал, в котором пишутся сообщения с момента запуска системы, от ядра Linux, различных служб, обнаруженных устройствах, сетевых интерфейсов и много другого.
  • /var/log/auth.log или /var/log/secure — информация об авторизации пользователей, включая удачные и неудачные попытки входа в систему, а также задействованные механизмы аутентификации.
  • /var/log/dmesg — драйвера устройств. Одноименной командой можно просмотреть вывод содержимого файла. Размер журнала ограничен, когда файл достигнет своего предела, старые сообщения будут перезаписаны более новыми. Задав ключ --level= можно отфильтровать вывод по критерию значимости.

Поддерживаемые уровни журналирования (приоритеты):
   emerg - система неиспользуемая
   alert - действие должно быть произведено немедленно
    crit - условия критичности
     err - условия ошибок
    warn - условия предупреждений
  notice - обычные, но значимые условия
    info - информационный
   debug - отладочные сообщения

(5:520)$ dmesg -l err
[1131424.604352] usb 1-1.1: 2:1: cannot get freq at ep 0x1
[1131424.666013] usb 1-1.1: 1:1: cannot get freq at ep 0x81
[1131424.749378] usb 1-1.1: 1:1: cannot get freq at ep 0x81

  • /var/log/alternatives.log — Вывод программы update-alternatives, в котором находятся символические ссылки на команды или библиотеки по умолчанию.
  • /var/log/anaconda.log — Записи, зарегистрированные во время установки системы.
  • /var/log/audit — Записи, созданные службой аудита auditd.
  • /var/log/boot.log — Информация, которая пишется при загрузке операционной системы.
  • /var/log/cron — Отчет службы crond об исполняемых командах и сообщения от самих команд.
  • /var/log/cups — Все, что связано с печатью и принтерами.
  • /var/log/faillog — Неудачные попытки входа в систему. Очень полезно при проверке угроз в системе безопасности, хакерских атаках, попыток взлома методом перебора. Прочитать содержимое можно с помощью команды faillog.
  • var/log/kern.log — Журнал содержит сообщения от ядра и предупреждения, которые могут быть полезны при устранении ошибок пользовательских модулей встроенных в ядро.
  • /var/log/maillog/ или /var/log/mail.log — Журнал почтового сервера, используемого на ОС.
  • /var/log/pm-powersave.log — Сообщения службы экономии заряда батареи.
  • /var/log/samba/ — Логи файлового сервера Samba, который используется для доступа к общим папкам Windows и предоставления доступа пользователям Windows к общим папкам Linux.
  • /var/log/spooler — Для представителей старой школы, содержит сообщения USENET. Чаще всего бывает пустым и заброшенным.
  • /var/log/Xorg.0.log — Логи X сервера. Чаще всего бесполезны, но если в них есть строки начинающиеся с EE, то следует обратить на них внимание.

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


  • /var/log/yum.log — Для программ установленных с помощью Yum в RedHat Linux.
  • /var/log/emerge.log — Для ebuild-ов установленных из Portage с помощью emerge в Gentoo Linux.
  • /var/log/dpkg.log — Для программ установленных с помощью dpkg в Debian Linux и всем семействе родственных дистрибутивах.

И немного бинарных журналов учета пользовательских сессий.


  • /var/log/lastlog — Последняя сессия пользователей. Прочитать можно командой last.
  • /var/log/tallylog — Аудит неудачных попыток входа в систему. Вывод на экран с помощью утилиты pam_tally2.
  • /var/log/btmp — Еже один журнал записи неудачных попыток входа в систему. Просто так, на всякий случай, если вы еще не догадались где следует искать следы активности взломщиков.
  • /var/log/utmp — Список входов пользователей в систему на данный момент.
  • /var/log/wtmp — Еще один журнал записи входа пользователей в систему. Вывод на экран командой utmpdump.

(5:535)$ sudo utmpdump /var/log/wtmp
[5] [02187] [l0  ] [        ] [4.0.5-gentoo     ] [0.0.0.0     ] [Вт авг 11 16:50:07 2015]
[1] [00000] [~~  ] [shutdown] [4.0.5-gentoo     ] [0.0.0.0     ] [Вт авг 11 16:50:08 2015]
[2] [00000] [~~  ] [reboot  ] [3.18.12-gentoo   ] [0.0.0.0     ] [Вт авг 11 16:50:57 2015]
[8] [00368] [rc  ] [        ] [3.18.12-gentoo   ] [0.0.0.0     ] [Вт авг 11 16:50:57 2015]
[1] [20019] [~~  ] [runlevel] [3.18.12-gentoo   ] [0.0.0.0     ] [Вт авг 11 16:50:57 2015]

И другие журналы


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


  • /var/log/mysql/ — Лог базы данных MySQL.
  • /var/log/httpd/ или /var/log/apache2/ — Лог веб сервера Apache, журнал доступа находится в access_log, а ошибки — в error_log.
  • /var/log/lighthttpd/ — Лог веб сервера lighttpd.

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


  • ~/.xsession-errors — Вывод stderr графических приложений X11.

Initializing  "kcm_input" :  "kcminit_mouse"
Initializing  "kcm_access" :  "kcminit_access"
Initializing  "kcm_kgamma" :  "kcminit_kgamma"
QXcbConnection: XCB error: 3 (BadWindow), sequence: 181, resource id: 10486050, major code: 20 (GetProperty), minor code: 0
kf5.kcoreaddons.kaboutdata: Could not initialize the equivalent properties of Q*Application: no instance (yet) existing.
QXcbConnection: XCB error: 3 (BadWindow), sequence: 181, resource id: 10486050, major code: 20 (GetProperty), minor code: 0
Qt: Session management error: networkIdsList argument is NULL

  • ~/.xfce4-session.verbose-log — Сообщения рабочего стола XFCE4.

Чем просматривать — lnav


Почти все знают об утилите less и команде tail -f. Также для этих целей сгодится редактор vim и файловый менеджер Midnight Commander. У всех есть свои недостатки: less неважно обрабатывает журналы с длинными строками, принимая их за бинарники. Midnight Commander годится только для беглого просмотра, когда нет необходимости искать по сложному шаблону и переходить помногу взад и вперед между совпадениями. Редактор vim понимает и подсвечивает синтаксис множества форматов, но если журнал часто обновляется, то появляются отвлекающие внимания сообщения об изменениях в файле. Впрочем это легко можно обойти с помощью <:view /path/to/file>.


Недавно я обнаружил еще одну годную и многообещающую, но слегка еще сыроватую, утилиту — lnav, в расшифровке Log File Navigator.





Установка пакета как обычно одной командой.


$ aptitude install lnav #Debian/Ubuntu/LinuxMint
$ yum install lnav #RedHat/CentOS
$ dnf install lnav #Fedora
$ emerge -av lnav #Gentoo, нужно добавить в файл package.accept_keywords
$ yaourt -S lnav #Arch

Навигатор журналов lnav понимает ряд форматов файлов.


  • Access_log веб сервера.
  • CUPS page_log
  • Syslog
  • glog
  • dpkg.log
  • strace
  • Произвольные записи с временными отметками
  • gzip, bzip
  • Журнал VMWare ESXi/vCenter

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


(5:471)$ sudo lnav /var/log/pm-powersave.log /var/log/pm-suspend.log

Программа умеет напрямую открывать архивный файл.


(5:471)$ lnav -r /var/log/Xorg.0.log.old.gz

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


Mon May 02 20:25:00        123 normal         3 errors         0 warnings         0 marks
Mon May 02 22:40:00          2 normal         0 errors         0 warnings         0 marks
Mon May 02 23:25:00         10 normal         0 errors         0 warnings         0 marks
Tue May 03 07:25:00         96 normal         3 errors         0 warnings         0 marks
Tue May 03 23:50:00         10 normal         0 errors         0 warnings         0 marks
Wed May 04 07:40:00         96 normal         3 errors         0 warnings         0 marks
Wed May 04 08:30:00          2 normal         0 errors         0 warnings         0 marks
Wed May 04 10:40:00         10 normal         0 errors         0 warnings         0 marks
Wed May 04 11:50:00        126 normal         2 errors         1 warnings         0 marks

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


Использованные материалы


  1. lnav — An Advanced Log File viewer for Linux
  2. What Are Linux Logs? How to View Them, Most Important Directories, and More
  3. Как посмотреть логи в Linux
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332502/


Метки:  

Забронируйте ваше место на БИТ-пикнике HPE

Пятница, 07 Июля 2017 г. 13:23 + в цитатник
Согласны, погода не для пикников. Но наша встреча для ИТ-специалистов «БИТ-пикник» в Москве 11 июля точно пройдет при любом прогнозе. В программе – практические сессии с специалистами по продуктам, разбор реализованных решений и живые демо. Регистрация – до 10 июля, количество мест ограничено, подробности под катом.



На мероприятии ждем технических специалистов, которым будет интересно узнать о новых продуктах и решениях HPE и поучаствовать в практикумах. Среди них:
  • Системы хранения HPE 3PAR и технология HPE Nimble InfoSight
  • Онлайн-демонстрация быстрой настройки гостевой WiFi сети с СМС авторизацией с помощью облачной системы управления Aruba Central; подключение к облачной системе управления Aruba Central, регистрация точек доступа, настройка гостевого портала и параметров доступа, подключение клиентов к гостевой WiFi сети, сбор и анализ статистики.
  • Процессоры Intel и вычислительные технологии HPE
  • Гиперконвергентная система HPE SimpliVity 380: вычисления, хранение, бэкап, отказоустойчивость и много другое в одной системе.
  • Теория и практика использования компонуемой инфраструктуры HPE Synergy
  • HPE OneView — платформа управления серверной инфраструктурой.

В демо-зоне можно будет пообщаться с нашими специалистами и посмотреть на интересное железо – компонуемую инфраструктуру HPE Synergy, серверы HPE Moonshot, гиперконвергентные системы HPE SimpliVity.

Ознакомьтесь с полной программой и зарегистрируйтесь до 10 июля. Ждем вас!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332610/


Метки:  

Семинар «Облака и реальность: кейсы, грабли, хорошие новости», 13 июля, Санкт-Петербург

Пятница, 07 Июля 2017 г. 13:16 + в цитатник


Привет, Хабр! Мы готовим к запуску новый курс Университетов DataLine. На этот раз про наши знания в делах облачных. Первый семинар пройдет в Санкт-Петербурге 13 июля – для нас это двойная премьера :-)

На вводном семинаре курса расскажем про практику IaaS в России и в мире, поделимся лайфхаками в области миграции и поговорим об облаке будущего.

У нас осталось всего несколько мест, и мы будем рады видеть ИТ-директоров, инженеров и всех тех, кто занимается обслуживанием ИТ-инфраструктуры.

О чем поговорим:

  • Кому в облаках жить хорошо, а кому не очень: российская и мировая IaaS-практика в контексте размещения критичных для бизнеса систем и ИТ-сервисов.
  • Миграция в облако: типичные ошибки и лайфхаки.
  • Облако завтрашнего дня: наш взгляд на ключевые тренды в развитии технологий и сервиса в целом.

После семинара для всех участников вкусный фуршет.

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

https://habrahabr.ru/post/332612/


Метки:  

[Перевод] Как создать билборд-текстуру растительности в Unreal Engine 4

Пятница, 07 Июля 2017 г. 12:41 + в цитатник
В этой статье мы поговорим о том, как создать билборд-текстуру растительности в Unreal Engine 4. Такая растительность – это простой многократно размноженный четырехугольник, все копии которого всегда повернуты к камере. Я постараюсь привести доводы в пользу такого подхода, расскажу о потенциальных недостатках и отдельно затрону вопрос производительности.



Растительность в Unreal Engine 4


В Unreal Engine 4 по умолчанию есть встроенный инструмент для работы с растительностью под названием Foliage tool. Он добавляет клонированные статические меши (в более общем смысле слова – бесскелетные модели). Каждый ассет с растительностью можно добавить на карту тысячи раз с разными настройками поворота, расположения и т. д. для всех экземпляров.

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

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

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

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

Именно в этом случае на помощь приходят билборды.

Билборд это что-то из области рекламы?


Unreal Engine 4 в базовой комплектации поддерживает компонент Billboard Material Component. Он хорошо подходит для работы с единичными или немногочисленными мешами в уровне, как показано на примере выше. К сожалению, его нельзя использовать для инструмента Foliage tool, который поддерживает только размещение статических мешей. Чтобы использовать компонент Billboard Component, он должен находиться внутри класса Actor, который не поддерживается данным инструментом.

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

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

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

Важно оставить немного разнообразия: я создал 4 варианта одного дерева, чтобы модели не выглядели одинаково.



Подготовка материала


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

Перейдите в панель Content Browser, кликните правой кнопкой мышки и создайте новый Material.

Выберите следующие настройки:
  • Blend Mode: Masked;
  • Shading Model: Unlit;
  • галочка напротив параметра Two Sided.




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

Узел 'Custom' содержит внутри секции, отвечающей за эффекты билборда, специальный HLSL-код. Он нужен для вычисления правильного поворота четырехугольника. Параметры этого узла выглядят так: напротив 'Inputs' нужно выбрать одно значение и назвать его 'In', а напротив ‘Output Type’ – CMOT Float 2. В документации это описано иначе, но там неправильные названия параметров:

float2 output;
output = atan2 (In.y,In.x);
return (output);


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

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

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



Определив материал, загрузим в Unreal Engine 4 простой прямоугольник, который будет использоваться как статический меш для Foliage tool.

Создание и загрузка меша


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

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

Я использовал для четырехугольника следующие настройки:

  • Roll: 270 градусов.
  • Pitch: 180 градусов.
  • Yaw: 0 градусов.
  • Import Uniform Scale: Настройте в соответствии с размером вашей карты, сам по себе четырехугольник достаточно большой.
  • Import translation, Z axis: Настройте в соответствии с ландшафтом. Я выставил на 190 единиц.


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

Теоретически мы уже могли бы поместить четырехугольник на карту и убедиться, что при движении камеры он всегда повернут к зрителю. Но разумнее будет перетащить этот статический меш в Foliage tool и поработать над его размещением:



Добавляя меш в Foliage tool, убедитесь, что опции Align to Normal и Random Yaw отключены: они поворачивают меш и нарушают эффект материала.

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

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



Внешний вид


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

Ниже приведены для сравнения деревья с тенью и освещением и простые неосвещенные билборды:



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



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


Поскольку мы рисуем только 2 треугольника для каждого дерева, производительность при таком подходе более чем приемлемая для современных компьютеров. Мне удалось заполнить деревьями всю карту без заметного снижения производительности средней видеокарты (AMD R9 270X). Метод также отлично подходит для работы с тростником, травой или другими мелкими растениями. Игрок не заметит, что они плоские, даже если подойдет ближе.

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

Правда, производительность в данном случае неидеальна. Узел 'Custom', который мы используем для материала, не позволяет движку оптимизировать шейдер. Сейчас это не играет роли, но у вас может быть по-другому. Если сомневаетесь, воспользуйтесь профайлером.

Альтернативы


Есть и другой подход – применять низкополигональные LOD-цепочки, которые генерируются с помощью таких инструментов, как Simplygon или Meshlab. В качестве растительности можно также использовать импостеры. А еще лучше совместить 3 подхода, используя высокополигональную модель дерева (например, с speedtree.com) и наименее детализированную модель в вашей LOD-цепочке. Так вы экономите ресурсы. Когда дерево находится далеко, оно не отличается от плоского спрайта по части детализации и теней. Поэтому необязательно прорисовывать его полностью.

Вывод


Надеюсь, эта статья принесет пользу вашей игре и позволит не тратить целое состояние на дорогостоящие видеокарты. Есть много способов рендерить растительность, и это только один из них.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332608/


Метки:  

Тюнинг типовых ролей Windows. Часть первая: Файлы и печать

Пятница, 07 Июля 2017 г. 12:01 + в цитатник


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


Общие рекомендации по железу


Процессор - он как сердце сервера, поэтому от него зависит очень много в плане производительности. Благодаря маркетологам мы знаем - чем больше ядер и мегагерцев, тем круче. На самом деле всё не совсем так:


  1. Выбирайте 64-битный процессор. Современные серверные Windows не поддерживают 32-битные процессоры, да и памяти он может адресовать намного больше.


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


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


  4. Кэш процессора. Тут все просто: чем он больше, тем лучше, и часто больший кэш дает большую производительность, чем частота процессора.


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


  6. Для Hyper-V важно, чтобы процессор поддерживал SPLAT (Second Level Address Translation). В терминологии Intel возможность называется Extended Page Tables (EPT), у AMD - Nested Page Tables (NPT). Проверить наличие этой функции процессора можно с помощью утилиты systeminfo.exe.


Проверка процессора под требования Hyper-V.


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


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


  • лучше не хранить файл подкачки на отказоустойчивом массиве вроде RAID1- он проигрывает по скорости одному диску. Хорошей идеей будет поместить файл подкачки на RAID0 или несколько файлов подкачки на разных физических дисках.


Размещение файла подкачки на системном диске - не лучший вариант.


Теперь о сетевых адаптерах. Из интересных особенностей можно отметить:


  1. Только адаптеры с поддержкой 64-разрядных систем имеют DMA (Direct Memory Access) - технологию прямого доступа к памяти по сети. Если нужна действительно быстрая сеть между нодами кластера - на это стоит обратить внимание.


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


HPE ProLiant DL360 Gen7 обладает изначально четырьмя сетевыми портами.


На этом закончу небольшую вводную и перейду непосредственно к оптимизации ролей сервера. Начнем с самого простого - с файлового сервера.


Файловый сервер


Обычно при установке и работе файлового сервера вопрос быстродействия не стоит. Но только до тех пор, пока на обычной файлопомойке на заводятся базы данных, чудовищные файлы Excel и им подобные «интересные» вещи. Расскажу про параметры, которые могут улучшить или ухудшить быстродействие SMB.


Отдельно отмечу вопрос быстродействия сервера, который обрабатывает не только клиентов внутри локальной сети, но и удаленных - например, по VPN. Лично я сталкивался с ситуацией, когда в сети на Windows XP\2003 начали появляться компьютеры на Windows 7\2008. Тогда мы столкнулись с тем, что быстродействие сети новых компьютеров оставляет желать лучшего при общении со старыми ОС. Начитавшись интернетов, выполнили на новых машинах следующий скрипт:


netsh int tcp set global autotuning=disabled

netsh int tcp set global autotuninglevel=disabled

netsh int tcp set global rss=disabled chimney=disabled

Сеть заработала, скрипт был добавлен в разворачиваемые образа систем.


И все было хорошо, пока в сети не появился удаленный сегмент с повышенным требованием к скорости работы сети. Файлы передавались по VPN не быстрее 2 Мб/с. Проблему локализовали: оказалось, что специально для работы в LAN\WAN сетях в новых операционных системах добавили функцию autotuning. С помощью нее системы определяют скорость соединения и договариваются о размерах кадра TCP для оптимального быстродействия. Чтобы VPN работала быстро, и сервера не тормозили при обращениях к WIndows 2003, достаточно было не отключать autotuning, а ограничить его командой:


netsh int tcp set global autotuninglevel=highlyrestricted

Но перейдем к более специализированным параметрам.


Помним, что изменения параметров реестра и настроек служб могут привести к чему угодно. Поэтому делаем все аккуратно.


Начнем с тюнинга клиентов файловых серверов. За подключение к серверу SMB отвечает служба LanmanWorkstation. Большинство параметров находятся в следующей ветке реестра:


HKLM\System\CurrentControlSet\Services\LanmanWorkstation\Parameters

В большинстве своем параметры имеют тип REG_DWORD. В современных Windows управление частью настроек возможно через командлет Set-SmbClientConfiguration. Просмотреть текущие значения - соответственно, Get-SmbClientConfiguration.



Значения параметров клиента SMB.


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


Имя параметра Значение по умолчанию Варианты значений За что отвечает Комментарий
DisableBandwidthThrottling 0 0-1 Включение - отключение троттлинга для сетей с высокой задержкой Включение параметра может повысить пропускную способность сетей с высокой задержкой (WAN)
FileInfoCacheEntriesMax 64 1-65536 Максимальное количество значений в кэше метаданных файлов Увеличение параметра уменьшает трафик и повышает пропускную способность сети при обращении к большому количеству файлов
DirectoryCacheEntrySizeMax 64 1-65536 Максимальный размер кэша для каталогов Измеряется в килобайтах
FileNotFoundCacheEntriesMax 128 1-65536 Максимальное количество значений в кэше информации о файлах Увеличение параметра уменьшает трафик и повышает пропускную способность сети при обращении к большому количеству файлов
MaxCmds 50 1-65536 Максимальное количество команд в сеансе Увеличение параметра увеличит расход памяти, но поднимет быстродействие. Только для SMB v1
DormantFileLimit 1023 1-65536 Максимальное количество файлов, которые могут быть открыты, после того как «отпущены» приложением
ScavengerTimeLimit 10 0-127 Как часто запускается «мусорщик», очищающий кэш дескрипторов файлов Измеряется в секундах, актуально для Windows XP\2003

В качестве примера тюнинга, можно привести следующие значения:


  • DisableBandwidthThrottling = 1;


  • FileInfoCacheEntriesMax = 32768;


  • DirectoryCacheEntriesMax = 4096;


  • FileNotFoundCacheEntriesMax = 32768;


  • MaxCmds = 32768;


  • DormantFileLimit = 32768;


  • ScavengerTimeLimit = 60.

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


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

Параметры, настраиваемые через powershell и реестр:


Имя параметра Значение по умолчанию Варианты значений За что отвечает Комментарий
ConnectionCountPerNetworkInterface 1 1-16 Максимальное количество подключений к серверу с интерфейсом без поддержки RSS MS не рекомендует изменять значение по умолчанию
ConnectionCountPerRssNetworkInterface 4 1-16 Максимальное количество подключений к серверу с интерфейсом c поддержкой RSS
ConnectionCountPerRdmaNetworkInterface 2 1-16 Максимальное количество подключений к серверу с интерфейсом с поддержкой RDMA
MaximumConnectionCountPerServer 32 1-64 Максимальное количество подключений к одному серверу
DormantDirectoryTimeout 600 Максимальное количество времени обработки каталога Измеряется в секундах
FileInfoCacheLifetime 10 Время хранения информации о файле в кэше
DirectoryCacheLifetime 10 Время хранения метаданных каталога в кэше
FileNotFoundCacheLifetime 5 Время хранения кэша не найденных файлов
CacheFileTimeout 10 Время хранения кэша для файла, после того как файл «отпущен» приложением
DisableLargeMtu 0 (Win8) 0-1 Включение-отключение большого размера MTU С включенным параметром размер запроса ограничен 64 КБ, с включенным - 1 МБ.
RequireSecuritySignature 0 0-1 Включение-отключение обязательной подписи SMB Включение этого параметра замедляет скорость работы, но повышает защиту от атаки MITM
DirectoryCacheEntriesMax 16 1-4096 Максимальное количество значений в кэше информации о каталогах Увеличение параметра уменьшает трафик и повышает пропускную способность сети при обращении к большим каталогам
MaxCredits 128 Максимальное количество команд в сеансе Тоже самое, что и MaxCmds, но для SMB v2

Параметры, настраиваемые через powershell:


EnableMultiChannel 1 0-1 Включение-отключение использования нескольких физических адаптеров
EnableByteRangeLockingOnReadOnlyFiles True True\False Включение-отключение блокировки файлов «только для чтения»
EnableInsecureGuestLogons True True\False Включение-отключение гостевого входа на ресурс Отключение не позволит заходить без авторизации на расшаренные для всех папки на недоменном сервере (NAS)
EnableLoadBalanceScaleOut True True\False Включение-отключение поддержки распределения нагрузки при подключении к кластеру
EnableSecuritySignature True True\False Включение-отключение возможности подписи SMB
ExtendedSessionTimeout 1000 Время ожидания ответа от сервера Измеряется в секундах
KeepConn 600 Время до закрытия неактивной сессии Измеряется в секундах, применимо только к SMB v1
OplocksDisabled False True\False
Переключается автоматически в зависимости от значения параметра UseOpportunisticLocking
SessionTimeout 60 Время до закрытия неактивной сессии Измеряется в секундах
UseOpportunisticLocking True True\False Включение-отключение режима гибких блокировок (oplock) файлов с их буферизацией Включенный механизм сильно увеличивает быстродействие, но в ненадежных сетях может привести к повреждению файлов
WindowSizeThreshold 1 для серверных систем, 8 для клиентских Минимальный размер окна до включения режима Multichannel

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


  1. Для лучшего быстродействия не используйте ненужные функции вроде мини-фильтров файловой системы, IPSec, шифрование и сжатие NTFS, шифрование SMB и другие. Включение антивируса может существенно подпортить быстродействие, и если периметр сети защищен, лучше его и не устанавливать.


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


  3. Копирование файлов - довольно регулярная операция для файлового сервера. При копировании по сети предпочтительнее использовать утилиту robocopy.exe с ключом /mt, включающим многопоточность для большого количества мелких файлов. Немного быстродействия добавит и отсутствие вывода в консоль - ключ /log для robocopy и /q для xcopy.

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


Напомню, как их посмотреть.

Тут поможет утилита perfmon.exe. После запуска удобно переключить отображение в режим «отчет»:



Потом необходимо добавить нужные счетчики производительности. Для примера добавим счетчик «Общие ресурсы SMB сервера», нажав на зеленый плюс, выбрав нужный нам счетчик и общий ресурс:



И наслаждаемся результатом:



Более полно с процедурой использования счетчиков производительности, сбора и анализа результата рекомендую ознакомиться в блоге Microsoft.


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


HKLM\System\CurrentControlSet\Services\LanmanServer\Parameters.

Удобнее, конечно, использовать командлет Set-SmbServerConfiguration.



Вывод значений параметров с помощью командлета Get-SmbServerConfiguration.


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


Имя параметра Значение по умолчанию Тип параметра За что отвечает Комментарий
Smb2CreditsMax 8192 uint32 Максимальное количество команд SMB v2 Эти два параметра позволяют динамически распределять нагрузку. Иногда при использовании скоростных каналов с высокой задержкой (WAN) изменение этих параметров увеличит скорость. Посмотреть, есть ли проблемы, поможет счетчик производительности «Общие ресурсы SMBклиента - Задержек кредита/c»
Smb2CreditsMin 512 uint32 Минимальное количество команд SMB v2
MaxThreadsPerQueue 20 unit32 Максимальное количество потоков сервера при обработке одновременных запросов Увеличение параметра влияет на аппаратную загрузку, но увеличивает производительность. Показателем к изменению параметра может служить значение счетчика производительности «Рабочие очереди сервера - Длина очереди - SMB2 NonBlocking» становится больше 100.
AsynchronousCredits 512 uint32 Максимальное количество одновременных асинхронных команд в одной сессии В ряде случаев, например, при использовании нагруженного веб-сервера, увеличение значения параметра увеличивает производительность
MaxMpxCt 50 uint32 Максимальное количество невыполненных клиентских запросов для каждого клиента Влияет только на клиентов SMB v1

Существует еще один параметр реестра, не контролируемый командлетом powershell:


  • путь: HKLM\System\CurrentControlSet\Control\Session Manager\Executive;


  • параметр: REG_DWORD c именем AdditionalCriticalWorkerThreads;


  • значение по умолчанию: 0.

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


В качестве примера тюнинга можно привести следующие значения параметров:


  • AdditionalCriticalWorkerThreads = 64;


  • MaxThreadsPerQueue = 64;


  • MaxMpxCt = 32768.

Значения также должны подбираться индивидуально.


Про другие параметры предлагаю почитать под спойлером.
Имя параметра Значение по умолчанию Тип параметра За что отвечает Комментарий
AnnounceComment null string Представление сервера
AnnounceServer False boolean Включение - отключение представления сервера
AuditSmb1Access False boolean Включение - отключение аудита доступа по протоколу SMB v1 Параметр появился только в Windows 10\2016
AutoDisconnectTimeout 15 uint32 Время, после которого отключается неактивная сессия
AutoShareServer True boolean Включение - отключение сетевых ресурсов сервера по умолчанию
AutoShareWorkstation True boolean Включение - отключение сетевых ресурсов рабочей станции по умолчанию
CachedOpenLimit 10 uint3 Максимальное количество открытых файлов в кэше
DurableHandleV2TimeoutInSeconds 180 uint32 Время отключения неактивного дескриптора
EnableAuthenticateUserSharing False boolean Включение - отключение возможности общего доступа к соединению
EnableDownlevelTimewarp False boolean Включение - отключение низкоуровневого искажения времени
EnableForcedLogoff True boolean Включение - отключение принудительного выхода
EnableLeasing True boolean Включение - отключение аренды
EnableMultiChannel True boolean Включение - отключение использования нескольких физических адаптеров
EnableOplocks True boolean Включение - отключение гибких блокировок (oplock)
EnableSecuritySignature False boolean Включение - отключение возможности подписи SMB
EnableSMB1Protocol True boolean Включение - отключение протокола SMB v1
EnableSMB2Protocol True boolean Включение - отключение протокола SMB v2+
EnableStrictNameChecking True boolean Включение - отключение проверки имени входящего подключения
EncryptData False boolean Включение - отключение поддержки шифрования данных
IrpStackSize 15 unit32 Размер стека IRP (запросов ввода - вывода)
KeepAliveTime 2 unit32 Частота TCP запросов keepalive для подключения SMB
MaxChannelPerSession 32 unit32 Количество каналов в одной сессии
MaxMpxCount 50 unit32 Максимальное количество команд в сессии Параметр должен быть настроен так же, как и параметр MaxCmds клиента
MaxSessionPerConnection 16384 unit32 Максимальное количество сессий в одном соединении
MaxWorkItems 1 uint32 Максимальное количество рабочих элементов Параметр влияет только на SMB v1
NullSessionPipes null string Каналы, доступные в нулевой сессии
NullSessionShares null string Сетевые ресурсы, доступные в нулевой сессии
OplockBreakWait 35 uint32 Время ожидания до прерывания блокировки
PendingClientTimeoutInSeconds 120 uint32 Время ожидания клиента
RejectUnencryptedAccess True boolean Включение - отключение незашифрованных запросов на доступ
RequireSecuritySignature False boolean Включение - отключение обязательной подписи SMB Включение этого параметра замедляет скорость работы, но повышает защиту от атаки MITM
ServerHidden True boolean Включение - отключение представления сервера По умолчанию сервер не представляет себя
SmbServerNameHardeningLevel 0 uint32 Уровень упрощения имени сервера
TreatHostAsStableStorage False boolean Включение - отключение надежного дискового хранилища Включение этого параметра говорит серверу о надежности дискового хранилища, стоит включать его при работе с диском с энергонезависимым кэшем на запись. Тогда сервер не будет дожидаться подтверждения записи на диск, что ускорит быстродействие.
ValidateAliasNotCircular True boolean Включение - отключение использования псевдонимов
ValidateShareScope True boolean Включение - отключение проверки имени ресурсов при создании нового ресурса
ValidateShareScopeNotAliased True boolean Включение - отключение проверки псевдонимов ресурсов при создании нового ресурса
ValidateTargetName True boolean Включение - отключение проверки имени целевого ресурса при создании псевдонима

Повторюсь: изменение параметров может привести к неработоспособности сервера. Поэтому лучше сначала «потренироваться на кошках». Или хотя бы делать бэкапы.


Перейду к следующей, казалось бы, простой роли - сервер печати.


Сервер печати


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


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



Настройка размещения очереди печати.


По возможности лучше отрисовывать задачи на клиенте. В таком случае клиент будет сам переводить документ в специальный формат для печати (PDL). Сервер же не будет тратить ресурсы на это преобразование.


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


printui /Xs /n "printer" ClientSideRender disabled

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


Принтеры с поддержкой XPS (OpenXPS) меньше нагружают сервер, чем принтеры без нее. Принтеры с поддержкой PCL 6 и Postscript чуть менее эффективны из-за векторного формата. Поэтому при выборе принтера лучше подбирать с поддержкой XPS, и устанавливать соответствующий драйвер.


С выходом Windows 8\2012 появилась поддержка драйверов печати v4. Драйвера 4-й версии более производительны, но Windows 7 будет печатать на драйвере четвертого типа, отрисовывая задачи на клиенте. Поэтому если в сети еще встречаются старые Windows, стоит установить и драйвера третьего типа. Посмотреть на тип драйвера можно в свойствах сервера печати на вкладке «Драйверы»:



Окно установки дополнительных драйверов.


Если говорить о возможностях драйверов четвертого типа, то к ним можно отнести:


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


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

Заслуживает внимания и технология Branch Office. С ее помощью клиент работает с принтером напрямую, минуя какую-либо обработку на сервере печати. Правда, понадобятся принтеры с поддержкой TCP\IP или WSD. Подробнее ознакомиться с технологией можно на сайте Microsoft, а включить или отключить для конкретного принтера можно с помощью командлета powershell:


Set-Printer -name  -ComputerName  -RenderingMode BranchOffice

Технология не работает, если используется обработка печати на сервере.


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


  • Spoolsv.exe;


  • Printfilterpipelinesvc.exe;


  • Printisolationhost.exe;

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



Набор типовых счетчиков производительности подсистемы печати.


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

В общем, подобрав параметры под конкретную ситуацию, можно повысить производительность этих простых ролей до 50%. А refurbished сервер еще даст прикурить современным монстрам с настройками «по умолчанию».


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

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

https://habrahabr.ru/post/332600/


Метки:  

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

Пятница, 07 Июля 2017 г. 11:49 + в цитатник
Хабр читают и представители бизнеса, для которых важны инструменты коммуникации с потребителем, и потребители, которые свято оберегают личное пространство от чрезмерного рекламного вторжения. Рассылки SMS – довольно мощный маркетинговый инструмент, который, при неправильном использовании может дать противоположный от ожидаемого, буквально разрушительный эффект. Как этого избежать?



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

И это явно проявляется на уровне обсуждения технологии и на таком сайте, где люди, в целом, понимают грани между адекватным и неправильным использованием инструментов. Что же говорить о ситуации “в полях”, где эта грань еще тоньше? SMS-рассылки действительно могут быть уникальным инструментом, а могут закрепить за компанией репутацию спамера. Чтобы этого не случилось, важно быть ответственным на каждом этапе.

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

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

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

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

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

Второй способ – регистрация на веб-сайте компании. Если клиент готов оставить вам личные данные, значит, он уже заинтересован в сотрудничестве с вами. Остается только подобрать предложение, от которого ему не захочется отказываться. Многие используют т.н. лид-магнит (Lead Magnet) — ценное и бесплатное предложение для потенциального клиента, которое он может получить в обмен на совершение целевого действия. Это могут быть книги, отчеты, доставка… На эту тему есть огромное количество руководств в сети и мы не будем на них заострять внимание.

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

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

Продумывая способы пополнения базы своих потенциальных клиентов, помните самое главное: она должна соответствовать вашей целевой аудитории. Ваша целевая аудитория – это люди, которые проявляли интерес к вашему продукту, возможно, даже уже его покупали, и которые имеют возможность его приобретать и в дальнейшем. И эти люди должны предоставлять вам личные контакты сознательно и добровольно. Только тогда коммуникация с помощью SMS будет честной, оправданной и взаимовыгодной.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332604/


Рынок систем детекции и распознавания: Эмоции и «эмоциональные вычисления»

Пятница, 07 Июля 2017 г. 11:45 + в цитатник
В наши дни технологии по распознаванию перестают быть недосягаемыми. Распознавание эмоций и «эмоциональные вычисления» являются частью большого пласта науки, также включающего такие основополагающие понятия, как распознавание образов и обработка визуальной информации. Этим постом мы хотим открыть наш блог на Хабре и провести небольшой обзор решений, представленных на рынке систем распознавания эмоций — взглянем, какие компании работают в этом сегменте и чем конкретно они занимаются.

/ Flickr / Britt Selvitelle / CC

Системы распознавания эмоций (EDRS)


Рынок систем детекции и распознавания эмоций (EDRS) активно развивается. По оценкам ряда экспертов, он продемонстрирует среднегодовой рост в 27,4% и достигнет планки 29,1 млрд долларов к 2022 году. Такие цифры вполне оправданны, поскольку программное обеспечение для распознавания эмоций уже позволяет определять состояние пользователя в произвольный момент времени при помощи веб-камеры или специализированного оборудования, параллельно анализируя поведенческие паттерны, физиологические параметры и изменения настроения пользователя.

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

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

Подобные приемы нашли применение и в других сферах. Например, определение эмоций по физиологическим данным является ключевой функцией устройства MindWave Mobile от NeuroSky, которое надевается на голову и запускает встроенный датчик мозговой активности. Он фиксирует степень концентрации, расслабления либо беспокойства человека, оценивая ее по шкале от 1 до 100. MindWave Mobile адаптирует способ регистрации ЭЭГ, принятый в научных исследованиях. Только в этом случае система оснащена всего одним электродом, в отличие от лабораторных установок, где их количество превышает десять.

Примером детекции эмоциональных реакций по мимике может служить сервис FaceReader нидерландской компании Noldus Information Technology. Программа способна интерпретировать микроэкспрессии лица, распределяя их по семи основным категориям: радость, грусть, гнев, удивление, страх, отвращение и нейтральная (neutral). Кроме того, FaceReader умеет с достаточно высокой точностью определять по лицам возраст и пол человека.

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

В этой области заявили о себе и крупные корпорации. Например, компания Microsoft занимается развитием собственного проекта под названием Project Oxford — набора готовых REST API, реализующих алгоритмы машинного зрения (и не только). Программное обеспечение умеет различать по фотографии такие эмоции, как гнев, презрение, отвращение, страх, счастье, грусть и удивление, а также сообщать пользователю об отсутствии каких-либо зримо выраженных эмоций.

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

Распознавание ведется на основе 20 информативных локальных признаков лица, характеризующих психоэмоциональное состояние человека (ASM). Также производятся расчет двигательных единиц и их классификация по системе кодирования лицевых движений П. Экмана (FACS Action Units). Помимо этого, решение строит графики динамического изменения интенсивности эмоций испытуемого во времени и формирует отчеты о результатах обработки видео.

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

Так, компания Neurodata Lab совместно с командой разработчиков из Ocutri создала прототип софтового айтрекера Eye Catcher 0.1, позволяющего извлекать данные движений глаз и головы из видеофайлов, записанных на обычную камеру. Эта технология открывает новые горизонты в изучении движений глаз человека в естественных условиях и ощутимо расширяет исследовательские возможности. Помимо этого, линейки айтрекинговых устройств выпускают такие компании глобального значения, как SR Research (EyeLink), Tobii, SMI (приобретенная на днях корпорацией Apple), а также GazeTracker, Eyezag, Sticky и др. Основным рабочим инструментом последних тоже является веб-камера.

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

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

Affective computing — «эмоциональные вычисления»


Ключевой вектор развития внедряемых в жизнь человека новых информационных технологий — это улучшение человеко-машинного взаимодействия — human-computer interaction (HCI). Появление EDR-систем привело к возникновению такого понятия, как эмоциональные вычисления, или же по устоявшейся англоязычной терминологии — affective computing. Affective computing — это вид HCI, при котором устройство способно детектировать и соответствующим образом реагировать на чувства и эмоции пользователя, определяемые по мимике, позе, жестам, речевым характеристикам и даже температуре тела. Любопытны в связи с этим и решения, обращающиеся к подкожному кровотоку (как это делает канадский стартап NuraLogix).

Количество проводимых исследований и объемы финансирования говорят о том, что это направление является чрезвычайно перспективным. По данным marketsandmarkets.com, рынок affective computing вырастет с 12,2 млрд долларов в 2016 году до 54 млрд долларов к 2021 году при среднегодовом темпе роста 34,7%, хотя львиная его доля, как и ранее, останется за ведущими игроками рынка (Apple, IBM, Google, Facebook, Microsoft и др.).

Признание статуса эмоциональных вычислений как самостоятельной научно-исследовательской ниши и рост публичного интереса к этой сфере наблюдается приблизительно с 2000 года, когда Розалинд Пикард (Rosalind Picard) опубликовала свою книгу под знаковым названием «Affective Computing» — именно эта монография положила начало профильным исследованиям в MIT. Позднее к ним подключились ученые и из других стран.

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

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

Эмоции: злость, страх, отвращение, удивление, счастье и грусть (источник)

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

Правило из OCC-модели (источник)

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

Циклическая модель Рассела (источник)

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

Еще одна компания, у истоков которой стояли Розалинд Пикард и её аспирантка из MIT Рана Эль Калибу (Rana el Kaliouby), носит название Affectiva. Разработчики компании выложили свой SDK на платформе Unity, открыв доступ сторонним разработчикам для экспериментов, тестов и реализации всевозможных микропроектов. В активе у компании на текущий момент крупнейшая в мире база проанализированных лиц — более пяти миллионов экземпляров, а также опыт первопроходца в ряде индустрий, где до того технология распознавания эмоций практически не принималась в расчет, однако анализ по-прежнему ведется только в пределах шести базовых эмоций и одного канала (микроэкспрессии лица).

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

Стоит упомянуть и компанию Emteq. Их платформа Faceteq не только способна отслеживать состояние водителя автомобиля [усталость], но и используется в медицинских целях — специальное приложение оказывает практическое содействие людям, страдающим от паралича лицевого нерва. Ведутся работы и по внедрению решения в сферу виртуальной реальности, что позволит VR-шлему проецировать эмоциональные реакции пользователя на аватар.

Будущее


Сегодня, в 2017 году, стратегической целью исследований в области «эмоциональных вычислений» и EDRS является выход за пределы узких рамок моно- или биканальной логики, что позволит приблизиться к реальным, а не сугубо декларируемым (положим, механически объединяющим микроэкспрессии с носимыми биодатчиками или айтрекингом), сложным мультимодальным технологиям и методам распознавания эмоциональных состояний.

Компания Neurodata Lab как раз и специализируется на разработке высокоинтеллектуальных технологических решений по распознаванию эмоций и внедрении технологий EDRS в различные отрасли экономики: масс-маркетные проекты, интернет вещей (IoT), робототехнику, индустрию развлечений, интеллектуальные транспортные системы и цифровую медицину.

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

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

Человечество пытается понять, каким образом формируются те или иные психологические феномены, чтобы воспроизвести их внутри вычислительных систем. Например, этим занимается правительство США, разрабатывая архитектуру TrueNorth, в основе которой лежат нейробиологические принципы. Процессор имеет неклассическую архитектуру, то есть не придерживается архитектуры фон Неймана, а вдохновлен некоторыми моделями работы неокортекса (о чем подробно рассказывает в своих текстах Курцвейл).

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



P.S. В наших последующих материалах мы планируем затронуть такие темы, как распознавание речи и распознавание лиц, поговорить о влиянии физиологических особенностей на распознавание эмоций и о том, какие задачи решают современные нейросистемы. Подписывайтесь на наш блог, чтобы не пропустить, друзья!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332466/


Метки:  

[Из песочницы] Почему мобильные приложения занимают все больше места

Пятница, 07 Июля 2017 г. 11:41 + в цитатник

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


Инфографика 1
Инфографика 2


Авторы инфографик в оригинальных статьях выделяют две причины такого роста:


  • повышение максимального допустимого размера приложений AppStore
  • оснащение телефонов все большим объемом памяти

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


Инфографика 3


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


Лишние копии ресурсов в приложении


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


В одной из статей автор решил детально разобрать внутреннее строение приложения Facebook для iOS после того, как оно увеличилось за полгода с 165 до 253 мегабайт. Он обнаружил, что в приложении содержалось свыше 40 мегабайт избыточных дублирующих данных. В основном это были картинки, но также были и абсолютно идентичные внутренние программные файлы. Таким образом, просто удалив дубликаты, можно было бы уменьшить размер приложения на 15% процентов. Что, кстати, Facebook впоследствии и сделал.


А/Б тестирование и внедрение новых функций


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


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


В случае с приложениями под iOS переход с Objective-C на Swift может дать увеличение размера скомпилированного кода приложения в 3-4 раза. Это происходит из-за того, что ради удобства и скорости разработки новые языки могут:


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

Сюда же можно отнести переход приложений на новые фреймворки, которые тащат с собой много необходимых им файлов.


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


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


Среди наиболее популярных "велосипедов", заменяющих стандартные средства ОС, можно выделить:


  • Браузеры
  • Работа с камерой
  • Ввод текста и обработка жестов
  • Проверка орфографии

Рост требований к приложениям


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


  • После появления Retina разработчиков обязали добавлять картинки с большей детализацией и соответственно размеров.
  • Переход iOS с 32 на 64 бита впоследствии заставил всех разработчиков выпускать именно 64-битные приложения.

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

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

https://habrahabr.ru/post/332602/


Метки:  

Снимаем и вносим наличные в банкомате с помощью смартфона. Впервые в мире

Пятница, 07 Июля 2017 г. 11:11 + в цитатник
Привет, Хабр! Мы с ребятами подумали и решили, что раз уж все начинают активно пользоваться разного рода Pay-ми (Apple Pay, Samsung Pay, Android Pay, да и не за горами еще парочка от вендоров), то почему бы не дать пользователям возможность не только платить с помощью смартфона на кассе магазина, но и снимать деньги в банкомате.



Сказано – сделано.

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


Мысли о том, что неплохо бы постепенно переводить процессы оплаты на бесконтакт, пришли к нам еще во время первого фестиваля Alfa Future People. Тогда эта затея хорошо укладывалась в концепцию о том, что на территории фестиваля не должно быть наличных денег. Расплачиваться предлагалось с помощью браслета.



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





Это был 2014-й, и затем возможность вносить или снимать наличные в банкомате была распространена с браслетов на наши карты MasterCard PayPass, после чего доработали и VISA.

Новый виток развития платежей касанием был задан, когда к делу активно подключились вендоры. Apple 9 сентября 2014-го представила Apple Pay, который не только доказал свою состоятельность, но и задал очередной тренд. Samsung решил не отставать, в результате чего мир увидел Samsung Pay, а сейчас в РФ работает и Android Pay.

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

Переговоры


Мы пообщались с ребятами из Apple и объяснили им, что и как хотим сделать. Идея была воспринята с энтузиазмом.

На Apple Pay обкатывались все доработки процессинга, поэтому после выхода Samsung Pay и Android Pay каких-то технических сложностей не возникало, и по сути все подключение новой системы к банкоматам зависело только от успешности переговоров с вендором.

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



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

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

В итоге на все про все в случае с подключением Apple Pay у нас ушел месяц. В апреле 2017-го мы едем в Apple, а уже в начале мая проводим первые живые тесты на банкоматах.

На каких смартфонах это работает и насколько это безопасно


Ответ на оба эти вопроса, по сути, прост – все зависит от самой платежной системы вендора.
То есть если ваш смартфон поддерживает Apple Pay, Samsung Pay или Android Pay, то вы можете снять или внести наличные в одном из наших новых банкоматов с помощью смартфона. Если оплата на пинпаде в магазине работает с помощью часов – то получится использовать их и с банкоматом.

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

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

Где можно попробовать в действии


На начало июля в Москве у нас пока установлено 20 таких терминалов, по России суммарно – 300. Приоритет в установке отдается отделениям Альфа-Банка, но банкоматы ставятся и в бизнес-центрах.

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



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

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

К концу 2017-го мы планируем довести число таких банкоматов до 700. Сама перестройка банкоматной сети проводится двумя способами – это и установка новейших моделей банкоматов, и апгрейд текущих (соответствующий софт + ридер). При этом в случае апгрейда стоимость такой доработки составляет примерно 5% от цены нового банкомата.

Сейчас с момента официального запуска прошла пара недель, поэтому показать какую-то подробную статистику использования данной функции будет затруднительно, но общие сведения дают понять, что этим начинают пользоваться все активнее. Причем не столько в тестовом режиме «Дай-ка попробую снять тысячу смартфоном», но и на довольно больших суммах – были снятия около 100 000 рублей с использованием Apple Pay. Пока мы склонны считать, что именно этот Pay станет самым популярным у пользователей, но время покажет.

Что дальше


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

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

Это, кстати, дает небольшой плюс в плане безопасности. Если раньше над клавиатурой под конкретным углом могли устанавливать камеры, записывающие для злоумышленника ваш пин-код (или вообще использовать подложную клавиатуру в тех же целях), то ввод пин-кода и других данных с экрана вашего смартфона такую уязвимость отсекает. Как и проблему скиммеров – нет прорези для карт = никто не клонирует магнитную полосу вашей карты.
Конечно, есть ненулевая вероятность, что со временем и ростом популярности бесконтакта появятся и миниатюрные NFC-скиммеры, это неизбежно, как вечное противостояние меча и щита. Но, прямо скажем, уровень защиты данных в токене и в магнитной полосе сильно отличается.

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

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


Barclays Bank, 1967-й год, фото – AP.

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

Сейчас же в США ситуация сложилась так, что большая часть используемых карт – с магнитными полосами, а не с чипами, не говоря уже о бесконтакте. Кстати, именно по этой причине клонированные карты везут на обнал из РФ в США. Допустим, у вас есть карта с чипом. Каким-то образом в установленном не в самом надежном месте банкомате вы попали на скиммеры, которые считали магнитную полосу и пин-код, после чего злоумышленник с помощью болванки сделал клон вашей карты.

Так вот, использование этого клона в РФ будет бесполезным – у банков есть данные о том, что карта защищена еще и чипом, поэтому снять деньги с клона через банкомат не выйдет. Зато можно увезти клон в США и обналичить его там, без проверки на чип.

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

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

Чем мы и стараемся заниматься.

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

https://habrahabr.ru/post/332596/


[Перевод] Исправляем баги в стиле 1988 года

Пятница, 07 Июля 2017 г. 10:00 + в цитатник


Я рос в 80-х, в десятилетие, когда домашние компьютеры превратились из диковинки в мейнстрим. В моей младшей школе стояло несколько домашних компьютеров Phillips P2000T и пара Apple Macintosh. У моего друга был Commodore 64, на котором мы играли в игры, а однажды мой отец купил для управления финансами Commodore 128. (Меня особенно умиляет тот факт, что он и по сей день использует для ведения бухгалтерии C128, хоть и в эмуляторе. Ему близок подход «не сломалось — не чини».)

Почти сразу после C128 мы купили C64. С128 использовали для бизнеса, а C64 — для развлечений. Я чётко помню, как играл в Space Taxi, Super Cycle, Velocipede, Last Ninja II, Electrix и другие игры. К тому же на этом компьютере я начал учиться программированию.

До изобретения World Wide Web оставалась ещё пара лет, поэтому изучение программирования в основном заключалось в чтении книг и журналов. В компьютерных журналах часто публиковались листинги исходного кода, которые читателю нужно было перепечатывать. Результат мог быть любым: игрой, утилитой для копирования диска, программой для рисования под GEOS или — чаще чем хотелось бы — чем-то, работающим кое-как из-за опечаток. В какой-то момент журналы начали публиковать листинги, рядом с каждой строкой которых была указана контрольная сумма. У них были специальные программы, проверявшие контрольную сумму каждой вводимой строки. Такие программы сильно помогали. Но всё равно это был один из самых медленных и подверженных ошибкам способов копирования компьютерных программ за всю историю компьютеров. Тем не менее, процесс был довольно интересным (по крайней мере, мне так казалось).

Одним из таких журналов был Commodore Dossier, «практический журнал для активных владельцев Commodore», выпускавшийся с 1984 по 1988 год. В семнадцатом, ставшем последним, выпуске содержался листинг довольно интересной игры. Она называлась Blindganger, что в переводе с нидерландского означает «хитрец», но здесь использовалось ещё и значение слова blind («слепой»).

image
Обложка семнадцатого выпуска Commodore Dossier

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

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

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

image
Пример карты канализации из оригинальной игры

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

Разумеется, прежде чем начать, мне пришлось снова вбить весь листинг. Тогда, в 1988 году, у меня не было утилиты проверки контрольной суммы, опубликованной в Commodore Dossier. Может быть, карта канализации оказалась перепутанной из-за моей невнимательности и опечаток?

Быстрый поиск в Google вывел меня на образ диска с программой «CHECKSUM DOSSIER». Звучит многообещающе! Чтобы проверить, я запустил программу и напечатал короткую строку из листинга Blindganger: «240 RETURN», рядом с которой была указана контрольная сумма «7E». Потом я попробовал вставить опечатку и в саму строку, и в контрольную сумму. В обоих случаях на экране выводилось сообщение «FOUT IN REGEL», то есть «ОШИБКА В СТРОКЕ». Отлично!

image
Разве это не мило?

С помощью этой программы я ввёл весь листинг. Некоторые строки отсканированного журнала плохо читались, поэтому утилита оказалась незаменимой. Часто мне приходилось подбирать разные варианты сочетаний строк и контрольных сумм, пока они не совпадали. Ну что ж, пока всё идёт неплохо. Теперь у меня была копия оригинала, в которой точно не было опечаток. Конечно же, в этой копии не должно быть тех багов, которые возникали у меня в 1988 году. Но… они были!

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

В строке 1780 нашлась переменная MAAL, которая сравнивалась с нулём. Эта переменная инициализировалась со значением 3 в строке 1550 и уменьшалась с каждым сливом канализации.

1780 MAAL=MAAL-1:IFMAAL=0THENGOTO1810

Блок кода в строках 1810-1840 выполняется, если MAAL равняется нулю. Строка 1840 — это бесконечный цикл. Посмотрев на три остальные строки BASIC, я понял, что нашей следующей целью является подпрограмма в машинном коде, расположенная по адресу памяти 16540 ($409C).

1810 POKECROSS+4096,1           :REM MARK EXIT ON THE MAP
1820 SYS16540                   :REM COPY MAP TO SCREEN
1830 POKESID+11,0:POKE53248+21,0:REM STOP SOUND AND DISABLE SPRITES
1840 GOTO1840                   :REM ENDLESS LOOP

Эта подпрограмма состоит из двух частей. Первая копирует 1000 байт из области памяти, начиная с $6000, в экранную память ($0400-$07E7). Она заполняет весь экран (40 столбцов на 25 строк = 1000 байт) картой канализации.

Как выяснилось, в этой части нет никаких багов. Карта может казаться странной, пока вы не заметите, что все сплошные части — это стены, символами "@" отмечены горизонтальные секции труб, символами «A» — вертикальные секции, символы с «B» по «J» обозначают разные типы углов и пересечений, «K» — это ямы, а «L» — выход. Эти символы неслучайны. Они соответствуют экранным кодам с 0 по 12. Карта — это просто дамп на экран внутреннего представления карты в игре.

Вторая часть подпрограммы копирует 1000 байт из области памяти, начиная с $7000, в цветовую ОЗУ ($D800-$DBE7). Так все посещённые локации закрашиваются жёлтым.

L40CB:  LDA     #$FF    ; >-- инициализация --
        STA     $FB     ;                      |
        LDA     #$6F    ;                      |
        STA     $FC     ;                      |
        LDA     #$F4    ;                      |
        STA     $FD     ;                      |
        LDA     #$D7    ;                      |
        STA     $FE     ; <--------------------
        LDX     #$04    ; >-- внешний цикл -----------------
L40DD:  LDY     #$FA    ; >-- внутр. цикл I ---             |
L40DF:  LDA     ($FB),Y ; (копирование байтов) |            |
        STA     ($FD),Y ;                      |            |
        DEY             ;                      |            |
        BNE     L40DF   ; <-------------------              |
        LDY     #$FA    ; >-- внутр. цикл II -----------    |
L40E8:  INC     $FB     ; (обновление начальных адресов) |  |
        BNE     L40EE   ;                                |  |
        INC     $FC     ;                                |  |
L40EE:  INC     $FD     ;                                |  |
        BNE     L40F4   ;                                |  |
        INC     $FE     ;                                |  |
L40F4:  DEY             ;                                |  |
        BNE     L40E8   ; <----------------------------     |
        DEX             ;                                   |
        BNE     L40DD   ; <-------------------------------

Байты копируются четырьмя блоками по 250 байт. Внешний цикл использует регистр X как счётчик с 4 до 0.

        LDX     #$04   
        ;
        ; внутренний цикл
        ;
        DEX            
        BNE     L40DD

Первый внутренний цикл использует регистр Y как счётчик с #$FA (250) до 0.

L40DD:  LDY     #$FA   
L40DF:  LDA     ($FB),Y
        STA     ($FD),Y
        DEY            
        BNE     L40DF  

Для копирования байтов во внутреннем цикле используется непрямая индексная адресация. В этом режиме адресации регистр Y используется как смещение, прибавляемое к 16-битному начальному адресу, хранящемуся в нулевой странице.

Например, команда LDA ($FB),Y выполняется следующим образом:

  • Считывается 16-битный начальный адрес в прямом порядке байтов, хранящийся в участках $FB и $FC нулевой страницы. Прямой порядок байтов означает, что наименьший значимый байт хранится в самом нижнем адресе ($FB). $FB инициализируется в #$FF, а $FC — в #$6F, поэтому 16-битный начальный адрес будет $6FFF.
  • Для вычисления действительного адреса к начальному адресу прибавляется значение регистра Y. Регистр Y инициализируется в начале цикла в #$FA. Прибавляя к $6FFF, получаем действительный адрес $70F9.
  • В накопитель (регистр A) загружается байт из действительного адреса.

Регистр Y ведёт обратный отсчёт от 250 до 0. Заметьте, что минимальное значение Y, используемое как индекс, равно 1. (Когда команда DEY уменьшает Y до нуля, то следующая команда ветвления BNE проходит мимо и выходит из внутреннего цикла.)

Первый загружаемый байт находится по адресу $7000. Поскольку минимальное значение Y равно 1, начальный адрес источника должен быть инициализирован в $7000 — 1 = $6FFF. Аналогично, первый сохраняемый байт находится по адресу $D800, поэтому целевой начальный адрес должен инициализироваться в $D800 — 1 = $D7FF. Вместо этого он инициализируется в $D7F4!

Случайная опечатка и ввод #$F4 вместо #$FF маловероятны. Но в десятичном счислении это соответствует вводу 244 вместо 255. Похоже, автор игры случайно нажал на 4 вместо 5 при вводе константы 255! Это сдвинуло цвета, использованные в карте, на 11 позиций относительно самой карты. В свою очередь, это значит, что на карте неправильно отмечались посещённые локации.

Виновный в ошибке байт находится в операторе задания данных в строке 3670 листинга на BASIC:

3670 DATA 252,169,244,133,253

После замены на правильное значение (255), карта канализации начинает отображаться правильно. И это означает… что мы исправили ошибку 29-летней давности!

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

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

Blindganger 2017 также доступен в форме листинга на BASIC, включая контрольные суммы. Чтобы ощутить себя в 80-х, скачайте и запустите утилиту проверки контрольных сумм Commodore Dossier (см. ссылку ниже), а потом начинайте печатать!

Позже я ещё внёс усовершенствования в (уже правильную) карту канализации, чтобы она проще читалась (см. пример ниже).


Крестом помечен выход!

Ссылки


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

https://habrahabr.ru/post/332586/


Метки:  

Kubernetes & production — быть или не быть?

Пятница, 07 Июля 2017 г. 09:01 + в цитатник
Сотни контейнеров. Миллионы внешних запросов. Миллиарды внутренних транзакций. Мониторинг и нотификации проблем. Простое масштабирование. 99% up time. Деплои и откатывание релизов.



Kubernetes как решение всех проблем! «Быть или не быть?» — вот в чем вопрос!


Disclaimer


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

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

Я попытаюсь описать весь опыт, полученный нами в `Lazada Express Logistics`, компании являющейся частью `Lazada Group`, которая в свою очередь — часть `Alibaba Group`. Мы разрабатываем и осуществляем поддержку систем автоматизирующих по-максимуму весь операционный цикл доставки и фулфилмента в 6 крупнейших странах Юго-восточной Азии.

Предпосылки к использованию


Однажды представитель компании, продающей облачные решения по всему миру, спросил у меня: «А что для Вас 'облако'?». Помешкав пару секунд (и подумав:«Хммм… наш диалог явно не о взвешенных в атмосфере конденсациях водяного пара...»), я ответил, что, мол, это как будто один сверх-надежный компьютер с неограниченными ресурсами и практически не имеющий накладных расходов на передачу потоков данных(cеть, диск, память, т.д.). Словно это мой лэптоп работающий для всего мира и способный держать такую нагрузку, а я в одиночку способен им управлять.



Собственно зачем нам это облачное чудо? Все в общем-то очень просто! Мы стремимся облегчить жизнь разработчиков, системных администраторов, devops-ов, тех-менеджеров. А такая вещь, как правильно приготовленное облако, многократно облегчает жизнь всем. Да и помимо всего прочего, мономорфные системы работающие на бизнес всегда дешевле и порождают меньше рисков.

Мы задались целью найти простую, удобную и надежную платформу приватного облака для всех наших приложений и для всех типов ролей в команде перечисленных выше. Провели небольшое исследование: Docker, Puppet, Swarm, Mesos, Openshift + Kubernetes, Kubernetes — Openshift… остановились на последнем — Kubernetes безо всяких аддонов.

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

Засучили рукава. И понеслось…

Проблемы и их решения





3-х уровневая архитектура


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



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

Мой чек-лист разделяет инфраструктуру на три слоя, а затем примерно описывает то, о чем на каждом из уровней нужно помнить при создании подобных систем. Три слоя о которых идет речь:
  • Hardware — сервера, физические сети
  • Cluster — в нашем случае Kubernetes и системные сервисы поддерживающие его (flannel, etcd, confd, docker)
  • Service — непосредственно процесс упакованный в Docker — микро/макро сервис в своем домене

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


Квалифицированные специалисты


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



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

Решение простое — нужно взращивать специалистов внутри компании! Благо, в нашем случае, мы уже знали что такое Docker и как его готовить — остальное пришлось нагонять.

Continuous Delivery/Integration


Не смотря на всю прелесть технологии «умного облачного кластера», нам были необходимы средства общения и установки объектов внутрь Kubernetes. Пройдя дорогу от самописного bash скрипта и сотен ветвей логики, мы закончили вполне понятными и читаемыми рецептами для Ansible. Для полноценного превращения Docker файлов в живые объекты нам понадобилось:

  • Набор стандартных решений:
    • Team City — для автоматизированных деплоев
    • Ansible — для сборки шаблонов и доставки/установки объектов
    • Docker Registry — для хранения и доставки Docker образов
  • images-builder — скрипт для рекурсивного поиска Docker файлов в репозитории и отправки образов на их основе после сборки в централизованное registry
  • Ansible Kubernetes Module — модуль для установки объектов с различными стратегиями в зависимости от объекта (создать или обновить/создать или заменить/создать или пропустить)




По мимо всего прочего мы изучали вопрос о Kubernetes Helm. Но тем не менее, не смогли найти той самой killer-feature, которая могла бы заставить нас отказаться или заменить Ansible шаблонизацию на Helm чарты. Других полезных способностей этого решения мы не смогли найти.

Например, как делать проверку того, что один из объектов успешно установлен и можно продолжить выкатку других? Или как делать более тонкие настройки и установки контейнеров, которые уже работают, и нужно просто выполнить пару команд внутри их?

Эти и многие другие вопросы обязывают относиться к Helm как к простому шаблонизатору. Но зачем это?.. если Jinja2, входящая в состав Ansible, даст фору любому не профильному решению.


Сервисы хранящие состояние


Как полноценное решение для любого типа сервисов, включая statefull(имеющие состояние), Kubernetes поставляется с набором драйверов для работы с сетевыми блочными устройствами. В случае с AWS, единственный приемлемый вариант — EBS.

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



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



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

Небольшой пример.
Собирать логи внутри запущенного Docker контейнера нельзя. НО очень много систем и фреймворков не готовы к стримингу в `STDOUT`. Нужно заниматься `патчингом` и осознанной разработкой на системном уровне: писать в пайпы, заботиться о процессах и т.д. Немного времени и у нас есть Monolog Handler для `php`, который способен выдавать логи так, как их поймет Docker/k8s


API Gateway


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

Все довольно просто — нужна единая точка отказа доступа ко всем вашим сервисам.



Есть ряд задач которые мы решали в разрезе Kubernetes кластера:

  • Контроль доступа и лимитация запросов извне — как пример небольшой LUA скрипт проливает свет на проблему
  • Единая точка аутентификации/авторизации пользователей для любых сервисов
  • Отсутствие множества сервисов требующих доступ по HTTP из `мира` — резервирование портов на серверах для каждого желающего сервиса управляется тяжелее, чем роутинг в Nginx
  • Интеграция Kubernetes-AWS для работы с AWS Load Balancer
  • Единая точка мониторинга HTTP статусов — удобно даже для внутреннего общения сервисов
  • Динамическая маршрутизация запросов на сервисы или версии сервисов, A/B тесты (альтернативно проблема может решаться разными pod-ами за сервисом Kubernetes)

Искушенный пользователь Kubernetes поспешит спросить о Kubernetes Ingress Resource, который предназначен именно для решения подобных задач. Все верно! Но мы требовали немного больше `фич`, как вы могли заметить, для нашего API Gateway чем есть в Ingress. Тем более, это всего лишь обертка для Nginx, с которым мы и так умеем работать.


Текущее состояние


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



Что же из себя представляет платформа в текущем состоянии — немного сухих фактов:
  • Всего 2-3 человека для поддержки всей платформы
  • Один репозиторий хранящий всю информацию обо всей инфраструктуре
  • От 10-50 независимых автоматизированных релизов в день — CI/CD mode
  • Ansible как средство управления кластером
  • Считанные часы для создания идентичного `life` окружения — локально на minikube или на реальных серверах
  • AWS-based архитектура на базе EC2 + EBS, CentOS, Flannel
  • 500~1000 pod-ов в системе
  • Лист технологий завернутых в Docker/K8s: Go, PHP, JAVA/Spring FW/Apache Camel, Postgres/Pgpool/Repmgr, RabbitMQ, Redis, Elastic Search/Kibana, FluentD, Prometheus, etc
  • Инфраструктура вне кластера отсутствует, за исключением мониторинга на уровне `Hardware`
  • Централизованное хранилище логов на базе Elastic Search внутри Kubernetes кластера
  • Единая точка сбора метрик и алертинга проблем на базе Prometheus

Список отражает множество фактов, но опущенными остаются явные преимущества и приятные особенности Kubernetes как системы управления Docker процессами. Подробнее с этими вещами можно ознакомится на оффициальном сайте Kubernetes, в статьях на том же Хабре или Medium.

Длинный список наших пожеланий, которые находятся на стадии прототипов или пока еще покрывают небольшую часть системы, тоже очень большой:
  • Система профилирования и трэйсинга — например, zipkin
  • Anomaly detectionмашинно обучаемые алгоритмы для анализа проблем по сотням метрик, когда мы не можем или не хотим понимать что значит каждая метрика/набор метрик в отдельности, но хотим знать о проблеме связанной с этими метриками
  • Автоматическое планирование мощностей и масштабирование как количества pod-ов в сервисе так и серверов в кластере на основе определенных метрик
  • Интеллектуальная система управления бэкапами — для любых stateful сервисов, в первую очередь баз данных
  • Система мониторинга сетей и визуализации связей — внутри кластера, между сервисами и pod-ами, прежде всего (интересный пример)
  • Federation mode — распределенный и связнный режим работы нескольких кластеров


Тaк быть или не быть?


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

Решать вам! Но мое мнение по поводу всего этого: «БЫТЬ!.. но очень аккуратно»
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332108/


[Перевод] Создание движка для блога с помощью Phoenix и Elixir / Часть 9. Каналы

Пятница, 07 Июля 2017 г. 08:42 + в цитатник


От переводчика: «Elixir и Phoenix — прекрасный пример того, куда движется современная веб-разработка. Уже сейчас эти инструменты предоставляют качественный доступ к технологиям реального времени для веб-приложений. Сайты с повышенной интерактивностью, многопользовательские браузерные игры, микросервисы — те направления, в которых данные технологии сослужат хорошую службу. Далее представлен перевод серии из 11 статей, подробно описывающих аспекты разработки на фреймворке Феникс казалось бы такой тривиальной вещи, как блоговый движок. Но не спешите кукситься, будет действительно интересно, особенно если статьи побудят вас обратить внимание на Эликсир либо стать его последователями.

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


На данный момент наше приложение основано на:


  • Elixir: v1.3.1
  • Phoenix: v1.2.0
  • Ecto: v2.0.2

На чём мы остановились


В прошлый раз было полностью покончено с комментариями! Теперь, когда все функции готовы, давайте сделаем блог по-настоящему классным, воспользовавшись возможностями, которые Elixir и Phoenix предоставляют прямо из коробки. Превратим систему комментариев в систему «живых» комментариев с помощью каналов из Phoenix. Честно признаёмся: в этой части ОЧЕНЬ много тяжёлого джаваскрипта.


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


  1. Новые комментарии по мере появления должны транслироваться только авторизованным пользователям.
  2. При одобрении, комментарии должны транслироваться всем пользователям.
  3. Удалённые комментарии должны пропадать у всех пользователей.

Добавляем каналы


Первым шагом при реализации любого канала в Phoenix является работа с файлом web/channels/user_socket.ex. Изменим закомментированную строку, находящуюся под ## Channels, на следующее:


channel "comments:*", Pxblog.CommentChannel

А затем создадим сам канал, с которым будем работать. Для этого воспользуемся генератором Phoenix:


$ mix phoenix.gen.channel Comment

* creating web/channels/comment_channel.ex
* creating test/channels/comment_channel_test.exs

Add the channel to your `web/channels/user_socket.ex` handler, for example:
channel "comment:lobby", Pxblog.CommentChannel

Основываясь на требованиях, мы будем создавать отдельный канал комментариев для каждого post_id.


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


Для авторизованных пользователей:


  1. Комментарий создан
  2. Комментарий удалён
  3. Комментарий одобрен

Для всех:


  1. Комментарий одобрен
  2. Комментарий удалён

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


Добавление jQuery с помощью Brunch


Начнём с установки jQuery через NPM.


npm install --save-dev jquery

А затем перезагрузим сервер Phoenix и проверим, что jQuery успешно установился. Откройте файл web/static/js/app.js и добавьте вниз следующий код:


import $ from "jquery"

if ($("body")) {
 console.log("jquery works!")
}

Если вы увидели сообщение «jquery works!» в Developer Console браузера, то можете удалять эти строчки и переходить к следующему шагу.


Реализация каналов на Javascript


Первым делом вернёмся к файлу web/static/js/app.js и раскомментируем оператор импорта сокета.


Затем откроем файл web/static/js/socket.js и внесём несколько небольших правок:


// For right now, just hardcode this to whatever post id you're working with

const postId = 2;
const channel = socket.channel(`comments:${postId}`, {});

channel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) });

Обратимся к описанию сокета, чтобы понять какие сообщения нужно слушать/транслировать. Будем использовать «CREATED_COMMENT» для свежесозданных комментариев, «APPROVED_COMMENT» для одобренных комментариев и «DELETED_COMMENT» для удалённых. Добавим их в качестве констант в файл socket.js:


const CREATED_COMMENT  = "CREATED_COMMENT"
const APPROVED_COMMENT = "APPROVED_COMMENT"
const DELETED_COMMENT  = "DELETED_COMMENT"

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


channel.on(CREATED_COMMENT, (payload) => {
  console.log("Created comment", payload)
});
channel.on(APPROVED_COMMENT, (payload) => {
  console.log("Approved comment", payload)
});
channel.on(DELETED_COMMENT, (payload) => {
  console.log("Deleted comment", payload)
});

И наконец, изменим кнопку Submit, чтобы вместо отправки комментария создавать «фальшивое» событие:


$("input[type=submit]").on("click", (event) => {
  event.preventDefault()
  channel.push(CREATED_COMMENT, { author: "test", body: "body" })
})

Доработка кода для поддержки каналов


Если попробовать протестировать в браузере, приложение упадёт. Вы получите сообщение об ошибке наподобие этого:


[error] GenServer #PID<0.1250.0> terminating
** (FunctionClauseError) no function clause matching in Pxblog.CommentChannel.handle_in/3
 (pxblog) web/channels/comment_channel.ex:14: Pxblog.CommentChannel.handle_in(“CREATED_COMMENT”, %{“author” => “test”, “body” => “body”}, %Phoenix.Socket{assigns: %{}, channel: Pxblog.CommentChannel, channel_pid: #PID<0.1250.0>, endpoint: Pxblog.Endpoint, handler: Pxblog.UserSocket, id: nil, joined: true, pubsub_server: Pxblog.PubSub, ref: “2”, serializer: Phoenix.Transports.WebSocketSerializer, topic: “comments:2”, transport: Phoenix.Transports.WebSocket, transport_name: :websocket, transport_pid: #PID<0.1247.0>})
 (phoenix) lib/phoenix/channel/server.ex:229: Phoenix.Channel.Server.handle_info/2
 (stdlib) gen_server.erl:615: :gen_server.try_dispatch/4
 (stdlib) gen_server.erl:681: :gen_server.handle_msg/5
 (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{event: “CREATED_COMMENT”, payload: %{“author” => “test”, “body” => “body”}, ref: “2”, topic: “comments:2”}
State: %Phoenix.Socket{assigns: %{}, channel: Pxblog.CommentChannel, channel_pid: #PID<0.1250.0>, endpoint: Pxblog.Endpoint, handler: Pxblog.UserSocket, id: nil, joined: true, pubsub_server: Pxblog.PubSub, ref: nil, serializer: Phoenix.Transports.WebSocketSerializer, topic: “comments:2”, transport: Phoenix.Transports.WebSocket, transport_name: :websocket, transport_pid: #PID<0.1247.0>}

Прямо сейчас у нас нет функциии для обработки сообщений внутри канала. Откройте файл web/channels/comment_channel.ex и давайте сделаем так, чтобы функция handle_in транслировала сообщения подписчикам, вместо того, чтобы молча наблюдать. Нам также нужно изменить стандартную функцию join вверху:


def join("comments:" <> _comment_id, payload, socket) do
  if authorized?(payload) do
    {:ok, socket}
  else
    {:error, %{reason: "unauthorized"}}
  end
end

# ...

# It is also common to receive messages from the client and
# broadcast to everyone in the current topic (comments:lobby).
def handle_in("CREATED_COMMENT", payload, socket) do
  broadcast socket, "CREATED_COMMENT", payload
  {:noreply, socket}
end

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


def handle_in("APPROVED_COMMENT", payload, socket) do
  broadcast socket, "APPROVED_COMMENT", payload
  {:noreply, socket}
end

def handle_in("DELETED_COMMENT", payload, socket) do
  broadcast socket, "DELETED_COMMENT", payload
  {:noreply, socket}
end

Нам также нужно внести несколько правок в шаблоны. Необходимо знать с каким постом мы работаем и кем является текущий пользователь. Таким образом, добавим наверх файла web/templates/post/show.html.eex следующий код:



Затем откройте файл web/templates/comment/comment.html.eex и измените открывающий div:



Теперь, когда всё, связанное с комментариями, обрабатывается через Javascript, нам нужно удалить некоторый написанный ранее код для кнопок Approve/Reject. Изменим весь блок, чтобы он выглядел похожим на это:



  
    
  
  

Также, внутри тегов div, где выводятся автор и текст комментария, измените тег strong, чтобы у них появились классы .comment-author and .comment-body, соответственно.



...



Наконец, нужно убедиться, что мы можем подходящим образом обращаться к автору и тексту комментария, так что откроем файл web/templates/comment/form.html.eex и убедимся, что поле ввода комментария и кнопка отправки выглядят так:



Сейчас необходимо реализовать каждую из возможностей транслирования должным образом, так что вернёмся на «поле джаваскрипта» и продолжим!


Реализация идентификатора пользователя через Phoenix.Token


Нам понадобится способ для проверки, является ли пользователь тем, за кого себя выдаёт и имеет ли он доступ к изменению данных комментария. Чтобы сделать это, мы воспользуемся встроенным в Phoenix модулем Phoenix.Token.


Начнём с проставления пользовательского токена в шаблон приложения. Это достаточно удобно, ведь вероятно мы захотим отображать его везде. В файле web/templates/layout/app.html.eex добавьте следующее к остальным мета-тегам:



  

Здесь мы говорим, что хотим подписанный токен, который указывает на идентификатор пользователя (конечно, если пользователь вошёл в систему). Это даст нам прекрасный способ для проверки user_id пользователя через Javascript без необходимости доверять скрытым полям ввода или пользоваться другими странными способами.


Далее в файле web/static/js/socket.js, внесите несколько изменений в код соединения сокета:


// Grab the user's token from the meta tag
const userToken = $("meta[name='channel_token']").attr("content")
// And make sure we're connecting with the user's token to persist the user id to the session
const socket = new Socket("/socket", {params: {token: userToken}})
// And then connect to our socket
socket.connect()

Теперь передадим валидный токен обратно в код Phoenix. На этот раз нам нужен файл web/channels/user_socket.ex, в котором изменим функцию connect для проверки токена пользователя:


def connect(%{"token" => token}, socket) do
  case Phoenix.Token.verify(socket, "user", token, max_age: 1209600) do
    {:ok, user_id} ->
      {:ok, assign(socket, :user, user_id)}
    {:error, reason} ->
      {:ok, socket}
  end
end

Итак, мы вызываем функцию verify из модуля Phoenix.Token и передаём в неё сокет, значение для проверки, сам токен и значение max_age (максимальное время жизни токена, например, две недели).


Если верификация прошла успешно, то отправим обратно кортеж {:ok, [значение, извлечённое из токена]}, которым в нашем случае является user_id. Затем поддержим соединение со значением user_id, сохранённым в сокете (подобно сохранению значения в сессии или conn).


Если верифицировать соединение не удалось, это тоже нормально. Так как мы по-прежнему хотим, чтобы неавторизованные пользователи так же могли получать обновления без верифицированного user_id, то не будем ничего присваивать, а просто вернём {:ok, socket}.



Возвращаемся к Socket.js


Нам понадобится тонна Javascript-кода для поддержки всего задуманного. Рассмотрим задачи подробнее:


  1. Брать значение postId прямиком из DOM
  2. Написать функцию для генерации шаблона нового комментария
  3. Написать функцию для получения автора комментария
  4. Написать функцию для получения текста комментария
  5. Написать функцию для получения идентификатора комментария
  6. Написать функцию для сброса комментария
  7. Написать функцию для обработки создания комментария
  8. Написать функцию для обработки одобрения комментария
  9. Написать функцию для обработки удаления комментария
  10. Написать функцию для обработки события создания комментария
  11. Написать функцию для обработки события одобрения комментария
  12. Написать функцию для обработки события удаления комментария

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


// Import the socket library
import {Socket} from "phoenix"
// And import jquery for DOM manipulation
import $ from "jquery"

// Grab the user's token from the meta tag
const userToken = $("meta[name='channel_token']").attr("content")
// And make sure we're connecting with the user's token to persist the user id to the session
const socket = new Socket("/socket", {params: {token: userToken}})
// And connect out
socket.connect()

// Our actions to listen for
const CREATED_COMMENT  = "CREATED_COMMENT"
const APPROVED_COMMENT = "APPROVED_COMMENT"
const DELETED_COMMENT  = "DELETED_COMMENT"

// REQ 1: Grab the current post's id from a hidden input on the page
const postId = $("#post-id").val()
const channel = socket.channel(`comments:${postId}`, {})
channel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) })

// REQ 2: Based on a payload, return to us an HTML template for a comment
// Consider this a poor version of JSX
const createComment = (payload) => `
  
${payload.author}
${payload.insertedAt}
${ userToken ? ' ' : '' }
${payload.body}
` // REQ 3: Provide the comment's author from the form const getCommentAuthor = () => $("#comment_author").val() // REQ 4: Provide the comment's body from the form const getCommentBody = () => $("#comment_body").val() // REQ 5: Based on something being clicked, find the parent comment id const getTargetCommentId = (target) => $(target).parents(".comment").data("comment-id") // REQ 6: Reset the input fields to blank const resetFields = () => { $("#comment_author").val("") $("#comment_body").val("") } // REQ 7: Push the CREATED_COMMENT event to the socket with the appropriate author/body $(".create-comment").on("click", (event) => { event.preventDefault() channel.push(CREATED_COMMENT, { author: getCommentAuthor(), body: getCommentBody(), postId }) resetFields() }) // REQ 8: Push the APPROVED_COMMENT event to the socket with the appropriate author/body/comment id $(".comments").on("click", ".approve", (event) => { event.preventDefault() const commentId = getTargetCommentId(event.currentTarget) // Pull the approved comment author const author = $(`#comment-${commentId} .comment-author`).text().trim() // Pull the approved comment body const body = $(`#comment-${commentId} .comment-body`).text().trim() channel.push(APPROVED_COMMENT, { author, body, commentId, postId }) }) // REQ 9: Push the DELETED_COMMENT event to the socket but only pass the comment id (that's all we need) $(".comments").on("click", ".delete", (event) => { event.preventDefault() const commentId = getTargetCommentId(event.currentTarget) channel.push(DELETED_COMMENT, { commentId, postId }) }) // REQ 10: Handle receiving the CREATED_COMMENT event channel.on(CREATED_COMMENT, (payload) => { // Don't append the comment if it hasn't been approved if (!userToken && !payload.approved) { return; } // Add it to the DOM using our handy template function $(".comments h2").after( createComment(payload) ) }) // REQ 11: Handle receiving the APPROVED_COMMENT event channel.on(APPROVED_COMMENT, (payload) => { // If we don't already have the right comment, then add it to the DOM if ($(`#comment-${payload.commentId}`).length === 0) { $(".comments h2").after( createComment(payload) ) } // And then remove the "Approve" button since we know it has been approved $(`#comment-${payload.commentId} .approve`).remove() }) // REQ 12: Handle receiving the DELETED_COMMENT event channel.on(DELETED_COMMENT, (payload) => { // Just delete the comment from the DOM $(`#comment-${payload.commentId}`).remove() }) export default socket

Пожалуй, достаточно с джаваскриптом. Сейчас у нас есть рабочая функциональность, но без какой-либо защиты. Давайте добавим её в нашем Elixir-коде с помощью создания вспомогательной функции для добавления, одобрения и удаления комментариев.


Вспомогательные функции для каналов


С нашим Javascript-кодом всё отлично, так что, вероятно, добавить вспомогательные функции нужно на стороне бэкенда. Начнём с создания нового модуля, который станет рабочей лошадкой наших взаимодействий с базой данных для создания/одобрения/удаления комментариев. Так что создадим файл web/channels/comment_helper.ex:


defmodule Pxblog.CommentHelper do
  alias Pxblog.Comment
  alias Pxblog.Post
  alias Pxblog.User
  alias Pxblog.Repo

  import Ecto, only: [build_assoc: 2]

  def create(%{"postId" => post_id, "body" => body, "author" => author}, _socket) do
    post      = get_post(post_id)
    changeset = post
      |> build_assoc(:comments)
      |> Comment.changeset(%{body: body, author: author})

    Repo.insert(changeset)
  end

  def approve(%{"postId" => post_id, "commentId" => comment_id}, %{assigns: %{user: user_id}}) do
    authorize_and_perform(post_id, user_id, fn ->
      comment = Repo.get!(Comment, comment_id)
      changeset = Comment.changeset(comment, %{approved: true})
      Repo.update(changeset)
    end)
  end

  def delete(%{"postId" => post_id, "commentId" => comment_id}, %{assigns: %{user: user_id}}) do
    authorize_and_perform(post_id, user_id, fn ->
      comment = Repo.get!(Comment, comment_id)
      Repo.delete(comment)
    end)
  end

  defp authorize_and_perform(post_id, user_id, action) do
    post = get_post(post_id)
    user = get_user(user_id)
    if is_authorized_user?(user, post) do
      action.()
    else
      {:error, "User is not authorized"}
    end
  end

  defp get_user(user_id) do
    Repo.get!(User, user_id)
  end

  defp get_post(post_id) do
    Repo.get!(Post, post_id) |> Repo.preload([:user, :comments])
  end

  defp is_authorized_user?(user, post) do
    (user && (user.id == post.user_id || Pxblog.RoleChecker.is_admin?(user)))
  end
end

Начнём сверху. Мы будем часто обращаться к модулям Comment/Post/User/Repo, так что для чистоты кода, правильно будет добавить для них алиасы. Нам также нужно импортировать функцию build_assoc из Ecto, но только версию арности 2.


Далее мы переходим сразу к созданию поста. Мы по привычке передаём в функцию socket, но он нам не всегда нужнен. Например, в данном случае, ведь комментарий добавить может любой. Мы сопоставляем с образцом значения post_id, body и author в аргументах, чтобы с ними можно было работать внутри функции.


def create(%{"postId" => post_id, "body" => body, "author" => author}, _socket) do
  post      = get_post(post_id)
  changeset = post
    |> build_assoc(:comments)
    |> Comment.changeset(%{body: body, author: author})

  Repo.insert(changeset)
end

Мы получаем пост через функцию get_post , которую пока не написали. Это будет приватная функция чуть ниже. We then build a changeset off the post to build an associated comment with the body and author we supplied.
Затем создаём ченджсет из поста для создания связанного комментария. В конце вернём результат функции Repo.insert. Это абсолютно простой и стандарный код на Ecto, так что здесь никаких сюрпризов возникнуть не должно. Тоже самое можно сказать и обо всех остальных функциях. Далее взглянем на функцию approve:


def approve(%{"postId" => post_id, "commentId" => comment_id}, %{assigns: %{user: user_id}}) do
  authorize_and_perform(post_id, user_id, fn ->
    comment = Repo.get!(Comment, comment_id)
    changeset = Comment.changeset(comment, %{approved: true})
    Repo.update(changeset)
  end)
end

Здесь снова сопоставляются с образцом необходимые значения — post_id и comment_id из первого аргумента и проверенный user_id из сокета, переданного вторым. Далее мы вызываем вспомогательную функцию authorize_and_perform и передаём в неё анонимную функцию, которая получает комментарий, обновляет флаг approved в true через ченджсет и затем отправляет обновление в Repo. Довольно стандартный код, но эта функция authorize_and_perform выглядит загадочной, так что давайте отвлечёмся на её разбор:


defp authorize_and_perform(post_id, user_id, action) do
  post = get_post(post_id)
  user = get_user(user_id)
  if is_authorized_user?(user, post) do
    action.()
  else
    {:error, "User is not authorized"}
  end
end

В неё передаются post_id и user_id, так как оба этих значения требуются для правильной авторизации действий с комментарием. Затем вызывается другая вспомогательная функция is_authorized_user?, которая, получая пользователя и пост, возвращает true или false. Если всё хорошо, то вызывается анонимная функция action. Обратите внимание на точку между названием и скобками. Иначе возвращается кортеж {:error, «User is not authorized»}, который мы можем перехватить далее, если захотим вывести красивое сообщение об ошибке.


Авторизация совершается внутри функции, а затем исполняются действия, переданные с помощью блока fn -> ... end. Это хороший образец, когда дублируется много логики.


С функции authorize_and_perform достаточно. Перейдём к функции delete:


def delete(%{"postId" => post_id, "commentId" => comment_id}, %{assigns: %{user: user_id}}) do
  authorize_and_perform(post_id, user_id, fn ->
    comment = Repo.get!(Comment, comment_id)
    Repo.delete(comment)
  end)
end

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


Наконец, взглянем на вспомогательные функции поменьше.


defp get_user(user_id) do
  Repo.get!(User, user_id)
end

defp get_post(post_id) do
  Repo.get!(Post, post_id) |> Repo.preload([:user, :comments])
end

defp is_authorized_user?(user, post) do
  (user && (user.id == post.user_id || Pxblog.RoleChecker.is_admin?(user)))
end

Получение пользователя, получение поста и проверка авторизации пользователя (код, взятый из PostController). Со вспомогательными функциями покончено. Добавим их в CommentChannel.


Встраивание вспомогательных функций в канал комментариев


Все, что нам нужно — заменить первоначальный код с сообщениями CREATED/APPROVED/DELETED на вспомогательные функции. Откройте файл web/channels/comment_channel.ex:


alias Pxblog.CommentHelper
  # It is also common to receive messages from the client and
  # broadcast to everyone in the current topic (comments:lobby).
  def handle_in("CREATED_COMMENT", payload, socket) do
    case CommentHelper.create(payload, socket) do
      {:ok, comment} ->
        broadcast socket, "CREATED_COMMENT", Map.merge(payload, %{insertedAt: comment.inserted_at, commentId: comment.id, approved: comment.approved})
        {:noreply, socket}
      {:error, _} ->
        {:noreply, socket}
    end
  end

  def handle_in("APPROVED_COMMENT", payload, socket) do
    case CommentHelper.approve(payload, socket) do
      {:ok, comment} ->
        broadcast socket, "APPROVED_COMMENT", Map.merge(payload, %{insertedAt: comment.inserted_at, commentId: comment.id})
        {:noreply, socket}
      {:error, _} ->
        {:noreply, socket}
    end
  end

  def handle_in("DELETED_COMMENT", payload, socket) do
    case CommentHelper.delete(payload, socket) do
      {:ok, _} ->
        broadcast socket, "DELETED_COMMENT", payload
        {:noreply, socket}
      {:error, _} ->
        {:noreply, socket}
    end
  end

Принципы схожи во всех трёх вызовах, так что разберём только create:


# It is also common to receive messages from the client and
  # broadcast to everyone in the current topic (comments:lobby).
  def handle_in("CREATED_COMMENT", payload, socket) do
    case CommentHelper.create(payload, socket) do
      {:ok, comment} ->
        broadcast socket, "CREATED_COMMENT", Map.merge(payload, %{insertedAt: comment.inserted_at, commentId: comment.id, approved: comment.approved})
        {:noreply, socket}
      {:error, _} ->
        {:noreply, socket}
    end
  end

Сигнатура функции не изменилась, так что оставим её в покое. Первое, что мы делаем — добавляем оператор case для функции CommentHelper.create и передаём в неё payload и socket (вспомните про сопоставление с образцом, которое мы делали). Если приходит :ok вместе с созданным комментарием, мы транслируем в сокет сообщение CREATED_COMMENT вместе с некоторыми данными из базы, которых нет у Javascript. Если произошла ошибка, то не нужно ничего транслировать, просто возвращаем сокет и беззаботно идём дальше.



Заключение


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


Дизайн по-прежнему плох, так что нужно заняться и им. Для этого добавим Zurb Foundation 6 и создадим чистый внешний вид нашей блоговой платформы!


Скромное заключение от переводчика


Ребята! Ещё три десятка статей по Elixir на русском ждут вас на сайте нашего проекта под названием Вунш. Там же можно подписаться на прикольную рассылку и получать самые интересные новости по Эликсиру вместе с эксклюзивными статьями. Приглашаю вас также присоединиться к работе над переводом документации. А если появились вопросы, то подключайтесь к нашему чату и каналу в Телеграм.

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

https://habrahabr.ru/post/332094/


Метки:  

Автоматное программирование – новая веха или миф? Часть 2

Пятница, 07 Июля 2017 г. 08:41 + в цитатник
Первая часть публикации вызвала определённый интерес, пришёл ряд откликов, среди которых есть один, который хочется отметить особо: «жаль, нельзя скачать с гитхаба половину автомата и допилить под свою задачу, все надо делать самостоятельно. Если бы был некий стандарт записи автомата в какой-нибудь xml, позволяющий обмен автоматными алгоритмами, плюс некая «стандартная библиотека», возможно, все бы было иначе […] речь идёт о выдумывании какого-то «обобщенного состояния» и «обобщенного автомата», построении библиотеки таких автоматов с возможностью их комбинировать так же просто, как вызываются функции в языках». Отвечу читателю и всем, кто знаком с темой программных автоматов, но не удовлетворён нынешним положением дел (а оно в целом неудовлетворительное): мы обратимся именно к такой постановке вопроса, после того как будет достаточно очерчен предмет разговора.
Сегодняшняя статья посвящена теоретическим, идейным и психологическим аспектам автоматов. Рассмотрев их, мы снова вернёмся на прагматические позиции, которые были заявлены в начале цикла публикаций.


_________________________________________________________________________________
«Дисплей», рассмотренный в предыдущей статье, это сквозной пример, который словно нитью свяжет весь цикл. Мне не хотелось делать статью, рассчитанную на «подготовленного читателя», но в то же время не хочется давать примеры типа «пусть у нас есть кнопка и светодиод», потому что такие примеры, конечно, дают представление об автоматах, но они не дают никакого представления о преимуществе автоматного подхода.
Для тех, кто наткнулся на неочевидные моменты, просьба скидывать конкретные труднопроходимые места в коменты, прямо в виде коротких цитаток. Тема автоматного проектирования и тема автоматной реализации ещё будут затронуты, и ваши пожелания лягут в основу демонстрационного и поясняющего материала. Так же я слегка поправил первую статью, подробней расписав ход рассуждений при разработке операционного и управляющего автоматов (см, начиная с рисунка 10 а).
Желающим подтянуть матчасть советую ознакомиться с лекциями. Это качественный обзорный и учебный материал, охватывающий многие аспекты математических автоматов.


Автомат vs автомат



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

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


Связь между этими подходами несложно проиллюстрировать:


Рисунок 1. Автоматное проектирование и автоматная реализация

Насколько стало понятно из общения с читателями, существует категория формалистов, людей рассматривающих автоматы как:
  • сущности, описание которых должно строго укладываться в рамки UML State Diagrams или аналогичных способов описания, то есть иметь набор узлов, заданных в виде отдельных функций, набор сигналов, и формализованную таблицу, определяющую связи между ними.
  • понятие автоматно реализованной программы строго ограничивается принадлежностью к одной из техник реализации — boost.statechart, visualState, и т.д.

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

То, ради чего хочется использовать автоматы – простота и в то же время глубина проектирования. В предыдущей части было показано, что в основе автоматно-ориентированного проектирования модулей, лежит разбиение задачи на операционный автомат (ОА) и управляющий автомат (УА), причём операционный автомат в свою очередь может быть повторно разбит на операционный автомат нижнего уровня и его управляющий автомат.

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

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

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

Но в таком случае, что подразумевать под автоматно реализованной программой?

Реализация: автоматная vs не автоматная.



Главным атрибутом автоматно реализованной программы является:
  • наличие явно выделенных и чётко ограниченных состояний. В процессе функционирования программа всегда находится в одном из состояний.
  • текущее состояние программы описывается одной единственной переменной, которая называется Внутреннее состояние автомата.

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

Теперь есть чёткий критерий, по которому мы относим программы к автоматно реализованным программам, но кто-то спросит: в чём прикол автоматной реализации, почему в некоторых случаях она более ценна?

Главное, что отличает автоматно-реализованные алгоритмы от реализованных неавтоматно лежит в сфере нашей психики, а точнее того как мы мыслим. Как метко заметил коллега:
«Человеческий разум устроен так, что ему проще понимать алгоритмы, которым скармливают данные на входе и получают данные на выходе, и результат зависит только от входа, но не от внутреннего состояния. Такие «чистые функции» (назовём их аналитические прим.авт.) проще понимать, тестировать и использовать повторно».

Поведение аналитической функции можно представить в виде некоторой таблицы или графика: есть что-то на входе и есть однозначное соответствие на выходе. Однако цифровые устройства в большинстве таковы, что используя в качестве кирпичиков аналитические функции, в результате мы всё равно получаем программу, поведение которой зависит уже и от внутреннего состояния. То есть, использование аналитических функций не решает проблему «понимаемости», перемещая её на другой уровень!

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



а)



б)

Рисунок 2. Обобщённый пример управляющего устройства (а) и граф-схема описывающая работу этого устройства (б).

Некая программа предназначена для управления неким устройством. Как показано на рис 2 а, непосредственно «железом» управляет не уточняемый ОА, которым управляет УА, алгоритм работы которого изображён на рис. 2 (б). УА обрабатывает внешние команды, условно обозначаемые набором символов {0,1,2}, и транслирует их в набор микроинструкций, управляющих операционным автоматом. Под микроинструкцией я подразумеваю нужный для получения эффекта набор команд. Каждый набор микроинструкций условно обозначен символом {1,2,3,4,5,6}. Флаги {a,b,c} управляющего автомата отслеживают состояние управляемого объекта, и, соответственно, определяют режимы обработки входной команды.
Поскольку это цифровое устройство с памятью, описанный рис 2 алгоритм фактически является автоматом, несмотря на то, что реализация алгоритма неавтоматная. Это приводит к тому, что в нем нет явно выделенных состояний, в результате чего текущее состояние неявно определяется флагами. При этом описание программы граф-схемой само по себе не противоречит автоматному принципу. Существуют техники, позволяющие в некоторых случаях по алгоритму, описанному граф-схемой математически получать соответствующую диаграмму состояний и переходов. Граф-схемой, наконец, можно описать автоматно-реализованную программу, будет и такой пример. Проблема не в граф-схеме, а в неавтоматности реализации. Неавтоматная реализация ухудшает понимаемость и не даёт ключа к анализу динамических систем. Вот, что я имею в виду: это очень простой пример, но здесь нельзя однозначно сказать, какой выходной сигнал будет соответствовать входному сигналу 0, потому что это будет зависеть от состояния флагов, а точнее флага b, которое в свою очередь зависит от того, что было на входе ранее. Точно также непросто с ходу сказать, какая выходная последовательность будет соответствовать входной последовательности: 2,1,0,2,1,0. Для этого нужно фактически выполнить алгоритм.
Для того чтобы дать полное соответствие входных и выходных сигналов, то есть описать функцию в виде таблицы, потребуется произвести тотальное тестирование, да ещё и к тому же результат получится в виде двухсигнальных последовательностей, в которых по очереди перебираются всевозможные входные комбинации.


Рисунок 3. Временная диаграмма – способ описания поведения систем с памятью.

Поскольку три бинарных флага позволяют отслеживать не более (но возможно и не менее) 8ми предшествовавших символов, то для алфавита из 3х входных символов, чтобы описать все возможные варианты нам потребуется привести 6561 диаграмм, так называемая мощность произведения множества входных сигналов и множества состояний, которая с ростом числа состояний и размера алфавита входных сигналов растёт геометрически.

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


Рисунок 4. Диаграмма состояний и переходов соответствующая изображённому на рис 2 алгоритму.

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

Взгляд на динамические процессы вне временной оси.



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

Рассмотрим пример, пусть у нас есть последовательность команд

Set_position(6,0);
Line_to (1,0);  Line_to (1,1);  Line_to (-1,2);  Line_to (4,0);
Line_to (1,-3); Line_to (3,0);  Line_to (0,6);   Line_to (-11,0);
Line_to (-1,1); Line_to (-2,0); Line_to (3,-2);  Line_to (0,-2);
Line_to (1,2);  Line_to (2,0);  Line_to (-1,-2); Line_to (1,-1);

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


а) б)
Рисунок 5. Результат выполнения последовательности команд (а), и результат выполнения этой же последовательности, если допущена ошибка(б).

В то же время, ошибись я в расчётах, и укажи, например, в первом операторе второй строки вместо (1,-3) значение (2,-3) результат работы был бы иной (5 б), но глядя на текст программы этого нельзя понять. И это простой случай, когда результат можно увидеть сразу после выполнения. Если бы мы видели результат в виде отдельно взятой линии в каждый момент времени, или имели дело не с графикой, а с цифрами, наша ошибка была бы не столь очевидна.

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

Неплохим примером взгляда на динамические процессы вне временной оси является анализ сигналов в частотной области. Рассмотрим сигнал рис 6. В чём-то его можно сравнить с временной диаграммой автомата. Это тоже последовательность действий: сигнал пересёк 0, пошёл вверх, достиг максимума, пошёл вниз, снова пересёк 0.


Рисунок 6. График сигнала, аналог временной диаграммы для автоматов.

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


Рисунок 7. Спектр сигнала изображённого на рис 6.

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

Немного математики.



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


Рисунок 8. Изоморфные автоматы.

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

Построим автомат, изоморфный исходному, но у которого переименованы номера состояний как это показано на рис 9 и очертим на нём указанные кластеры. В кластере с состояниями 4,5,6 в скобках указаны идентичные состояния первого кластера.



Рисунок 9. Автомат, изоморфный изображённому на рис.4

Декомпозируем (разобьём) исходный автомат на два параллельных автомата, как показано на рис. 10.


Рисунок 10. Параллельная декомпозиция автомата показанного на рис 9.

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

Обратите внимание на Автомат 2. В каком бы состоянии он не находился, входной символ 0, приводит к появлению на выходе символа 1, входной символ 1 к появлению на выходе символа 3, а символ 2 к появлению символа 2. То есть, фактически это комбинационная схема, массив выходных символов, а индекс массива — символ на входе. Изобразим автомат как это показано на рис. 11


Рисунок 11. Автомат эквивалентный автомату изображённому на рис. 10

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

Подчеркну особо, поскольку символы 0,1,2 на входе и символы 1,2,3 на выходе относятся к разным алфавитам, то нельзя просто так взять и подать символ 1 с выхода обратно на вход. Однако, могут быть такие автоматы, в которых входной и выходной символы принадлежат одному алфавиту и в этом случае выходные символы автомата можно подавать на его вход. Это называется композиция с обратной связью. Таким композициям посвящён параграф 4.7 лекций.

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

Рассмотренный пример затрагивает ещё одно важное и полезное свойство автоматов, понятие эквивалентных автоматов. Дело в том, что может существовать сколь угодно много автоматов, с разным количеством состояний (т.е. речь идёт не об изоморфных автоматах), которые на одну и ту же входную последовательность дадут одинаковый отклик. Соответственно, если поместить их в «чёрный ящик», то нельзя будет отличить их, подавая на вход разные последовательности и анализируя отклик. Одни автоматы при этом будут более «расточительны» с точки зрения количества внутренних состояний, другие более «экономны». Среди всего множества эквивалентных автоматов будет автомат с минимально возможным количеством состояний, и он называется минимальный автомат. Более того, существуют алгоритмические методики получения из любого автомата эквивалентного ему минимального. Это свойство в частности означает, что при составлении диаграммы состояний и переходов не следует гнаться за минимизацией числа состояний, но следует добиться максимально ясной и полной картины. И хотя часто понимаемость и простота реализации связаны, может оказаться, что нагляднее представить результат в виде пары автоматов как в нашем примере. После этого, при помощи математических алгоритмов можно найти эквивалентный минимальный автомат.

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

Подведём итог сегодняшней части. Характерная черта неавтоматного программирования, это то, что состояние программы в каждый момент времени описывается не только программным счётчиком, но и некоторым количеством внутренних флагов. Термин состояние при неавтоматном стиле программ это некое не формализуемое понятие, означающее примерно то, что программа выполняет все действия, которые требует ТЗ. И тем не менее, как это было показано выше, даже при неавтоматном стиле программы, математически она – автомат. Она обладает состояниями в математическом смысле, но состояния эти нигде не описаны. Неизвестно сколько их и какие между ними связи. Добавление каждого нового двоичного флага увеличивает количество возможных состояний геометрически. Многие новые состояния при этом будут недостижимыми состояниями, в которые программа не должна попасть никогда ни при каких условиях, но поскольку в этом случае мы не выбираем следующее состояние явно, но оно получается как суперпозиция всех флагов, при неверной логике хоть одного из флагов программа может скакать в запрещённые состояния и нет индикатора, который демонстрировал бы это. Когда мы имеем дело с флагами, которые активно меняются, а путь программы извилист и проходит множество ветвлений, то до тех пор пока не будут протестированы все варианты развилок для всех возможных входных символов, нам остаётся только верить, что после -дцатой итерации программа окажется именно в том состоянии, которое мы ожидаем.

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

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

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

Список рекомендованной литературы. Если есть потрясающий сюжет про автоматы, пишите мне, я добавлю.
Лекции новичкам, тем кто подзабыл и вообще.
Очень сильные лекции с примерами
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332508/


[Перевод] Защищаем сайт с помощью ZIP-бомб

Четверг, 06 Июля 2017 г. 23:32 + в цитатник

Старые методы по-прежнему работают


[Обновление] Теперь я в каком-то списке спецслужб, потому что написал статью про некий вид «бомбы», так?

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

Когда я в возрасте 13 лет впервые захостил свою маленькую Linux-коробочку с доступом по SSH, я смотрел логи и каждый день видел IP-адреса (в основном, из Китая и России), которые пытались подключиться к моей сладенькой маленькой коробочке (которая на самом деле была старым ноутом ThinkPad T21 со сломанным дисплеем, жужжавшим под кроватью). Я сообщал эти IP их провайдерам.

На самом деле если у вас Linux-сервер с открытым SSH, то можете сами посмотреть, сколько попыток подключений происходит ежедневно:

grep 'authentication failures' /var/log/auth.log


Сотни неудачных попыток авторизации, хотя на сервере вообще отключена авторизация по паролю и он работает на нестандартном порту

Wordpress нас приговорил


Ладно, признаем, сканеры веб-уязвимостей существовали и до Wordpress, но после того, как эта платформа стала настолько популярной, большинство сканеров начали проверять неправильно сконфигурированные папки wp-admin и непропатченные плагины.

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


Образец логов при сканировании инструментом Nikto

Вот почему все серверы и админы веб-сайтов имеют дело с гигабайтами логов, полными попыток сканирования. Так что я подумал…

Можно ли нанести ответный удар?


После экспериментов с возможностью потенциального применения IDS или Fail2ban я вспомнил о старых добрых ZIP-бомбах из прошлого.

Что за штука такая — ZIP-бомба?


Как выяснилось, сжатие ZIP великолепно справляется с повторяющимися данными, так что если у вас имеется гигантский текстовый файл, заполненный повторяющимися данными вроде всех нулей, он очень хорошо сожмётся. В смысле, ОЧЕНЬ хорошо.

Как показал 42.zip, можно сжать 4,5 петабайта (4 500 000 гигабайт) в 42 килобайта. Когда вы попытаетесь посмотреть содержимое архива (извлечь или разархивировать его), то у вас, вероятно, израсходуется всё дисковое пространство или оперативная память.

Как спустить ZIP-бомбу на сканер уязвимостей?


К сожалению, веб-браузеры не понимают ZIP, но зато они понимают GZIP.

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

dd if=/dev/zero bs=1M count=10240 | gzip > 10G.gzip


Создание бомбы и проверка её размера

Как видите, её размер 10 МБ. Можно было сжать и получше, но пока хватит.

Теперь установим PHP-скрипт, который доставит её клиенту.

https://habrahabr.ru/post/332580/


Метки:  

[Перевод] Правда ли уже пора использовать CSS Grid Layout?

Четверг, 06 Июля 2017 г. 20:05 + в цитатник

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


Уже после приземления я подумала, что фраза «это не ваша вина, но ваша проблема» отлично подходит практически к любым ситуациям. В этой статье я раскрываю тему поддержки старых браузеров при использовании новых технологий наподобие CSS Grid Layout. Мы, разработчики, часто робеем при обсуждении браузерной поддержки с заказчиками и коллегами, как будто это мы виноваты в том, что сайты не выглядят в IE9 в точности так же, как в новейших Firefox или Chrome. Пора нам уже принять, что это не наша вина. Но обязанность справиться с этим как следует, с пользой для каждого — во многом наша проблема.


Гриды совсем новые! У них наверняка ужасная поддержка в браузерах?


CSS Grid Layout уже работает в Chrome, Firefox, Opera и Safari с марта этого года. Microsoft Edge недавно выпустил предварительную сборку с гридами за флагом. На момент выхода статьи Can I Use показывает, что глобальная поддержка CSS Grid Layout составляет 65.64%, или 70.75%, если добавить версию с префиксом из IE10-11 и теперешнего Edge. До сих пор мы не видали, чтобы настолько грандиозная новинка внедрялась так быстро. Неудивительно, что люди не осознают, у какого множества посетителей поддержка будет.


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


Зачем мне использовать гриды?


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


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


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


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


Можно накладывать элементы друг на друга, они подчиняются свойству z-index, так что разные элементы можно помещать в одни и те же грид-ячейки, что дает массу простора для творчества.


А как же неподдерживающие браузеры?


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


Таким образом, если вы хотите использовать флоаты, инлайн-блоки, многоколоночную раскладку, флексбоксы или даже display: table в качестве фолбэка для своей раскладки на гридах, в спецификации уже всё предусмотрено. Можете переопределять эти методы надежным и предсказуемым способом. Я сделала шпаргалку с пояснением фолбэков. О некоторых из них говорится в моем докладе, записанном на конференции Render ранее в этом году.


В CSS также есть проверка наличия возможностей. У нее поистине замечательная поддержка браузерами, и что особенно радует в связи с ней, вам не нужно беспокоиться о браузерах без ее поддержки. Не бывает браузеров, поддерживающих гриды и не поддерживающих supports. Вот всё, что нужно вам в CSS-файле:


  1. CSS для фолбэка
  2. CSS для гридов

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


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


Мы пишем CSS с помощью CSS. Никаких полифилов, никаких хаков. Всё строго по спецификации.


Но фолбэки означают, что я пишу раскладку дважды!


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


Вот статья, которую я написала в 2002 г. В 2002-м люди боялись изучать верстку на CSS, потому что это значило бы, что их сайты не будут «одинаково отображаться» во всех браузерах. Но я верстала сайты с помощью CSS, стараясь выяснить, как это можно сделать наилучшим образом, и учила других людей тому, что узнавала сама. С самого открытия собственной фирмы, делая сайты для клиентов, требующих, чтоб всё работало в Netscape 4. Я занимаюсь этим на протяжении всей своей карьеры. Я разбираюсь с проблемами совместимости уже 20 лет. Сейчас я делаю продукт с интерфейсом, который должен работать вплоть до IE9. Не моя вина, что эти старые браузеры существовали, но моя проблема и моя работа все эти годы как раз в том и состояла, чтобы справляться с ними.


Если ваш сайт действительно должен выглядеть одинаково во всех браузерах (что бы это для вас ни значило), вы не сможете использовать ничего, что можно сделать только гридами. В таком случае не используйте гриды! Используйте Grid Layout, если хотите добиться чего-то, чего никак не сделать нормально старыми технологиями. Затем делайте фолбэк, которым можно будет пользоваться в менее продвинутых браузерах, и не беспокойтесь о том, чтобы сделать в точности так же. Мощь гридов в том, что с ними можно делать такое, что раньше было невозможным. Используйте их для этого, а не для воссоздания своих старых дизайнов.


Хочу волшебный полифил!


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


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


Вот что значит разрабатывать для веба


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


Ваша работа состоит в том, чтобы изучать новое и советовать своему клиенту или руководству, как наилучшим способом реализовать их бизнес-цели при помощи всех доступных технологий. А для этого вы должны сначала сами изучить эти новинки. Тогда вы сможете советовать им, на какие именно компромиссы пойти стоит. Гарантировать единообразный дизайн ценой добавочной разметки, лишнего времени на разработку или вынужденного ограничения удобства для всех браузеров? Или упрощенный макет для IE9, что позволит сократить время разработки, и более быстрый сайт благодаря новым технологиям в итоге? Если вы понимаете плюсы и минусы каждого варианта, вы сможете отстоять свои аргументы.


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


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


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


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


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


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


Вот к чему мы идем


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


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

А вы уже используете CSS Grid Layout в своих проектах?

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

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

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

https://habrahabr.ru/post/332572/


Метки:  

Moya — как перестать беспокоиться о сетевой части и начать жить

Четверг, 06 Июля 2017 г. 19:40 + в цитатник
Хай! Вам знакомо то чувство уныния, когда нужно интегрировать проект с очередным RESTful API? Это когда в очередной раз нужно создавать какой-нибудь APIManager и наполнять его Alamofire запросами, а потом связывать их с моделями маппинга данных. Лично я стараюсь максимально оптимизировать всю свою работу, поэтому регулярно изучаю различные библиотеки чтобы не писать кучу повторяющегося кода и избавиться от рутины. В один из таких заходов я наткнулся на отличную библиотеку Moya, о которой и пойдёт речь.

Первое знакомство


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

Начинаем интеграцию


Создадим Single-View Applicaton и и подключим библиотеку к нашему проекту (для маппинга я предпочитаю библиотеку ObjectMapper, для подключения сторонних зависимостей — CocoaPods)

Podfile
platform :ios, '9.0'

def app_pods
pod 'ObjectMapper', '~> 2.2'
pod 'Moya'
pod 'Moya-ObjectMapper'
end

target 'MoyaExample' do
use_frameworks!
app_pods

# Pods for MoyaExample

target 'MoyaExampleTests' do
inherit! :search_paths
app_pods
end

end


Далее нам нужно создать файл с запросами, делается это так:

import Moya

enum MoyaExampleService {
    case getRestaurants(page: Int?, perPage: Int?)
}

extension MoyaExampleService: TargetType {
    var baseURL: URL { return URL(string: "http://moya-example.svyatoslav-reshetnikov.ru")! }
    var path: String {
        switch self {
        case .getRestaurants:
            return "/restaurants.json"
    }
    var method: Moya.Method {
        return .get
    }
    var parameters: [String: Any]? {
        return nil
    }
    var parameterEncoding: ParameterEncoding {
        return URLEncoding.default
    }
    var sampleData: Data {
        return Data()
    }
    var task: Task {
        return .request
    }
}

В этом файле происходит настройка запросов. В самом начале мы видим enum — это наш будущий сервис со всеми запросами. Можно запихнуть все запросы в один сервис, но в больших проектах я рекомендую придерживаться буквы I из SOLID и не превращать файл в кашу. После перечисления всех запросов в enum нам нужно расширить класс протоколом TargetType. Давайте рассмотрим подробней содержание этого протокола:

1. var baseURL — это адрес сервера, на котором лежит RESTful API.
2. var path — это роуты запросов.
3. var method — это метод, который мы хотим послать. Moya ничего не придумывает и берёт все методы из Alamofire.
4. var parameters — это параметры запроса. На данном этапе библиотеку не волнует будут ли эти параметры в теле запроса (POST) или в url (GET), эти нюансы определяются позже. Пока просто пишем параметры, которые мы хотим передать в запросе.
5. var parameterEncoding — это кодировка параметров, также берётся из Alamofire. Можно сделать их как json, можно как url, можно как property list.
6. var sampleData — это так называемые stubs, используются для тестирования. Можно взять стандартный ответ от сервера, сохранить его в проекте в формате JSON и затем использовать в unit тестах.
7. var task — это задача, которую мы будем выполнять. Их всего 3 — request, download и upload.

Применяем в проекте


Для того, чтобы начать использовать Moya, нам необходимо создать Provider — это абстракция библиотеки, которая даёт доступ к запросам:

let provider = MoyaProvider()

После этого можно жениться делать запрос с помощью provider:

provider.request(.getRestaurants()) { result in
    switch result {
    case .success(let response):
        let restaurantsResponse = try? response.mapObject(RestaurantsResponse.self)
        // Do something with restaurantsResponse
    case .failure(let error):
        print(error.errorDescription ?? "Unknown error")
    }
}

Добавляем реактивности


Moya поддерживает ReactiveSwift и RxSwift. Лично я предпочитаю последнюю библиотеку, поэтому мой пример будет для неё. Для начала давайте добавим нужные зависимости:

Podfile
platform :ios, '9.0'

def app_pods
pod 'ObjectMapper', '~> 2.2'
pod 'Moya'
pod 'Moya-ObjectMapper'
pod 'Moya/RxSwift'
pod 'Moya-ObjectMapper/RxSwift'
end

target 'MoyaExample' do
use_frameworks!
app_pods

# Pods for MoyaExample

target 'MoyaExampleTests' do
inherit! :search_paths
app_pods
end

end

И наш код трансформируется следующим образом:

let provider = RxMoyaProvider()
    provider.request(.getRestaurants())
        .mapObject(RestaurantsResponse.self)
        .catchError { error in
            // Do something with error
            return Observable.error(error)
        }
        .subscribe(
            onNext: { response in
                self.restaurants = response.data
            }
        )
        .addDisposableTo(disposeBag)

Пара трюков с Moya


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

1. Добавить что-нибудь в заголовок запроса (например, basic auth)
Сначала сделаем requestClosure — это замыкание, в котором мы можем модифицировать отправляемый запрос:

let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
    var request = endpoint.urlRequest
    request?.setValue("set_your_token", forHTTPHeaderField: "XAuthToken")
    done(.success(request!))
}

Этот requestClosure надо обязательно добавить в provider:

let provider = RxMoyaProvider(requestClosure: requestClosure)

2. Продебажить запрос

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

let provider = RxMoyaProvider(plugins: [NetworkLoggerPlugin(verbose: true)])

Unit тесты


Я предпочитаю BDD стиль тестов, поэтому для unit-тестирования будем использовать библиотеки Quick и Nimble. Добавим их в наш Podfile:

Podfile
platform :ios, '9.0'

def app_pods
pod 'ObjectMapper', '~> 2.2'
pod 'Moya'
pod 'Moya-ObjectMapper'
pod 'Moya/RxSwift'
pod 'Moya-ObjectMapper/RxSwift'
end

def test_pods
pod 'Quick'
pod 'Nimble'
end

target 'MoyaExample' do
use_frameworks!
app_pods

# Pods for MoyaExample

target 'MoyaExampleTests' do
inherit! :search_paths
app_pods
test_pods
end

end

Теперь пишем небольшой тест:

import Quick
import Nimble
import RxSwift
import Moya
@testable import MoyaExample

class NetworkTests: QuickSpec {
    
    override func spec() {
        var testProvider: RxMoyaProvider!
        let disposeBag = DisposeBag()
        
        beforeSuite {
            testProvider = RxMoyaProvider(stubClosure: MoyaProvider.immediatelyStub)
        }
        
        describe("testProvider") {
            it("should be not nil") {
                expect(testProvider).toNot(beNil())
            }
        }
        
        describe("getRestaurants") {
            it("should return not nil RestaurantsResponse object") {
                testProvider.request(.getRestaurants())
                    .mapObject(RestaurantsResponse.self)
                    .subscribe(
                        onNext: { response in
                            expect(response).toNot(beNil())
                    }
                    )
                    .addDisposableTo(disposeBag)
            }
        }
    }
}

Запускаем тесты, убеждаемся что они пройдены, после чего убеждаемся что сетевая часть покрыта тестами на 100% (как включить code coverage в xcode читайте здесь).

Заключение


В этой статье я хотел дать читателям базовое представление о мощной сетевой библиотеке Moya, намеренно опустив нюансы для того, чтобы вы самостоятельно смогли исследовать её и насладиться развитым инструментарием, который позволяет решать широкий спектр задач при выстраивании сетевого слоя в iOS разработке. Исходный код ждёт Вас на Github.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332570/


Метки:  

Работа с API КОМПАС-3D -> Урок 3 -> Корректное подключение к КОМПАС

Четверг, 06 Июля 2017 г. 19:05 + в цитатник
В предыдущих уроках по API КОМПАС (Напоминаем, что в качестве среды используется C++ Builder) Основы и Оформление чертежа мы исходили из того, что КОМПАС не запущен, и запускали его сами методом CreateInstance. Но что если в момент вызова этого метода КОМПАС уже запущен? Тогда будет создан еще один экземпляр данной программы. В принципе ничего страшного, но неаккуратно. Зачем плодить копии программы, когда можно обойтись одним экземпляром?



Сегодня мы поговорим о том, как подключаться к уже запущенному КОМПАС, чтобы не создавать картину, похожую на ту, которая изображена на рисунке ниже.


Запущено несколько экземпляров КОМПАС-3D

Подключение к КОМПАС


Для подключения к программе КОМПАС используется метод ActiveInstance. Ниже приводится пример программы, подключающейся к КОМПАС.

KompasObjectPtr kompas;
kompas.ActiveInstance(L"KOMPAS.Application.5");

//Делаем КОМПАС видимым
kompas->Visible = true;
kompas.Unbind();

Единственный параметр метода ActiveInstance – строковое наименование интерфейса, к которому мы подключаемся, в кодировке Unicode.

А что будет, если в момент вызова этого метода КОМПАС не запущен? Произойдет ошибка. Причем пользователю будет показано сразу два окна с ругательствами.


Первое окно с ошибкой


Второе окно с ошибкой

Формат этих окон зависит от используемой среды разработки и может отличаться от приведенных выше. Оборачивание вызова метода ActiveInstance в блок try/catch, к сожалению, не решает проблему.

try{

KompasObjectPtr kompas;
kompas.ActiveInstance(L"KOMPAS.Application.5");
//Делаем КОМПАС видимым
kompas->Visible = true;
kompas.Unbind();

}catch(...){}

Мы избавляемся только от одного окна с ошибкой. Получается, что вызывать метод ActiveInstance можно только тогда, когда КОМПАС запущен. И здесь мы приходим к главному вопросу: как определить, запущен КОМПАС или нет? Для этого существует несколько методов.

По главному окну


Самый распространенный способ – с помощью функции FindWindow найти главное окно программы. Функция FindWindow ищет окно по его заголовку или по наименованию его оконного класса. К сожалению, она требует точного совпадения строк. Искать по части строки она не умеет.
Заголовок окна мы не можем использовать, так как он включает в себя версию КОМПАС, которая заранее нам неизвестна, и дополнительную информацию, например, наименование открытого документа. Поэтому мы не можем знать наверняка точную строку в заголовке окна. Попробуем по наименованию оконного класса.

Узнать его можно с помощью программы Spy++. На рисунке ниже приведена примерная информация об оконном классе (наименование обведено в красный прямоугольник).


Окно «Свойства окна»

Наименования оконного класса мало того, что не отличаются наглядностью, так еще и различаются в разных версиях КОМПАС. Поэтому поиск по наименованию оконного класса нам также не подходит.

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

//Функция обратного вызова для поиска окна
bool CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
//Получаем размер заголовка окна
unsigned int size;
size = GetWindowTextLength(hwnd);
if(!size) return true;
//Подготавливаем буфер под заголовок окна
wchar_t* pbuffer;
pbuffer = (wchar_t*)malloc(sizeof(wchar_t)*(size+1));
//Читаем заголовок окна
GetWindowTextW(hwnd, pbuffer, size-1);
//Ищем подстроку
wchar_t *p;
p = wcsstr(pbuffer, L"КОМПАС-3D");
//освобождаем память
free(pbuffer);
if(!p) return true;
//Окно найдено, сохраняем результат и останавливаем поиск
bool *pres;
pres = (bool*)lParam;
*pres = true;
return false;
}
//Функция проверки запущен ли КОМПАС?
bool IsKOMPASRun()
{
bool res = false;
EnumWindows((WNDENUMPROC)EnumWindowsProc, (LPARAM)(&res));
return res;
}

Для перечисления окон используется функция EnumWindows, входящая в состав Windows API. Данная функция подготавливает список окон верхнего уровня и для каждого найденного окна вызывает пользовательскую функцию EnumWindowsProc. В данной функции мы читаем заголовок найденного окна и проверяем, содержит ли он подстроку «КОМПАС-3D». Если содержит, то окно найдено и останавливаем поиск, если нет – переходим к следующему окну. Ниже приводится пример использования данной процедуры.

if(IsKOMPASRun())
ShowMessage("КОМПАС запущен");
else
ShowMessage("КОМПАС не запущен");

К сожалению, данный метод очень ненадежен. Дело в том, что в системе могут быть другие окна, содержащие в своем заголовке подстроку «КОМПАС-3D». Пример такого окна приведен на рисунке 4. Это явно не то окно, которое мы хотим найти.


Окно справки

По процессу


Другим вариантом является поиск процесса КОМПАС. У программы КОМПАС исполняемый файл обычно именуется «kompas.exe» (в разных версиях может различаться регистр). Что если вместо окна искать процесс с таким наименованием исполняемого файла? Ниже приводится исходный текст программы, реализующей данный метод.

bool IsKOMPASRun()
{
//Имя исполняемого файла, который мы ищем
char ExeName[] = "kompas.exe";
size_t lenName = strlen(ExeName);
//Делаем снимок системы
HANDLE hSnapshot;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//Перечисляем процессы
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapshot, &entry);
size_t len;
bool res = false;
do{
//Сравниваем наименования исполняемых файлов
len = strlen(entry.szExeFile);
if(len != lenName) continue;
if(!strnicmp(entry.szExeFile, ExeName, len))
{
res = true;
break;
}
}while(Process32Next(hSnapshot, &entry));
CloseHandle(hSnapshot);
return res;
}

В данном примере для перечисления процессов используются функции CreateToolhelp32Snapshot, Process32First, Process32Next, входящие в состав Windows API. Для их использования необходимо подключить заголовочный файл tlhelp32.h. Это не единственный способ перечисления процессов, но один из самых простых. Для сравнения строк используется функция strnicmp, которая сравнивает строки без учета регистра символов.

Способ, основанный на поиске процессов, надежнее поиска окна. Он дает значительно меньше ложных срабатываний, но не исключает их. Что если на компьютере пользователя запущена программа с точно таким же наименованием исполняемого файла? Или в последующих версиях КОМПАС исполняемый файл будет называться по-другому? Во всех этих случаях данный метод не работает.

С использованием технологии COM


Все описанные выше методы громоздки и ненадежны. Поэтому их использование нежелательно. Существует более надежный способ проверки факта запуска программы КОМПАС. Он основан на функциях библиотеки ole32.dll, которая входит в состав Windows и реализует технологию COM. Ниже приводится исходный код процедуры, проверяющей с помощью этих функций, запущен ли КОМПАС.

bool IsKOMPASRun()
{
wchar_t ObjectName[] = L"KOMPAS.Application.5";
//Инициализируем библиотеку Ole32.dll
CoInitialize(NULL);
CLSID clsid;
//Получаем clsid объекта
CLSIDFromProgID(ObjectName, &clsid);
//Пытаемся подключиться
HRESULT res;
IUnknown *pIUnknown;
res = GetActiveObject(clsid, NULL, &pIUnknown);
if(res == S_OK)
{
pIUnknown->Release();
return true;
}
return false;
}

Основную работу выполняет функция GetActiveObject. С ее помощью мы пытаемся подключиться к КОМПАС. Если это удалось, значит, КОМПАС запущен. Функция CLSIDFromProgID используется для конвертирования строкового представления объекта в его CLSID (уникальный 128-битный идентификатор). Ее можно использовать для проверки того, установлен КОМПАС на компьютере пользователя или нет. Ниже приводится пример программы, реализующей такую проверку.

bool IsKOMPASInstalled()
{
wchar_t ObjectName[] = L"KOMPAS.Application.5";
//Инициализируем библиотеку Ole32.dll
CoInitialize(NULL);
CLSID clsid;
//Получаем clsid объекта
HRESULT res;
res = CLSIDFromProgID(ObjectName, &clsid);
return (res == S_OK);
}

Корректное подключение


Ниже приводится исходный текст программы, реализующей корректное подключение к КОМПАС.

wchar_t ObjectName[] = L"KOMPAS.Application.5";

……………………………………………………………

if(! IsKOMPASInstalled())
{
   ShowMessage("КОМПАС не установлен");
   return;
}

KompasObjectPtr kompas;

if(IsKOMPASRun())
   kompas.ActiveInstance(ObjectName);
else
   kompas.CreateInstance(ObjectName);

kompas->Visible = true;
kompas.Unbind();

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

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

В конце статьи приведен пример программы, реализующей подключение к КОМПАС с проверкой на его наличие в системе и работу в момент запуска программы.

Продолжение следует, следите за новостями блога.

Сергей Норсеев, автор книги «Разработка приложений под КОМПАС в Delphi».
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332554/


Метки:  

Веб-разработка: как распознать проблемного клиента на старте

Четверг, 06 Июля 2017 г. 17:50 + в цитатник
Моя компания НеВсем давно уже прочно обосновалась на первых местах по запросам, связанным с аудитом сайтов во многих городах Поволжья. Вот уже несколько лет мы делаем их все больше и больше, поэтому о качестве веб-сайтов и о том, как ведется разработка и подготовительный этап, знаем очень хорошо. И со стороны клиента и со стороны студии.

Бывает так, что веб-студии виноваты только в том, что вообще взялись за эти проекты (да-да, виноваты в 99% случаев обе стороны, и было бы интересно почитать ответную статью от клиентов веб-студий).

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

1. Нет понимания, зачем?


Слово «зачем» подразумевает цели, выраженные в цифрах – деньги, сроки, объемы реализации, глобальные цели компании. Особенно важно участие ЛПР или владельцев бизнеса на этом этапе.

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

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

2. У меня это в первый раз…


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

2.1. Нет доверия


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

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

Построить доверительные отношения можно только постоянным общением и обучением. Но здесь я бы время свое не стал бы вкладывать. Потому что клиент хочет все…

2.2. «За слишком дешево»


Объяснять про процессы в студии, стоимость нормо-часа и прочее бесполезно. Ведь вы в итоге все равно по ощущениям клиента продаете «воздух». Донести, что сайт – это образ компании в интернете, достаточно сложно. Хотя образа-то никакого может и не быть, если заказчик описывает себя в форме «мы такие, как все».

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

2.3. Синдром пропавшего клиента


Для новичков очень характерная черта – появляться и пропадать в любое время без возможности дозвониться или как-то связаться. Поэтому никаких работ до заключения договора и поступления на счет денег делать ни в коем случае нельзя.

2.4. Пустышка без контента


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

Финиш.

3. Здравствуйте, я новый менеджер


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

Тратятся время, деньги. Долгие согласования, вымученный результат…Новый сайт работает еще хуже, чем старый, а менеджер уходит из компании спустя 3-4 месяца.

4. Слишком много ожиданий


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

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

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

5. Перфекционизм клиента


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

Когда у компании на проверку своей бизнес-гипотезы всего 4-5 месяцев, а штаны уже готовы вот-вот упасть, не до проверки запятых в тексте. Нужны продажи.

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

Поэтому главная задача разработки – выдать минимально готовый продукт по требованиям ТЗ, а не работа ради работы. Это долгострой, который в итоге из-за быстро меняющейся среды через полгода умираем сам собой.

6. Мы точно знаем, чего хотим


Клиент такого типа рассматривает разработчика в качестве «литературного негра» и не понимает, что сотрудничество подразумевает обмен мыслями обеих сторон.

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

В итоге заказчик влезает во все процессы, и если PM даст прямой доступ к дизайнеру и программистам, нервный срыв им обеспечен.

7. С порога навязывают свои условия


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

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

8. Нет распределения ролей/обязанностей


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

P.S. А как срабатывает ваша «чуйка»? Когда внутренний голос говорит вам: «не лезь в это дело, дружище»?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332564/


Метки:  

Android Architecture Components. Часть 1. Введение

Четверг, 06 Июля 2017 г. 17:47 + в цитатник
image

На Google I/O 2017, было представлено набор библиотек под названием Android Architecture Components. В нескольких словах — это ряд вспомогательных библиотек, которые призваны помочь с такими вещами как, проектирование, тестирование и сопровождение приложений. То, что команда разработки Android начала акцентировать внимание на архитектуре не может не радовать, поскольку проблема является действительно актуальной. Ведь изначально не было предоставлено никаких требований или гайдлайнов по проектированию, и разработчику приходилось отталкиваться от своего предыдущего опыта. Что, в свою очередь, вызывало сложности в сопровождении проекта, а также сомнительные решения для специфических для ОС ситуаций. По факту это не первые шаги в этом направлении. Ранее уже Google представил репозиторий android-architecture с примерами применения разных архитектурных концептов. Надеемся, что развитие будет дальше и может на следующем Google I/O мы сможем увидеть полноценный фреймворк.

В целом Android Architecture Components можно разделить на четыре блока: Lifecycles, LiveData, ViewModel и Room Persistence.

Компонент Lifecycle – призван упростить работу с жизненным циклом. Выделены основные понятия такие как LifecycleOwner и LifecycleObserver.

LifecycleOwner – это интерфейс с одним методом getLifecycle(), который возвращает состояние жизненного цикла. Являет собой абстракцию владельца жизненного цикла (Activity, Fragment). Для упрощения добавлены классы LifecycleActivity и LifecycleFragment.

LifecycleObserver – интерфейс, обозначает слушателя жизненного цикла owner-а. Не имеет методов, завязан на OnLifecycleEvent, который в свою очередь разрешает отслеживать жизненный цикл.

Что это нам дает?

Назначение этого компонента – избавить разработчика от написания рутинного кода и сделать его более читаемым. Довольно частая ситуация, когда в нашем приложении работает ряд процессов, которые зависят от этапа жизненного цикла. Будь-то воспроизведение медиа, локация, связь с сервисом и т.д. Как итог нам приходится вручную отслеживать состояние и уведомлять о нём наш процесс. Что неудобно по двум причинам, захламление основного класса (Activity или Fragment) и снижение модульности, ведь нам нужно позаботиться про поддержку передачи состояния. С помощью же этого компонента мы можем переложить всю ответственность на наш компонент и все что для этого нужно это объявить интересующий наш класс как observer и передать ему в onCreate() методе ссылку на owner. В общем это выглядит так:

class MyActivity extends LifecycleActivity {
    private PlayerWrapper mPlayerWrapper;
    public void onCreate(…) {
       mPlayerWrapper = new PlayerWrapper (this, getLifecycle());
    }
}

class PlayerWrapper implements LifecycleObserver {
   private PlayerController mController;
   public MyLocationListener(Context context, Lifecycle lifecycle) {
      //init controller
   }
   @OnLifecycleEvent(Lifecycle.Event.ON_START)
   void start() {
     mController.play();
   }
   @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
   void stop() {
      mController.stop();
   }
}

Наш обсервер абсолютно осведомлен о состоянии и может самостоятельно обрабатывать его изменение.

Компонент LiveData – являет собой holder класс для хранения объекта, а также разрешает подписаться к нему. LiveData знает про жизненный цикл и разрешает от него абстрагироваться.

Для имплементации компонента нам нужно расширить класс LiveData. Для работы нам нужно знать всего три метода из этого класса.

onActive() – этот метод вызывается когда у нашего экземпляра есть активный(-ые) обсервер. В нем мы должны инициировать интересующий нас сервис или операцию.

onInactive() – вызывается когда у LiveData нет активных слушателей. Соответственно нужно остановить наш сервис или операцию.

setValue() – вызываем если изменились данные и LiveData информирует об этом слушателей.

class ChatLiveDataHolder extends LiveData{
  
   private static ChatLiveDataHolder sInstance;
   private ChatManager mChatManager;
   private ChatListener mChatListener = new ChatListener(){
      @Override
      public void newMessage(Message message){
         setValue(message);
      }
   }
   public static ChatLiveDataHolder get() {
      if (sInstance == null) {
         sInstance = new ChatLiveDataHolder();
      }
      return sInstance;
   }
   private ChatLiveDataHolder(){
      //init mChatManager and set listener
   }
   @Override
   protected void onActive() {
      mChatManager.start();
   }
   @Override
   protected void onInactive() {
      mChatManager.stop();
   }
}

Если вы обратили внимание, то мы реализовали наш класс как Singleton. Это дает нам возможность использовать LiveData в других Activity, Fragment и т.д без переинициализации, если это нам не нужно.

Для того чтоб подписать слушателя, тоже никаких проблем нет. Все что нужно это вызвать метод observe у нашего экземпляра LiveData, передать в него LifeCycleOwner и реализацию интерфейса Observer. Интерфейс Observer имеет всего один метод onChanged(T t), с помощью него LiveData будет информировать слушателей об изменении в данных(вызов метода setValue(T t) в LiveData).

Что это нам дает?

Плюсов действительно много, начиная от защиты от memory leaks(Observer связан со своим Lifecycle и автоматически отписывается в случае, когда его Lifecycle уничтожен), защита от остановленной Activity(если, Lifecycle неактивен(stopped), то и нотификации на Observer не будут отправляться). С функциональных особенностей, это единый доступ к данным(с помощью singleton) и сбережение наших данных(Для таких операций как пересоздание активити, фрагмента). В целом же, назначение все то же, избавить разработчика от рутинной работы связанной с жизненным циклом.

Компонент ViewModel — спроектирован для хранения и управления данными которые связанные с представлением.

Задача же данного компонента, помочь разработчику абстрагировать данные и предоставить их хранение между такими операциями как пересоздание Activity. Если же нам необходимо сохранить небольшой набор данных, таких как item в RadioButtonGroup или же введенный данные, нам отлично подходит Bundle в onSaveInstanceState(). Но если это большой список к примеру: пользователей, товаров, каталог чего-нибудь нам приходилось заново доставать этот список. Вот в этом случае ViewModel является нашим основным помощником. Особенностью данного компонента является то что он привязывается к Activity и автоматически сохраняет свое состояние во время таких операций как onCofigurationChange().

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

public class OurModel extends ViewModel {
    private List userList;
    public List  getUserList() {
        return userList;
    }
     public void setUserList(List list) {
        this.userList = list;
    }
}

И это все, наш холдер для userList готов. Для того чтоб использовать наш холдер необходимо в методе onCreate(..) активити вызвать instance нашей модели:

@Override
protected void onCreate(Bundle savedInstanceState){
   // init UI etc.
   OurModel model = ViewModelProviders.of(this).get(OurModel.class);
   If (model.getUserList()==null){
      downloadData();
   } else {
      showData();
   }
}

С помощью ViewModelProviders, мы берем instance нашей модели. A c помощью if конструкции смотрим есть ли у нас уже данные в нашей модели или еще нет.

Что это нам дает?

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

Компонент Room Persistence — Предлагает уровень абстракции над SQLite, предлагая более простой и продвинутый способ управления.

В целом же мы получили дефолтную ORM, этот компонент можно разделить на три части: Entity, DAO (Data Access Object), Database.

Entity — объектное представление таблицы. С помощью аннотаций можно легко и без лишнего кода описать наши поля.

Для создания нашей Entity нам нужно создать класс POJO (Plain Old Java Object). Пометить класс аннотацией Entity.

Пример:

@Entity(tableName = «book»)
class Book{
   @PrimaryKey
   private int id;
   @ColumnInfo(name = «title»)
   private  String title;
   @ColumnInfo(name = «author_id»)
   private int authorId;
   …
   //Get and set for fields
}

@PrimaryKey — Для обозначения ключа. @ColumnInfo — для связи поля в таблице. Создавать методы get и set не обязательно, ног тогда нужно предоставить доступ к переменным с помощью модификатора public.

Установление связей объявляется также в теле аннотации Entity: Entity(foreignKeys = @ForeignKey(entity = Other.class, parentColumns = «id», childColumns = «author_id»))

DAO — Интерфейс который описывает методы доступа к БД.

Для реализации создаем интерфейс который помечаем аннотацией DAO и объявляем наши методы. Основные аннотации для методов это Insert Update @Deleta Query, в комментариях не нуждаются.

Пример:

@Dao
public interface OurDao {
   @Insert
   public void insertBook(Book book);
   @Update
   public void updateBook(Book book);
   @Delete
   public void deleteBook(Book book);
@Query(«SELECT * FROM book»)
   public Book[] loadAllBooks();
}

В обычном состоянии попытка получить доступ к БД с основного потока закончиться Exception. Если вы все же уверены в своих действиях, то можно воспользоваться методом allowMainThreadQueries(). Для асинхронного доступа рекомендовано использовать LiveData или RxJava.

Database — используется для создания Database Holder и является точкой доступа к соединению с БД.

Для создания нашего класса нужно наследоваться от RoomDatabase и использовать аннотацию Database, которой передаем параметры такие как используемые entity и версию базы. В теле описываем абстрактные методы доступа к нашим DAO.

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
   public abstract OurDao ourDao();
}

Для создания instance для нашей БД используем код:

AppDatabase db = Room.databaseBuilder(getApplicationContext(),  AppDatabase.class, «database-name»).build();

Для хранения db рекомендуют использовать singleton.

Что это нам дает?

Упрощение работы с базой данных, отпадает потребность в использовании сторонних ORM.
Кроме описанных выше плюшек NestedObject, параметры в запросах, коллекции аргументов, TypeConverter, database migration и т.д. Эти темы не входят в скоуп данного материала и будут рассмотрены позже.

К завершению материала хочу добавить еще несколько слов об архитектуре. С представлением Android Architecture Components была предложена архитектура решений, которая для большинства разработчиков уже и так привычна в той или иной форме. Суть заключается в том, что мы разбиваем архитектуру на 3 основных слоя: View (Activity/Fragment), который общается с ViewModel, а ViewModel работает непосредственно уже с Repository. Для наглядности преведу картинку с developer.android.com.

image

Выглядит абсолютно просто, а как на самом деле мы рассмотрим в следующих статьях.
Где сначала разберем более подробно каждый компонент и в конце реализуем приложение, как говорится с базой данных и… коннектом к сервису.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332562/


Метки:  

Фреймворк для UI-тестирования JDI: как и зачем использовать

Четверг, 06 Июля 2017 г. 17:36 + в цитатник
Давным-давно, в далекой-далекой галактике жили тестировщики. Они тестировали все, что только можно было, и на это уходило немало времени. Пришла эра автоматизированного тестирования, а вместе с ней — фреймворки. Многие говорили, что сделать работу тестировщиков эффективнее и проще уже невозможно. Но разработчики JDI так не думали.

Зачем создали JDI, когда и так есть несколько фреймворков для тестирования пользовательских интерфейсов? Чем он отличается от других и как его использовать?

Инженеры по автоматизированному тестированию ЕРАМ, разработчики JDI — Роман Иовлев и Алексей Гирин — ответили на вопросы о фреймворке, которые им задают чаще всего.



Что такое JDI?


JDI — это фреймворк для UI-тестирования. Название расшифровывается как Just do it: главная идея JDI — в том, чтобы с помощью него было легко тестировать и поддерживать тесты. Это опенсорсный фреймворк, его можно скачать с GitHub или с сайта JDI. JDI поддерживает Java и C#. Сейчас мы работаем над поддержкой Python.

Зачем создали JDI?


В ЕРАМ постоянно приходят новые проекты, и тестировщикам нужно готовое решение, которое позволяет быстро писать тесты, логирует все действия на понятном пользователю языке и создает наглядные отчеты. Имеющихся инструментов для тестирования UI нам было недостаточно для эффективной работы. В Selenium логирование низкоуровневое, и нет типизированных элементов. В HTML Elements от «Яндекса» они есть, но этот фреймворк заточен под верстку HTML-страниц. Кроме того, он давно не обновлялся. Мы решили объединить лучшее, что есть на рынке, в один фреймворк. JDI включает в себя наработки, которые пригодятся везде, где нужно тестировать UI. В том числе, если речь идет о мобильных устройствах и десктоп-приложениях.

Но ведь фреймворков много. Чем JDI отличается от других?


Нас часто спрашивают, что лучше: JDI или Selenide, JDI или Cucumber? Сравнивать их неправильно: они могут отлично взаимодействовать и помогать друг другу. Selenium или Selenide – это, скорее, драйверы для JDI, они отлично с ним сочетаются, а не конкурируют. Но они не работают с типизированными элементами — тем уровнем абстракции, который есть в JDI. Фреймворки вроде Cucumber, которые реализуют BDD, находятся, наоборот, выше JDI по этой шкале и реализуют дополнительный слой абстракции. Мы, кстати, советуем вместе с JDI использовать слои BDD и CI.

JDI – это такая прослойка, которая позволяет описывать Page Objects и работает с типизированными элементами, которые видны пользователю: кнопками, формами, таблицами, дропдаунами и так далее. Когда речь идет о типизированных элементах, имеется в виду представление об элементе. Например, что такое кнопка, и что она должна уметь, вне зависимости от конкретного UI. Кнопка может быть в вебе или в мобильном приложении, верстка может быть разной, это уже вопрос имплементации. Главное – есть идея о кнопке: ее нельзя спутать с таблицей или дропдауном.

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

При работе с JDI дополнительно нужно описывать только те действия, которые связаны с конкретным бизнесом, заказчиком. Например, «купить продукт». Типизированные элементы не знают, что такое «купить продукт», и это нужно описывать на UI-объектах.



Как можно описывать элементы? При помощи аннотации FindBy, что есть в Selenium, или с помощью JFindBy, что расширяет возможности: можно искать по тексту, по значению (value), по типу (type). Можно описывать элементы при помощи конструкторов или интерфейсов. Последний способ дает ряд преимуществ. Например, можно менять имплементацию кнопки, сделать вместо мобильной кнопку для веба, и запустить для веба тесты, которые писали для мобильных устройств. Тестировщику не придется менять Page Objects и тестовый сценарий, если не поменялась логика. Это еще одно отличие JDI от других фреймворков – он не привязан к определенной верстке. Это то, чего нам не хватало во фреймворке HTML Elements от «Яндекса». Там тоже используются типизированные элементы, но фреймворк ориентирован именно на верстку HTML-страниц.

Работа с простыми типизированными элементами – кнопками, текстом – позволяет сделать тесты более наглядными. А работа со сложными элементами – дропдаунами, таблицами, чек-листами – дает возможность сократить количество кода, который нужно написать тестировщику. Необходимая информация об элементе (локаторы, методы) расположена в одном месте, и такой код проще поддерживать.

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

Как тестировать с JDI?


Чтобы начать работу, JDI нужно скачать с GitHub или с сайта. Вы скачиваете архив, где фреймворк уже полностью настроен: не нужно думать, как запустить драйвер, настроить логирование и репортинг. Если вы сами хотите настроить проект, то можете добавить JDI как dependency к нему.

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

Сложно ли тестировать с JDI?


Чтобы начать писать тесты на JDI, достаточно посмотреть наши презентации или примеры, которые есть на GitHub. Можно прийти на курсы по автоматизации тестирования, которые ЕРАМ проводит в Петербурге. На них мы учим работать в том числе с JDI, фреймворк осваивают даже студенты.

Иногда тестировщики хотят добавить что-то в JDI, не подозревая, что внутри он устроен сложнее, чем снаружи. Разобраться во «внутренностях» фреймворка смогут разработчики уровня Senior.

Пользуются ли тестировщики JDI?


JDI использовали уже более чем в 50 проектах в ЕРАМ, и в нескольких десятках проектов вне компании.

Как разрабатывают JDI?


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

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

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

На Selenium Camp Роман подробно рассказал, как использовать JDI. Вот видео его выступления:







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

https://habrahabr.ru/post/332560/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1040 1039 [1038] 1037 1036 ..
.. 1 Календарь