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

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

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

 

 -Статистика

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





Расширение API от Vk для стикеров на Elixir

Пятница, 06 Января 2017 г. 07:37 + в цитатник
Введение Во Вк есть наборы стикеров, некоторые из которых даже бесплатные. Но во Вк нет ни какого публичного API для использования данного функционала на сторонних сайтах. Задачка состоит в том, чтобы используя функциональный язык Elixir написать расширение над местом хранения стикеров во Вк в виде API. По моему мнению имена методов, и параметры, которые они принимали были бы следующими. Общим пространством имён для коллекции API методов для работы со стикерами было бы ключевое слово stickers, а сами методы возможно выглядели бы так: stickers.get — со следующими параметрами: pack_ids, pack_id, fields; stickers.getById — со следующими параметрами: sticker_ids, sticker_id, fields. Так как нет возможности создавать или редактировать стикеры, которые есть во Вк, данное API будет иметь только read-only методы. Честно, сложно угадывать, и не хочется подражать разработчикам социальной сети, по этому ограничусь только придумыванием имён методов. И не буду реализовывать API в стиле Вк, хоть это бы и добавило общей идентичности расширению. Вот такие методы буду реализовывать для работы со стикерами: Методы для наборов: GET /packs GET /packs/{id} GET /packs/{id}/stickers Методы для стикеров: GET /stickers GET /stickers/{id} GET /stickers/{id}/pack Реализация Как написано выше, языком для написания программирования выбран Elixir. Базой данных в проекте будет выступать PostgreSQL и для взаимодействия с ней будут использованы Postgrex и Ecto. В качестве web-сервера будет использован Cowboy. За сериализацию данных в json-формат будет отвечать Poison. Вся поставленная задача довольно не объёмная и не сложная, по этому Phoenix использоваться не будет. Для создания нового приложения используется команда mix new api_vk_stickers, она создаст базовую структуру, на основе которой будет строится расширение для API Вк. Первым делам следует отредактировать файл mix.exs, который содержит базовую информацию о приложении и список используемых внешних зависимостей: # mix.exs defmodule ApiVkStickers.Mixfile do use Mix.Project # ... defp deps do [{:postgrex, "~> 0.13"}, {:ecto, "~> 2.1.1"}, {:cowboy, "~> 1.0.4"}, {:plug, "~> 1.1.0"}, {:poison, "~> 3.0"}] end end После редактирования списка зависимостей необходимо их все установить, для этого предназначена команда mix deps.get. Теперь приступим к написанию логики самого расширения. Структура проекта будет следующая: models/ pack.ex sticker.ex decorators/ pack_decorator.ex sticker_decorator.ex encoders/ packs_encoder.ex stickers_encoder.ex finders/ packs_finder.ex stickers_finder.ex parsers/ ids_param_parser.ex controllers/ packs_controller.ex stickers_controller.ex router.ex models Модели создаются с использованием модуля Ecto.Schema. В модели Pack вместе с полем title будет ещё несколько дополнительных не обязательных полей. Структура модели задаётся с помощью выражения schema/2, как аргумент она принимает имя источника, то есть название таблицы. Поля задаются в теле schema/2 с помощью выражения filed/3. filed/3 принимает название поля, тип поля (по умолчанию :string) и дополнительные не обязательные функции (по умолчанию []). Для определения связи один-ко-многим используется выражение has_many/3. # pack.ex defmodule ApiVkStickers.Pack do use Ecto.Schema schema "packs" do field :title field :author field :slug has_many :stickers, ApiVkStickers.Sticker end end Для противоположной связи один-к-одному предназначено выражение belongs_to/3. Код Sticker# sticker.ex defmodule ApiVkStickers.Sticker do use Ecto.Schema schema "stickers" do field :src, :map, virtual: true belongs_to :pack, ApiVkStickers.Pack end end decorators В Эликсире по понятным причинам объектов нет, но всё же логика расширения моделей будет размещена в модулях с суффиксом _decorator. API на равне с атрибутами полученными из базы данных также будут возвращать несколько дополнительных атрибутов. Для наборов это будет коллекция обложек в двух размерах и url места, где можно добавить себе данный набор во Вк. # pack_decorator.ex defmodule ApiVkStickers.PackDecorator do @storage_url "https://vk.com/images/store/stickers" @shop_url "https://vk.com/stickers" def source_urls(pack) do id = pack.id %{small: "#{@storage_url}/#{id}/preview1_296.jpg", large: "#{@storage_url}/#{id}/preview1_592.jpg"} end def showcase_url(pack) do "#{@shop_url}/#{pack.slug}" end end Для стикеров дополнительным атрибутами будет коллекция адресов картинок в четырёх вариациях. Код StickerDecorator# sticker_decorator.ex defmodule ApiVkStickers.StickerDecorator do @storage_url "https://vk.com/images/stickers" def source_urls(sticker) do id = sticker.id %{thumb: "#{@storage_url}/#{id}/64.png", small: "#{@storage_url}/#{id}/128.png", medium: "#{@storage_url}/#{id}/256.png", large: "#{@storage_url}/#{id}/512.png"} end end encoders Сериализаторы будут ответственны за преобразование атрибутов в json-формат. Первым делом из модели будет создан ассоциативный массив с базовыми атрибутами, а затем в него будут добавлены экстра атрибуты полученные из декораторов. Последним шагом будет преобразование массива в JSON с помощью модуля Poison.Encoder.Map. Модуль PacksEncoder будет иметь один публичный метод call/1. # packs_encoder.ex defmodule ApiVkStickers.PacksEncoder do alias ApiVkStickers.PackDecorator defimpl Poison.Encoder, for: ApiVkStickers.Pack do def encode(pack, options) do Map.take(pack, [:id, :title, :author]) |> Map.put(:source_urls, PackDecorator.source_urls(pack)) |> Map.put(:showcase_url, PackDecorator.showcase_url(pack)) |> Poison.Encoder.Map.encode(options) end end def call(stickers) do Poison.encode!(stickers) end end Сериализатор для стикеров будет идентичен. Код StickersEncoder# stickers_encoder.ex defmodule ApiVkStickers.StickersEncoder do alias ApiVkStickers.StickerDecorator defimpl Poison.Encoder, for: ApiVkStickers.Sticker do def encode(sticker, options) do Map.take(sticker, [:id, :pack_id]) |> Map.put(:source_urls, StickerDecorator.source_urls(sticker)) |> Poison.Encoder.Map.encode(options) end end def call(stickers) do Poison.encode!(stickers) end end finders Для того чтобы не хранить логику запросов к базе данных в контроллерах, будут использованы файндеры (простите, искатели). Их будет также два, по количеству моделей. Файндер по наборам будет иметь три базовые функции: all/1 — получение коллекции наборов, one/1 — получение одного набора и by_ids/1 — получение коллекции наборов согласно переданным id. # packs_finder.ex defmodule ApiVkStickers.PacksFinder do import Ecto.Query alias ApiVkStickers.{Repo, Pack} def all(query \\ Pack) do Repo.all(from p in query, order_by: p.id) end def one(id) do Repo.get(Pack, id) end def by_ids(ids) do all(from p in Pack, where: p.id in ^ids) end end Похожими функциями будет обладать файндер по стикерам, за исключением третьей функции by_pack_id/1, которая возвращает коллекцию стикеров не по их id, а по их pack_id. Код StickersFinder# stickers_finder.ex defmodule ApiVkStickers.StickersFinder do import Ecto.Query alias ApiVkStickers.{Repo, Sticker} def all(query \\ Sticker) do Repo.all(from s in query, order_by: s.id) end def one(id) do Repo.get(Sticker, id) end def by_pack_ids(pack_ids) do all(from s in Sticker, where: s.pack_id in ^pack_ids) end end parsers Данный сервис необходим из-за того, что не была познана практика передачи параметров в url GET-запроса таким образом, чтобы Plug автоматически представлял мне массив. И вообще как-то создавал для переданного набора id какую-то переменную, без указания принимаемых параметров в выражении get/3 модуля Plug.Router. # ids_param_parser.ex defmodule ApiVkStickers.IdsParamParser do def call(query_string, param_name \\ "ids") do ids = Plug.Conn.Query.decode(query_string)[param_name] if ids do String.split(ids, ",") end end end controllers Контроллеры будут на основе модуля Plug.Router, DSL которого многим напомнит фреймворк Sinatra. Но прежде чем приступить к самим контроллерам, необходимо собрать модуль который будет отвечать за маршруты. Код router.exdefmodule ApiVkStickers.Router do use Plug.Router plug Plug.Logger plug :match plug :dispatch forward "/packs", to: ApiVkStickers.PacksController forward "/stickers", to: ApiVkStickers.StickersController match _ do conn |> put_resp_content_type("application/json") |> send_resp(404, ~s{"error":"not found"})) end end Контроллеры по сути дела тоже будут такими же маршрутными модулями, но в душе есть вера, в то, что размещение этих модулей в папку controllers было правильным решением. # packs_controller defmodule ApiVkStickers.PacksController do # ... get "/" do ids = IdsParamParser.call(conn.query_string) packs = if ids do PacksFinder.by_ids(ids) else PacksFinder.all end |> PacksEncoder.call send_json_resp(conn, packs) end get "/:id" do pack = PacksFinder.one(id) |> PacksEncoder.call send_json_resp(conn, pack) end get "/:id/stickers" do stickers = StickersFinder.by_pack_ids([id]) |> StickersEncoder.call send_json_resp(conn, stickers) end # ... end Код StickersController# stickers_controller defmodule ApiVkStickers.StickersController do # ... get "/" do pack_ids = IdsParamParser.call(conn.query_string, "pack_ids") stickers = if pack_ids do StickersFinder.by_pack_ids(pack_ids) else StickersFinder.all end |> StickersEncoder.call send_json_resp(conn, stickers) end get "/:id" do sticker = StickersFinder.one(id) |> StickersEncoder.call send_json_resp(conn, sticker) end get "/:id/pack" do sticker = StickersFinder.one(id) pack = PacksFinder.one(sticker.pack_id) |> PacksEncoder.call send_json_resp(conn, pack) end # ... end Результат $ curl -X GET --header 'Accept: application/json' 'http://localhost:4000/packs'[{"title":"Спотти", "source_urls":{"small":"https://vk.com/images/store/stickers/1/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/1/preview1_592.jpg"}, "showcase_url":"https://vk.com/stickers/spotty", "id":1,"author":"Андрей Яковенко"}, {"title":"Персик", "source_urls":{"small":"https://vk.com/images/store/stickers/2/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/2/preview1_592.jpg"}, "showcase_url":"https://vk.com/stickers/persik", "id":2,"author":"Елена Савченко"}, {"title":"Смайлы", "source_urls":{"small":"https://vk.com/images/store/stickers/3/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/3/preview1_592.jpg"}, "showcase_url":"https://vk.com/stickers/smilies", "id":3,"author":"Елена Савченко"}, {"title":"Фруктовощи", "source_urls":{"small":"https://vk.com/images/store/stickers/4/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/4/preview1_592.jpg"}, "showcase_url":"https://vk.com/stickers/fruitables", "id":4,"author":"Андрей Яковенко"}] $ curl -X GET --header 'Accept: application/json' >[{"title":"Персик", "source_urls":{"small":"https://vk.com/images/store/stickers/2/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/2/preview1_592.jpg"},"showcase_url":"https://vk.com/stickers/persik", "id":2,"author":"Елена Савченко"}, {"title":"Смайлы", "source_urls":{"small":"https://vk.com/images/store/stickers/3/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/3/preview1_592.jpg"},"showcase_url":"https://vk.com/stickers/smilies", "id":3,"author":"Елена Савченко"}] $ curl -X GET --header 'Accept: application/json' 'http://localhost:4000/packs/1'{"title":"Спотти", "source_urls":{"small":"https://vk.com/images/store/stickers/1/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/1/preview1_592.jpg"}, "showcase_url":"https://vk.com/stickers/spotty", "id":1,"author":"Андрей Яковенко"} $ curl -X GET --header 'Accept: application/json' 'http://localhost:4000/packs/1/stickers'[{"source_urls":{"thumb":"https://vk.com/images/stickers/1/64.png", "small":"https://vk.com/images/stickers/1/128.png", "medium":"https://vk.com/images/stickers/1/256.png", "large":"https://vk.com/images/stickers/1/512.png"}, "pack_id":1,"id":1},...,{"source_urls":{"thumb":"https://vk.com/images/stickers/48/64.png", "small":"https://vk.com/images/stickers/48/128.png", "medium":"https://vk.com/images/stickers/48/256.png", "large":"https://vk.com/images/stickers/48/512.png"}, "pack_id":1,"id":48}] $ curl -X GET --header 'Accept: application/json' 'http://localhost:4000/stickers'[{"source_urls":{"thumb":"https://vk.com/images/stickers/1/64.png", "small":"https://vk.com/images/stickers/1/128.png", "medium":"https://vk.com/images/stickers/1/256.png", "large":"https://vk.com/images/stickers/1/512.png"}, "pack_id":1,"id":1}, {"source_urls":{"thumb":"https://vk.com/images/stickers/2/64.png", "small":"https://vk.com/images/stickers/2/128.png", "medium":"https://vk.com/images/stickers/2/256.png", "large":"https://vk.com/images/stickers/2/512.png"}, "pack_id":1,"id":2}, {"source_urls":{"thumb":"https://vk.com/images/stickers/3/64.png", "small":"https://vk.com/images/stickers/3/128.png", "medium":"https://vk.com/images/stickers/3/256.png", "large":"https://vk.com/images/stickers/3/512.png"}, "pack_id":1,"id":3},...,{"source_urls":{"thumb":"https://vk.com/images/stickers/167/64.png", "small":"https://vk.com/images/stickers/167/128.png", "medium":"https://vk.com/images/stickers/167/256.png", "large":"https://vk.com/images/stickers/167/512.png"}, "pack_id":4,"id":167}, {"source_urls":{"thumb":"https://vk.com/images/stickers/168/64.png", "small":"https://vk.com/images/stickers/168/128.png", "medium":"https://vk.com/images/stickers/168/256.png", "large":"https://vk.com/images/stickers/168/512.png"}, "pack_id":4,"id":168}] $ curl -X GET --header 'Accept: application/json' >[{"source_urls":{"thumb":"https://vk.com/images/stickers/49/64.png", "small":"https://vk.com/images/stickers/49/128.png", "medium":"https://vk.com/images/stickers/49/256.png", "large":"https://vk.com/images/stickers/49/512.png"},"pack_id":2,"id":49}, ..., {"source_urls":{"thumb":"https://vk.com/images/stickers/128/64.png", "small":"https://vk.com/images/stickers/128/128.png", "medium":"https://vk.com/images/stickers/128/256.png", "large":"https://vk.com/images/stickers/128/512.png"},"pack_id":3,"id":128}] $ curl -X GET --header 'Accept: application/json' 'http://localhost:4000/stickers/1'{"source_urls":{"thumb":"https://vk.com/images/stickers/1/64.png", "small":"https://vk.com/images/stickers/1/128.png", "medium":"https://vk.com/images/stickers/1/256.png", "large":"https://vk.com/images/stickers/1/512.png"}, "pack_id":1,"id":1} $ curl -X GET --header 'Accept: application/json' 'http://localhost:4000/stickers/1/pack'{"title":"Спотти", "source_urls":{"small":"https://vk.com/images/store/stickers/1/preview1_296.jpg", "large":"https://vk.com/images/store/stickers/1/preview1_592.jpg"}, "showcase_url":"https://vk.com/stickers/spotty", "id":1,"author":"Андрей Яковенко"} Послесловие Из проекта можно убрать PostgreSQL. В таком случае все данные о наборах стикеров будут храниться в коде включая данные об интервале принадлежащих им стикеров. Проект не сильно упростится, но в скорость базы данных вы уже не уткнётесь точно. Если вам интересен функциональный язык программирования Elixir или вы просто сочувствующий то советую вам присоединиться к Telegram-каналу https://telegram.me/proelixir про Elixir. У отечественного Elixir сообщества начинает появляться единая площадка в лице проекта Wunsh.ru. Сейчас ребята во всю пишут новую версию сайта. Но уже у них есть подписка на рассылку. В ней нет ничего нелегального, раз в недельку будет приходить письмо с подборкой статей про Elixir на русском языке. Если вам интересна тема создания своих приложений на Elixir, могу посоветовать статью: Создание Elixir-приложения на примере. От инициализации до публикации https://habrahabr.ru/post/317444/.

Метки:  

Как я продолжил дело Дота-лиги

Среда, 07 Декабря 2016 г. 01:38 + в цитатник
Предыдущие части (не за моим авторством): раз и два. Возвышение Хоруса Тимс был автором бота, а я был тем самым «прошаренным админом», который допиливал его код. Можно долго спорить, кому что принадлежало, кто прав и кто виноват, но факт остается фактом — одна лига раскололась на две. Владелец бренда say-plz и спонсор поставил меня админом sP Dota League, а Тимс в тот же момент развернул RIHL (Russian In-House League. Между лигами была война за игроков используя любые средства, кроме разве что ядерного оружия. Как произошел развал с моей точки зренияВладельцем домена и хостинга say-plz был менеджер команды и спонсор под ником Матрикс. Он не знал, что происходит на лиге и не особо вникался в подробности. И после того, как Тимсу были предъявлены обвинения в неадекватном поведении и продаже модераторского доступа за деньги, у него был диалог со спонсором, в котором Тимс заявил примерно следующее: «это моя лига, что хочу, то и делаю». После чего Матрикс спрашивает меня — смогу ли я потянуть всё без участия Тимса? Я отвечаю ему — да. Ну а потом Матрикс снял права доступа с Тимса, сделав меня новым СЕО. После того, как админом стал я, были внесены некоторые изменения в политику лиги. 1. Никаких необоснованных банов по личной неприязни. 2. Равные наказания и для известных игроков, и для новичков. Бан на 14 дней за намеренный выход из игры. 3. Моментальный демоут (из модеров в юзеры) тех, кто злоупотребляет своими правами — разбанивал друзей, или например пытался продать воучи (доступ к лиге) за деньги. Продолжение жизни в Garena В то время у нас было два дивизиона — SP1 и SP2. На первом играли самые продвинутые и скилловые игроки. С этим была проблема, потому что игроков SP1 было мало, многие не хотели ждать, пока соберется игра на первом дивизионе и шли играть на SP2. Сначала проблема была решена таким способом — прежде чем пойти на сп2, надо сыграть на сп1 хотя бы один раз за день. А с переездом в IRC комнаты были объединены, об это будет чуть позже. Бот, в отличие от обычных игр в первой доте, учитывал всю твою статистику. И это были не только победы-поражения-очки, но и такая вещь как «стрик», т.е. победы подряд. И если 2-3 или даже 5 побед подряд в доте — нормальная ситуация, то 10, 20 — это уже что-то из разряда вон выходящее. На нашей лиге был такой легендарный игрок Vigoss, который побил абсолютно все рекорды, у него было 60 (!!!) побед подряд. А самое интересное, что при победе над игроком со стриком, победителям давали бонусные очки. Все с нетерпением ждали момента, когда же Вигосс потеряет корону, и это всё-таки случилось. Я даже нашел лог бота этой легендарной игры длительностью всего 23 минуты: Game 4629. Scourges won-63/+63.Mode: chall 3x3 ggc,Length 23min Draw/Sent/Scou results: 0/0/4PLZ4629. Sentinels: vigoss sahka Sp- > Scourges: Traffic-Roger Traffic|Dark Traffic|Tunes. Scourges got 382 BONUS points for breaking streak of vigoss; streak of sahka; Стрик был настолько большим (+55/60 у вигосса и сашки), что даже не показывалось его название. В боте тимса названия были определены только до 50, всё что выше +10 называлось просто Holy Shit. Никто даже представить не мог, что у кого-то будет стрик 50+. Разработка бота под IRC Garena была не просто глючной, а невероятно глючной. Например, там можно было запускать одного и того же бота в двух комнатах, он отвечал на сообщения и работал вполне нормально. Однажды лига подверглась нападению бешеного хакера из Казахстана, который каким-то образом мог «ресетить» всю комнату, у всех вылетали игры и случались дисконнекты. Это сейчас если тебя выкинуло, ты можешь просто зайти заново и начать играть, но не в первой доте. Дисконнект — это всё, конец. Обычно игра или продолжала идти 4х5, или же загружался предварительно сделанный сейв. Использовать не совсем надежный StealthBot (знали бы вы, как Тимс прикрутил его к Garena!) и Visual Basic Script не было никакого желания, поэтому было решено переводить лигу на IRC, и писать бота под него. Именно так работала лига IHCS, которая была эталоном на тот момент. Я начал заниматься любимым делом всех программистов, которые однажды пытались разбираться в чужом коде — ПЕРЕПИСАТЬ ВСЁ С НУЛЯ, уж сам-то сделаешь идеально! Итак, мне нужно было сделать бота для IRC, каким-то образом прикрутить к нему MySQL и заставить работать на сервере Quakenet в IRC. Это был путь, полный боли и страданий. Наверное, именно так и становятся программистами, самостоятельно решая какую-то новую проблему, когда даже гугл не в силах дать тебе ответ. Для IRC платформы я взял Eggdrop, по дефолту в нем не было почти ничего, но мне нужна была лишь поддержка скриптов, которые писались на языке TCL. Язык был хоть и новый для меня, но достаточно простой, без излишеств. Он был приятнее, чем VBS, и разработка в целом шла нормально. Вот только Eggdrop отказывался компилироваться на VPS. Превозмогая, пришлось как-то править исходники, чтобы заставить его работать. Это была победа. Мой первый IRC бот завелся и написал на канале первые фразы. Переезд в IRC на сервер Quakenet Сначала был сделан бот для тестгеймов. Это для тех, кто еще не имел доступа на лигу, но очень хотел туда попасть. Игроки заходили на канал, ждали модератора, который начинает игру, а потом принимает решение, кому дать инвайт. Обычно этот канал заспамливался фразами «ГО ТГ!» и игрокам было нечем заняться. В дальнейшем именно этот канал стал широко известной в узких кругах лигой «сп3», на которой можно было играть и получать очки (напомню, что именно из-за статистики побед-поражений игроки предпочитали лиги, в первой доте не было никакой встроенной статистики вообще). В конце месяца среди лучших игроков проводился суперфинал, в котором можно было сразу попасть на основную лигу. Сп3 была достаточно ламповой, и на ней играли даже некоторые игроки с основных дивизионов, когда не хотелось особо напрягаться. Затем и основной бот был переведен на платформу IRC. Вместо двух отдельных дивизионов с разными чатами, было решено сделать один общий чат, но с градацией игроков. Игроки SP1 подсвечивались синим цветом, SP2 цвета не имели. Кроме этого, я значительно обновил систему ролей. Вместо иерархии вида Игрок -> Хост -> Модератор -> Воучер -> Админ, я сделал 3 ветки — игроки, модераторы и воучеры. Каждый мог иметь абсолютно разный доступ, и это было очень удобно. Воучеры перестали быть «крутыми модераторами», и в их обязанности не входило рассмотрение жалоб, они занимались только инвайтами новых игроков. По приколу добавил команду ".днодоты", которая выводила игрока с наименьшим количеством очков на лиге. По некоторой версии, именно после введения этой команды фраза «ты дно» стала популярна, но мало кто знал, откуда это пошло. Так же была улучшена система расчета очков. В боте Тимса считалось отношение очков твоей команды и команды противника, чем меньше у вашей, тем больше давало в случае победы. Я изменил это и сделал, что учитывается не твоя команда, а только твои очки. Благодаря этому, стало проще вылезать из низкого рейтинга, и сложнее занимать высокие места. В дальнейшем я добавил еще одну штуку — зависимость опыта от репутации. О цензурах и репутацииНа лиге была такая штука — censure. С помощью бота и команды .censure <ник> <причина> его мог выдать любой игрок кому угодно, даже просто так. Если ты его выдаешь, и у тебя и у цели снимаются очки репутации. Если ты начнешь выдавать их всем подряд — рискуешь сам потерять её. Репутация изначально не влияла ни на что, ее было около 50 единиц, и цензур снимал 3. Если она заканчивалась, ты получал бан на 3 дня, и репутация снова становилась равна 50. Следующий бан был уже на 6 дней, и так далее по +3 за каждый. Затем я ввел некоторые коэффициенты, если у тебя было мало репутации — количество получаемых очков за победу уменьшались вплоть до 40%. Игроки стали гораздо тщательнее следить за своим поведением. Хотя, и приколы с этим были тоже. Была одна легендарная личность под ником MarcoDeLacrosso, он писал смесью каПСЛОКа иОБЫЧНОГОтекста и ИНОГДАБЕЗпробелов. Называл всех школьниками, еще до того как это вообще стало считаться оскорблением. При этом Марко вел себя достаточно адекватно, но после игры КАЖДЫЙ считал своим долгом дать ему цензур. Когда он улетал в бан из-за отсутствия репутации, то ждал несколько недель, чтобы снова начать играть. За это время по нему уже многие успели соскучиться, спрашивали, когда же его разбанят. По сравнению с ботом в Garena, который то и дело отваливался, и лига просто вставала, Eggdrop был надежен как автомат Калашникова. Бот был на канале 24 часа в сутки, 7 дней в неделю. Никто и никогда не мог его положить. За небольшим исключением. Один особо резвый игрок получил бан и начал угрожать нас положить. И если айпи бота был скрыт, то сайт лиги был в открытом доступе. Хостинг мне любезно предоставил друг, потому что много ресурсов нам было не надо. В общем, после 10-гигабитного ДДОСа, я остался без хостинга. Как и мой друг, которого просто послал хостер. Я нашел какой-то недорогой VPS на американском сайте, самое смешное, что через месяц они не стали требовать оплаты, всё работало как раньше. Так продолжалось целый год, пока они в один момент не отрубили сервер. Я предполагал, что рано или поздно это должно случиться, и просто восстановил бэкапы на другом сервере. Веб-проекты Т.к. на лиге по сути все команды выводились через бота в текстовом виде, иногда это было неудобно. Например, надо посмотреть все игры конкретного игрока, и с кем он играл. Через бота это бы занимало вечность — вывести список игр, затем вывести каждую и так далее. Благодаря тому, что данные хранились в MySQL, было достаточно легко отобразить всё это на сайте. Первую версию на Perl делал один из администраторов под ником Tycooon. Но после того, как я переписал бота, требовалось переписать и сайт. Tycooon взял модный на тот момент Ruby on Rails, но сайт так и не доделал. Я понял, что надо браться самому. Начинать учить Rails как первый web-фреймворк (без опыта с PHP) было гораздо сложнее, чем написать IRC бота. Я ещё зачем-то заботился о юзерах с выключенным javascript, мой код выглядел максимально ужасно. Мне было совершенно непонятно, как работают ассоциации, когда писать includes :people, а когда includes :person. Но всё это я успешно решил, и сайт был запущен на радость игрокам. На сайте была сделана очень удобная подача жалоб, игрок мог скрыть свой ник от модераторов или других игроков, чтобы избежать предвзятого отношения. Можно было быстро посмотреть, кто из модераторов работает, а кто ничего не делает. Каждая закрытая жалоба засчитывалась, и модераторы буквально выхватывали их друг у друга, чтобы получить +1 в статистику. Закат лиги Под моим руководством лига просуществовала примерно 4-5 лет. Вплоть до выхода доты 2, а в ней, как известно, статистика была уже в клиенте. Меня самого к тому времени уже практически перестали интересовать игры, я занимался этим проектом потому что мне было интересно. Большинство игроков перешли на вторую доту, и лига стала просто не нужна. Это были очень веселые и интересные времена, и я совершенно не жалею, что потратил на неё время. Не знаю, как бы повернулась моя судьба, если бы дота прошла мимо меня. В том числе благодаря ей сейчас я Ruby on Rails разработчик в одной из московских компаний, и мне очень нравится то, чем я занимаюсь. На этом и закончу рассказ, надеюсь, читать было интересно :)
Эффекты в OpenGL

Метки:  

Кабель-менеджмент и PUE: как они связаны?

Воскресенье, 11 Сентября 2016 г. 00:13 + в цитатник
В прошлой статье наша компания рассказывала о тех принципах работы с кабелями, которых мы придерживаемся уже много лет. В этот раз предлагаем поговорить о том, как эффективный кабель-менеджмент может повлиять на PUE дата-центра. Влияние это — только положительное. Если все делать правильно, то PUE будет только снижаться. Мы сами уже давно убедились в том, что продуманная инфраструктура с рациональным размещением кабелей может эффективно сказаться на PUE дата-центра. Это может казаться странным, но кабели, охлаждение северов и, соответственно, коэффициент PUE довольно сильно связаны. Как? Об этом давайте и поговорим. Так вот, неэффективный кабель-менеджмент приводит к тому, что изменяется направление воздушных потоков внутри дата-центра и между отдельными его элементами. Изменения эти приводят на ухудшение эффективности охлаждения дата-центра. При этом работает система охлаждения в прежнем режиме. Но мощности системы охлаждения уже не хватает на создание прежних условий микроклимата. Оборудование греется, растут затраты на энергию. Соответственно, растет коэффициент PUE, а оператор дата-центра понапрасну теряет время и деньги на работу систем охлаждения. Иногда хаотичное размещение кабелей может привести к появлению особо нагретых зон, что чревато выходом из строя оборудования. Чтобы решить эту проблему, операторы дата-центров предпочитают обычно увеличивать скорость потоков воздуха в дата-центре и понижать рабочую температуру систем охлаждения. Все это приводит к излишним затратам и бьет по бюджету компании. А все потому, что при прокладке кабелей мало кто задумывается над тем, как будет проходить холодный воздух через кабели, которые встречаются ему по пути. А задумываться нужно, поскольку в таком случае дата-центру может грозить не только увеличение PUE, но и выход из строя оборудования, если охлаждение будет недостаточным. В дата--центре следует обратить внимание на следующие способы прокладки кабелей: прокладка кабелей под фальшполом, пропуск кабелей в решетку, прокладка кабеля в стройке и над стойкой. Возможно, список неполный. Так что если у вас есть свои варианты, указывайте их в комментариях. Кабель-менеджмент и фальшпол Размещение кабелей под фальшполом Кабели можно и нужно размещать под фальшполом. Главная проблема — это то, что кабели могут закрывать путь потоку холодного воздуха. А это, в свою очередь, может повлиять на уровень статистического давления под фальшполом. Возникает ситуация, когда эффективность охлаждения, ранее бывшего вполне приемлемым, падает. Что можно сделать? Старайтесь размещать кабельные лотки как можно выше, чтобы воздух мог проходить под ними; Для того, чтобы избежать влияния проводов на токи прохладного воздуха, стоит размещать кабельные лотки в горячих коридорах. Только в этом случае провода не повлияют на эффективность работы системы охлаждения; Если кабель не используется, удаляйте его, не оставляйте лишние элементы. Прокладывание кабелей через решетку фальшпола В этой ситуации система охлаждения работает напрасно, поскольку холодный воздух блокируется, провода препятствуют охлаждению специального оборудования. Чем больше кабелей вставлено в фальшпол, тем выше коэффициент PUE. Тем не менее, многие операторы дата-центров предпочитают прокладывать провода через фальшпол. В этом случае прохладного воздуха здесь почти нет, и приходится повышать активность работы вентиляторов и системы охлаждения в целом. Что можно сделать? Кабельные отверстия под стойки, которые не закрываются, стоит закрывать; Также специалисты рекомендуют убрать все лишние отверстия под силовым оборудованием; Стоит заменить плитами без перфорации все перфорированные плиты фальшпола. Кабель менеджмент и серверные стойки Практически все операторы дата-центров стремятся увеличить плотность размещаемых внутри стойки серверов. Чем плотнее размещение оборудования внутри монтажных стоек, тем больше в стойке силовых и сетевых кабелей. Соответственно, тем больше вероятность перегрева оборудования. Все логично. При хаотичном размещении кабелей внутри серверной стойки воздух может блокироваться и не проходить через стойку. Это приведет к накоплению горячего воздуха в ее задней части. Здесь зависимость простая — чем больше кабелей, тем больше и проблем с системой охлаждения. Повышается нагрузка на систему охлаждения, фрикулинг можно использовать меньшее количество времени. Что можно сделать? Использовать глубокие и широкие серверные стойки с дополнительными инструментами для кабель-менеджмента; Чем глубже шкаф, тем больший объем воздуха проходит в вертикальной плоскости, без особых проблем в виде препятствий; Также рекомендуем использовать панели-заглушки. Это актуально при повышении количества кабелей, которые усиливают давление внутри корпуса; Никогда не нужно блокировать канал вытяжки воздуха от серверов. Кабель-менеджмент над стойкой Увеличить эффективность распределения воздуха помогает простая операция перемещения кабельных лотков ближе к потолку из-под фальшпола. В итоге будет повышена эффективность распределения воздуха на предприятии. Что можно сделать? Не нужно ставить кабельные лотки высоко над стойками; Если не ни горячего, ни холодного коридоров, стоит опробовать специальные изоляционных оболочек для кабельных лотков. В качестве вывода: как видим, кабель-менеджменту уделяется все больше внимания. Это правильно, поскольку эта сфера ничуть не менее важна, чем плотность оборудования, микроклимат в ДЦ и прочее. Если неправильно размещать кабели, это может негативно повлиять не только на эффективность работы охлаждающего оборудования, энергии станет потребляться больше, PUE будет расти.

Метки:  

Хобби-проекты: lets-meet.ru — куда пойдем в пятницу

Воскресенье, 28 Августа 2016 г. 02:21 + в цитатник
Автор: Артем Трубачев Идея создания этого приложения родилась, когда мы с коллегами в очередной раз собирались пойти в бар, но никак не могли договориться о дате. Все мы люди взрослые, и свободного времени у нас, конечно, мало. lets-meet.ru создан как раз чтобы определить, когда всем будет удобнее собраться. В двух словах, это работает так: вы создаете встречу и указываете варианты даты, время и места. Также можно добавить дополнительные вопросы. После создания встречи отправляете ссылку на опрос возможным участникам, они отвечают, а вы сразу можете посмотреть страницу результатов, где наглядно показано, когда и в каком формате всем удобнее встретиться. Технические детали: • Обычное Rails-приложение. • JQuery и Underscore. • База данных MongoDB. При создании этого приложения не ставилась цель изучить или попробовать что-то новое, скорее, наоборот: взять, что умеешь, и сделать все максимально удобно и быстро. Есть много идей по улучшению и добавлению функционала, но уже сейчас можно пользоваться, и вообще MVP.

Метки:  

Сколько нужно нейронов, чтобы узнать, разведён ли мост Александра Невского?

Воскресенье, 07 Августа 2016 г. 12:26 + в цитатник
Введение. На той неделе darkk описал свой подход к проблеме распознавания состояния моста(сведён/разведён). Алгоритм, описанный в статье использовал методы компьютерного зрения для извлечения признаков из картинок и скармливал их логистической регрессии для получения оценки вероятности того, что мост сведён. В комментариях я попросил выложить картинки, чтобы можно было и самому поиграться. darkk на просьбу откликнулся, за что ему большое спасибо. В последние несколько лет сильную популярность обрели нейронные сети, как алгоритм, который умудряется в автоматическом режиме извлекать признаки из данных и обрабатывать их, причём делается это настолько просто с точки зрения того, кто пишет код и достигается такая высокая точность, что во многих задачах (~5% от всех задач в машинном обучении) они рвут конкурентов на британский флаг с таким отрывом, что другие алгоритмы уже даже и не рассматриваются. Одно из этих успешных для нейронных сетей направлений — работа с изображениями. После убедительной победы свёрточных нейронных сетей на соревновании ImageNet в 2012 году публика в академических и не очень кругах возбудилась настолько, что научные результаты, а также програмные продукты в этом направлении появляются чуть ли не каждый день. И, как результат, использовать нейронные сети во многих случаях стало очень просто и они превратились из "модно и молодёжно" в обыкновенный инструмент, которым пользуются специалисты по машинному обучению, да и просто все желающие. Постановка задачи. darkk выложил изображения моста Александра Невского в Санкт-Петербурге. 30k+ в поднятом положении, 30k+ в опущенном, 9k+ в промежуточном положении. Задача, которую мы пытаемся решить: по изображениям со статической камеры, которая направлена на мост Александра Невского в различное время дня, ночи и времени года определить вероятность того, что мост принадлежит к классам (поднят/опущен/процессе). Я буду работать с классами поднят/опущен из тех соображений, что именно это важно с практической точки зрения. Нейронные сети могут решать достаточно сложные задачи с изображениями, шумными данными, в условиях, когда данных для тренировки очень немного и прочей экзотикой(Например вот эта задача про отвлекающихся водителей или вот эта про сегментацию нервов. Но! Задача классификации на сбалансированных даннных, когда этих данных хватает и объект классификации практически не меняется — для нейронных сетей, да и вообще для задач машинного обученя — это где-то между просто и очень просто, что darkk и продемонстрировал, используя достаточно простой и интерпретируемый подход комбинации компьютерного зрения и машинного обучения. Задача, которую я постараюсь решить, — это оценить, что нейронные сети могут предложить по данному вопросу. Подготовка данных. Не смотря на то, что нейронные сети достатоно устойчивы к шуму, тем не менее слегка почистить данные — это никогда не помешает. В данном случае — это обрезать картинку так, чтобы там было по максимуму моста и по минимуму всего остального. Было во так: А стало вот так: Также надо разделить данные на три части: train validation test train — 19 мая — 17 июля validation — 18, 19, 20 июля test — 21, 22, 23 июля Собственно, на этом подготовка изображений закончилась. Пытаться вычленять линии, углы, какие-то другие признаки не надо. код Тренировка модели. Определяем простую свёрточную сеть в которой свёрточные слои извлекают признаки, а последний слой по ним пытается ответить на наш вопрос. (Я буду использовать пакет Keras с Theano в качестве backend просто потому что это дёшево и сердито.) У нас достаточно простая задача, простая структура сети с малым числом свободных параметров, поэтому сеть замечательно сходится. Все картинки можно засунуть в память, но, не хочется, так что тренировать будем считывая картинки с диска порциями. Тренировочный процес выглядит как-то вот так: Using Theano backend. Using gpu device 0: GeForce GTX 980 Ti (CNMeM is disabled, cuDNN 5103) Found 59834 images belonging to 2 classes. Found 6339 images belonging to 2 classes. [2016-08-06 14:26:48.878313] Creating model Epoch 1/10 59834/59834 > код Или на картинках: Видно, что мы не дотренировали и точность модели можно повысить, просто увеличив время тренировки. Но, как любят говорить в университах нерадивые преподаватели — это домашнее задание для желающих. Оценка точности предсказания Численная Оценка точности будет производится на данных за 21-23 июля. accuracy_score = 0.994 roc_auc_score = 0.985 log_loss_score = 0.014 Визуальная Зелёная линия — то, что отмечено на картинках. Синяя линия — бегущее среднее по предыдущим 20 предсказаниям. код, который создаёт картинки Что осталось за кадром. Почему при тренировке модели точность на val лучше, чем на train. Ответ: => потому что на train — эта точность с dropout, а на val — нет Почему выбрана именно такая архитектура модели. Ответ => Хочется сказать: "Но это же очевидно!", но правильный ответ, наверно, всё-таки — читаем конспект лекций на http://cs231n.github.io/, смотрим серию лекций на https://www.youtube.com/watch?v=PlhFWT7vAEw и гоняем соревнования на kaggle.com пока не прийдёт озарение в виде ответа:"Эта архитектура выбрана потому что она работает на очень похожих задачах типа MNIST" На каких картинках модель даёт ошибку. Ответ: => Я глянул одним глазом — это те картинки, где и человек не отличит просто потому что камера не работала. Возможно там есть адекватные изображения, на которых модель даёт ошибку, но это требует более вдумчивого анализа. Где взять код, от всего вышеописанного? Ответ => https://github.com/ternaus/spb_bridges Будет ли модель работать на других мостах? Ответ => не исключено, но кто его знает, надо пробовать. А если бы задача стояла так: По изображениям моста Александра Невского создать модель для предсказания разведения Литейного моста, вы бы действовали так же? Ответ => Нет. У них различная система подъёма, так что там надо было смотреть на данные, пробовать и думат. Вопрос про правильной cross validation стоял бы очень остро. В общем это была бы интересная задача. А если не обрезать изображение, так чтобы остался только мост, то задача стала бы сильно сложнее? Ответ => Стала бы, но не сильно. А что если делать классификацию не на два класса (сведён/разведён), а на три (сведён/разведён/в движении)? Ответ => Если классифицировать на три класса, то получим оценку принадлежности к одному из трёх классов. Но надо менять несколько строк в файле, который делит данные на части, и одну в определении модели. => Домашнее задание для энтузиастов. Пример сложной задачи, на которой надо мозг сломать, чтобы заставить модель хорошо работать => Ответ: Вот прямо сейчас я закончу текст, причешу github c кодом. и начну думать о сегментации нервов на изображениях. Где взять сами картинки с мостами? Ответ: => Это к darkk Сколько нужно нейронов, чтобы узнать, разведён ли мост Александра Невского? Ответ: => И один нейрон, то есть логистическая регрессия выдаст замечательный результат. Послесловие. Это действительно очень простая задача для нейронных сетей на данном этапе развития этого направления в машинном обучении. Причём тут даже и не нейронные сети, а и более простые алгоритмы будут работать на ура. Премущество нейронных сетей в том, что они работают в режиме автоматического извлечения признаков, при наличии большого количества шума, и на некоторых типах данных, например, при работе с изображениями выдают точность на уровне State Of The Art. И данным текстом с приложенным кодом я попытался развеять мнение, что работать с нейронными сетями очень сложно. Нет это не так. Работать с нейронными сетями так чтобы они показывали хорошую точность на сложных задачах — это сложно, но очень многие задачи к этой категории не относятся и порог вхождения в эту область не такой высокий, как может показаться после прочтения новостей на популярных ресурсах.

Метки:  

Oracle объявил о крупнейшей сделке за последние 12 лет

Воскресенье, 31 Июля 2016 г. 16:36 + в цитатник
Фото с сайта rusbase.com Стратегически важной задачей для Oracle является укрепление позиций на рынке облачных технологий. Компания разрабатывает не только собственные облачные сервисы, но и занимается поглощением более мелких игроков. За «облака» Оracle конкурирует с такими компаниями, как Salesforce.com Inc. и Workday Inc., Microsoft и Amazon. Salesforce.com Inc. и Workday Inc. производят программное обеспечение и облачные системы хранения данных. На рынке облачных технологий Microsoft пока заметно отстает от Amazon.com, однако результаты недавно завершившегося квартала показывают, что корпорация успешно трансформируется из продавца лицензий на ПО в поставщика услуг по запросу. Эти результаты приятно удивили инвесторов Microsoft. В IV квартале продажи облачного подразделения Microsoft Azure выросли более чем на 100% по сравнению с аналогичным периодом прошлого года. 28 июля компания Oracle объявила о новом поглощении. На этот раз Oracle покупает дружественную компанию NetSuite за $9,3 миллиарда. За каждую акцию покупатель отдаст $109 наличными. Это на 19% превышает цену ($91,5), которая была зафиксирована на закрытии торгов в среду. Oracle разрабатывает программное обеспечение для бизнес-сегмента. Компания специализируется на выпуске систем управления базами данных и бизнес-приложений. Кроме того, она является поставщиком серверного оборудования. NetSuite – американская компания, по запросу предоставляющая софт и услуги на основе облачных технологий. Покупка этой компании позволит Oracle, как выразился основатель и аналитик Constellation Research Рэй Ванг, «залатать дыры» в стратегии по развитию облачных технологий. Председатель совета директоров Oracle Ларри Эллисон и управляющий директор NetSuite Зак Нельсон сотрудничали и раньше: в 1990-е годы Нельсон был директором по маркетингу в Oracle. Более того, в Oracle какое-то время работал и основатель NetSuite Эван Голдберг. Эллисон является крупнейшим инвестором NetSuite: по данным ежегодного собрания акционеров, Эллисон и его семья владеют 40% акций NetSuite. По этим причинам многие аналитики ожидали подобного исхода. Поглощение NetSuite – одна из крупнейших сделок в истории Oracle. Слева направо: Ларри Элиссон, Зак Нельсон NetSuite является одним из лидеров в разработке приложений для планирования и распределения ресурсов компаний. Эти приложения компания предоставляет по запросу клиентов и использует модель подписки. Самые популярные продукты NetSuite – CRM-система NetSuite CRM, вошедшая в ТОП-20 лучших CRM-систем в мире по версии Gartner, и NetSuite ERP – одна из первых ERP-систем, которые начали распространяться исключительно по подписке. Штаб-квартира компании находится в Калифорнии (США). В четверг NetSuite опубликовала финансовые результаты за второй квартал. Выручка компании достигла $230,8 миллиона и выросла на 30% год к году. У NetSuite открыты представительства в Австралии, Канаде, Чехии, Гонконге, Японии, Нидерландах, Сингапуре, Испании, Тайланде, на Филиппинах, в Уругвае и в Великобритании. Oracle планирует и дальше целенаправленно инвестировать в бизнес NetSuite, не меняя направления его развития. В компании верят, что эти инвестиции быстро окупятся. Oracle известна своей агрессивной тактикой поглощения компаний: за последние месяцы было потрачено более $1 миллиарда на покупку Opower Inc., производящей облачное программное обеспечение для коммунальных служб, и Textura Corp., предоставляющей аналогичные услуги строительным компаниям. В начале июля Oracle и Fujitsu договорились о сотрудничестве в сфере облачных технологий. Они также создадут новый корпоративный альянс, главной задачей которого станет обеспечение корпоративных клиентов решениями, непосредственно связанными с облачным хранением информации. Они будут доступны для японских клиентов, а также для дочерних компаний данных персон во всех странах мира. Одну из своих недавних многомиллионных сделок Oracle заключила в 2014 году: тогда корпорация купила компанию Micros Systems Inc. за $5,3 миллиарда, продававшую подключенные к интернету кассовые аппараты. В число других крупных приобретений Oracle входят принудительное поглощение таких компаний, как PeopleSoft Inc. за $10,3 миллиарда в 2004 году, BEA Systems Inc. за $8,5 миллиарда в 2008 году, а также покупка Sun Microsystems Inc. за $7,4 миллиарда в 2009 году. После объявления о сделке в ходе предварительных торгов цена акций NetSuite выросла на 18% до $108,3, в то время как цена акций Oracle увеличилась на 1,9% до $41,7.
Опыт автоматизации тестирования серверного REST API с помощью Jmeter

Метки:  

Перенос и развертывание рабочих процессов SharePoint 2013

Суббота, 23 Июля 2016 г. 16:43 + в цитатник
При разработке решений SharePoint необходимо иметь возможность переносить рабочие процессы как в пределах фермы, так и с одной фермы SharePoint на другую. Типичный сценарий — перенос в продуктивную среду рабочего процесса, созданного в тестовой среде. Рассмотрим различные подходы к решению данной задачи. Разработка рабочих процессов в Visual Studio Этот вариант предусматривает размещение рабочих процессов в файлы решений SharePoint (*.wsp). Такой подход обеспечивает большУю гибкость и возможности по конфигурированию рабочих процессов, однако в некоторых случаях использование решений типа Farm Solution может быть небезопасно в плане работоспособности и производительности фермы SharePoint. Подробно о разработке рабочих процессов в Visual Studio можно почитать по ссылке. Создание пакета, содержащего рабочий процесс, в SharePoint Designer 2013 Инструмент SharePoint Designer 2013 предоставляет возможность сохранить рабочий процесс в файл шаблона. Сохранение рабочего процесса в файл шаблона называют упаковкой рабочего процесса. Полученный файл шаблона может быть импортирован на целевой сервер SharePoint, что исключает необходимость повторной разработки рабочего процесса на целевом сервере. Следует иметь в виду ограничения на типы рабочих процессов, которые могут быть экспортированы как шаблон: Все типы рабочих процессов платформы SharePoint Workflow 2013 Только повторно используемые (reusable) рабочие процессы платформы SharePoint Workflow 2010. Поскольку мы не планируем использовать устаревшую модель рабочих процессов, данное ограничение для нас не принципиально. Однако полученный файл шаблона представляет собой такой же пакет решения *.wsp как и пакет, генерируемый Visual Studio, а значит данный подход имеет те же недостатки, что и предыдущий, если выполнять развертывание упакованного рабочего процесса непосредственно. Вместо непосредственного развертывания, мы воспользуемся файлом шаблона для извлечения метаданных (файл workflow.xaml), описывающих рабочий процесс. Эти метаданные мы сможем использовать для развертывания рабочего процесса с помощью альтернативных вариантов, описанных ниже. Экспорт workflow.xaml с помощью SharePoint Designer Откройте с помощью SharePoint Designer сайт, на котором развернут рабочий процесс, подлежащий переносу. Выберите в боковой панели «Объекты сайта» пункт меню «Рабочие процессы». Выберите нужный рабочий процесс в списке и нажмите на элемент ленты «Сохранить как шаблон», расположенный в группе «Управление». Появится сообщение: «Шаблон сохранен в библиотеке „Активы сайта“.». Выберите в боковой панели «Объекты сайта» пункт меню «Все файлы». В списке в области основного просмотра выберите элемент с именем «Site Assets». Нажмите F5, чтобы обновить представление. Выберите элемент с именем "<имя рабочего процесса>.wsp" и нажмите на элемент ленты «Экспорт файла», расположенный в группе «Управление». Выберите путь для сохранения файла. Откройте в Проводнике (или другом файловом менеджере) папку, в которую был сохранен файл *.wsp. Переименуйте файл, изменив расширение с «wsp» на «cab». Откройте файл после переименования. Выполните извлечение файла «workflow.xaml» из содержимого архива. Это можно сделать простым перетаскиванием (drag-and-drop) файла в каталог для извлечения. Использование фреймворков для развертывания (Provision Frameworks) Типовые задачи, связанные с переносом и развертыванием артефактов разработки SharePoint, побудили сообщество разработчиков создать удобные инструменты для их автоматизации. Один из таких инструментов — фреймворк SPMeta2. Это мощный инструмент для решения задач развертывания артефактов разработки SharePoint, позволяющий использовать написание кода на языке C# вместо декларативного описания (XML). SPMeta2 поддерживает множество сценариев работы, в том числе сценарии для работы с рабочими процессами. К недостаткам развертывания через фреймворк можно отнести необходимость создания отдельного проекта для его использования даже в простых случаях, когда можно обойтись скриптами PowerShell. Перенос рабочих процессов с помощью скриптов PowerShell Командная консоль PowerShell позволяет решать обширный класс задач, связанных с администрированием SharePoint. Более того: некоторые задачи возможно решить исключительно с помощью этого инструмента. Для переноса рабочих процессов списка разработан скрипт PowerShell, доступный по ссылке. Скрипт использует объект класса WorkflowServicesManager для выполнения операций над рабочими процессами. Для развертывания рабочего процесса с помощью скрипта необходимо получить файл workflow.xaml, содержащий описание рабочего процесса. Выше был описан способ получения файла workflow.xml с помощью SharePoint Designer. Однако проще сделать с помощью функции ExtractWorkflowXaml, определенной в скрипте. Параметры функции: Параметр Описание $url URL узла, ассоциированного с сервисом Workflow, который содержит рабочий процесс $wf_displayname Имя рабочего процесса $workflow_xaml_path Путь к файлу для сохранения Пример использования функции: ExtractWorkflowXaml "http://mysp.com/source" "Test workflow" "C:\spmetadata\workflow.xaml" Для развертывания рабочего процесса необходимо вызвать функцию DeployListWorkflow. Параметры функции: Параметр Описание $workflow_xaml Путь к файлу .xaml $url URL узла, ассоциированного с сервисом Workflow, для которого нужно создать рабочий процесс $list_name Имя списка, с которым должен быть ассоциирован рабочий процесс $wf_displayname Имя рабочего процесса $overwrite Признак необходимости перезаписи определения рабочего процесса, если он уже существует Пример использования функции: DeployListWorkflow "C:\spmetadata\workflow.xaml" "http://mysp.com/sandbox" "Test Workflow List" "My New Workflow" $true Перенос рабочих процессов с помощью скриптов PowerShell позволяет выполнить задачу без использования сторонних инструментов. Плюсы данного решения: Не нужно создавать проект в Visual Studio и писать код, вызывающий функционал фреймворков для развертывания, достаточно простого вызова функции скрипта PowerShell. Возможность извлекать метаданные рабочего процесса простым вызовом функции скрипта PowerShell. Логирование действий в процессе развертывания позволит легко локализовать и исправить ошибку. Минусы данного решения: Скрипт использует серверную объектную модель SharePoint (SSOM), а значит должен выполняться на сервере фермы SharePoint. Для работы скрипта посредством клиентской объектной модели необходима модификация скрипта. Скрипт настраивает лишь базовые атрибуты рабочего процесса, необходимые для его функционирования. Для работы с дополнительными атрибутами необходима модификация скрипта. В текущей версии скрипт предназначен для развертывания рабочих процессов списка. Для работы с другими типами рабочих процессов необходима модификация скрипта. Скрипт сделан наиболее простым с целью демонстрации возможности развертывания рабочих процессов через PowerShell. В дальнейшем планируется расширение функциональности описываемого скрипта.

Метки:  

Очередное требование об использовании отечественных средств шифрования

Вторник, 19 Июля 2016 г. 20:30 + в цитатник
Владимир Путин подписал личное поручение премьеру Дмитрию Медведеву (а не правительству, что было бы логично) об обеспечении «комплекса мероприятий, необходимых для перехода органов власти на использование российских криптографических алгоритмов и средств шифрования» Комментарии на это поручение уже появились. Скажем здесь. Как говориться — о пользе чтения первоисточников. Так в комментариях отмечается, что «правительству, а точнее лично премьер-министру, было поручено выполнить всего одну вещь — поэтапно перевести федеральные органы исполнительной власти, органы государственной власти субъектов Российской Федерации, государственные внебюджетные фонды, органы местного самоуправления на отечественную криптографию при взаимодействие между собой, с организациями и гражданами». На самом деле в поручении написано совсем иное и куда более интересное: Обеспечьте разработку и реализацию комплекса мероприятий, необходимых для поэтапного перехода федеральных органов исполнительной власти, органов государственной власти субъектов Российской Федерации, государственных внебюджетных фондов, органов местного самоуправления на использование российских криптографических алгоритмов и средств шифрования в рамках исполнения полномочий при электронном взаимодействии между собой, с гражданами и организациями. Тоесть лично премьер-министру поручено обеспечить подготовку к переходу, а не сам переход. О сроках перехода речи нет. Нюанс однако. Еще один нюанс — отсутствие в поручении требования об использовании сертифицированного ПО. А ведь согласно ФЗ-149 перечисленные организации должны использовать сертифицированные средства. Логично было бы поручить выяснить причины неисполнения закона и наказать виновных… Очередной поворот в деле использования сертифицированных средств? Хотелось бы, но маловероятно. Далее президент указывает предусмотреть: 1) предоставление безвозмездного доступа гражданам Российской Федерации к использованию российских средств шифрования для электронного взаимодействия с органами государственной власти и органами местного самоуправления; Очень интересный пункт. На Госуслуги можно будет обращаться только с помощью российских средств шифрования? Интересно, что президент указывает предусмотреть доступ, а не разработать ПО. Предполагается, что такие средства для всех платформ есть? Опять же не указано, что средства должны быть сертифицированы. Интересный нюанс. Кстати законный способ обратиться с требованием о предоставлении такого ПО. Но только после нового года. 2) законодательные меры с целью исключить применение оборудования, позволяющего третьим лицам вмешиваться в работу криптографических протоколов при передаче данных с использованием сети связи общего пользования, кроме случаев реализации органами, осуществляющими оперативно-разыскную деятельность, мероприятий по снятию информации с технических каналов связи в соответствии с требованиями законодательства Российской Федерации. Тут интересно, что кроме криптографических средств защиты требуется предотвратить использование средств типа человек-посередине и аналогичных. Судя по формулировке, нагрузка ляжет на провайдеров, обеспечивающих передачу данных. Выполнено поручение должно быть в срок до 1 декабря 2017 г.

Метки:  

[Из песочницы] Транспорт-бот Jabber конференций для Telegram

Понедельник, 18 Июля 2016 г. 21:20 + в цитатник
Доброго времени суток. В один прекрасный день, после значительного перерыва, судьба вновь столкнула меня с jabber-конференциями. Правда, среди знакомых jabber уже никто не использует, 2007 год канул в лету, а основным средством общения стал Telegram. Поддержка XMPP на мобильных устройствах оставляла желать лучшего — клиенты на Android хороши каждый в чём-то одном, с iOS и WP всё мягко скажем, не очень. И особенности протокола тоже сказываются на автономности. Поэтому возникла мысль: а не сделать ли бота, которой будет транслировать сообщения из конференций в чат Telegram? В качестве инструментов использовались: Python 3.5 aiohttp для API Telegram slixmpp для xmpp gunicorn как wsgi сервер nginx как фронтенд и прокси для gunicorn VS Code в качестве IDE Основные возможности и зависимости Из готовых реализаций удалось найти только jabbergram, но он позволяет работать только с одним юзером. Ещё есть реализация на Go, с которым опыта работы не было, так что этот вариант не рассматривался и о функционале не могу ничего сказать. Выбор библиотек обусловлен, в основном, желанием поработать с asyncio. Изначально разрабатывалась версия с tet-a-tet диалогом для одного пользователя, которая позднее была расширена использованием XMPP Components для групповых чатов, с отдельным xmpp-юзером для каждого участника. Бот настроен так, что добавить его в чат с иным пользователем невозможно, поэтому как универсальную реализацию рассматривать нельзя. Почему так сделано? API ботов весьма ограничивает количество входящих/исходящих запросов за короткое время, и при достаточно интенсивном обмене сообщениями будут возникать ошибки. Что есть в целом: Отправка/приём текстовых сообщений в общем диалоге Двусторонее редактирование сообщений (XEP-0308) Приватные сообщения Ответ по нику собеседника Файлы, аудио, изображения (загружаются через сторонний сервис) Стикеры (заменяются на emoji) Автостатус при неактивности с последнего сообщения Смена ника в конференции Тем не менее, есть различия между двумя версиями: «Подсветка» сообщений с ником пользователя не работает в групповых чатах, так как в телеграме невозможно это сделать индивидуально Бот делает групповой чат в телеграмм бесшовным, т.е., если участника забанили в xmpp-конференции, он не может писать сообщения в чат При разработке удобно использовать виртуальные окружения, так что можно создать одно: $ python3.5 -m venv venv $ . venv/bin/activate Для использования нужно установить из pip aiohttp, slixmpp и ujson. При желании можно добавить gunicorn. С окружением или без, все пакеты есть в PyPI: $ pip3 install aiohttp slixmpp ujson В конце поста есть ссылки на bitbucket репозитории с исходниками. История telegram Прежде стоит отметить, что готовые фреймворки для API Telegram не использовались по ряду причин: На момент начала работы asyncio поддерживал только aiotg. Сейчас, кажется, все популярные Вебхуки часто реализованы как добавка к лонг пуллу и в любом случае приходится использовать библиотеку для обработки входящих соединений В целом, многие возможности библиотек были просто не нужны Ну или просто NIH Так что была сделана простенькая обёртка над основными объектами и методами bots api, запросы отправляются с помощью requests, json парсится ujson, потому что быстрее. Настройка бота осуществляется посредством скрипта-конфига: config.pyVERSION = "0.1" TG_WH_URL = "https://yourdomain.tld/path/123456" TG_TOKEN = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" TG_CHAT_ID = 12345678 XMPP_JID = "jid@domain.tld" XMPP_PASS = "yourpassword" XMPP_MUC = "muc@conference.domain.tld" XMPP_NICK = "nickname" DB_FILENAME = "bot.db" LOG_FILENAME = "bot.log" ISIDA_NICK = "IsidaBot" # для фильтрации сообщений с заголовками ссылок от xmpp бота UPLOADER_URL = "example.com/upload" # загрузчик файлов # для групповых чатов нет XMPP_JID/XMPP_PASS/XMPP_NICK и используются дополнительно иные параметры: # TG_INVITE_URL = "https://telegram.me/joinchat/ABCDefGHblahblah" # ссылка на групповой чат # COMPONENT_JID = "tg.xmpp.domain.tld" # COMPONENT_PASS = "password" # XMPP_HOST = "xmpp.domain.tld" # XMPP_PORT = 5347 Представление объектов выглядит примерно так: mapping.pyclass User(object): def __str__(self): return '<User .format(self.id, self.first_name, self.last_name, self.username) def __init__(self, obj): self.id = obj.get('id') self.first_name = obj.get('first_name') self.last_name = obj.get('last_name') self.username = obj.get('username') Класс бота для выполнения запросов: bind.pyclass Bot(object): def _post(self, method, getMe') return User(r.get('result')) if r.get('ok') else None ... @property def token(self): return self.__token ... def __init__(self, token): self.__token = token ... Все запросы обрабатываются с помощью вебхуков, которые приходят на адрес TG_WH_URL. RequestHandler.handle() — coroutine для обработки запросов aiohttp. handler.pyfrom aiohttp import web import asyncio import tgworker as tg # модуль для работы с bots api import mucbot as mb # модуль с процедурами xmpp import tinyorm as orm # небольшая обёртка над sqlite3 class RequestHandler(object): ... async def handle(self, request): r = await request.text() try: ... update = tg.Update(ujson.loads(r)) log.debug("TG Update object: {}".format(ujson.loads(r))) ... except: log.error("Unexpected error: {}".format(sys.exc_info())) ... raise finally: return POST', '/', whHandler.handle) ... В процессе обработки текстовые сообщения отправляются в конференцию. Либо как приватное сообщение, если это ответ на приватное сообщение или при ответе добавлена команда /pm. Файлы перед отправкой загружаются на сторонний сервер и в конференцию отправляется ссылка на файл. Скорее всего, для общего использования такой подход не подойдёт и придётся сделать загрузку на Imgur или другой сервис, который предоставляет API. Сейчас же файлы просто отправляются на сервер jTalk. С позволения разработчика, конечно. Но, так как это всё-таки для личного пользования, то адрес вынесен в конфиг. Стикеры просто заменяются на их emoji-представление. Опус о xmpp В своё время для python было две весьма популярных библиотеки — SleekXMPP и xmpppy. Вторая уже устарела и не поддерживается, а асинхронность SleekXMPP реализована потоками. Из библиотек, которые поддерживают работу с asyncio есть aioxmpp и slixmpp. Aioxmpp пока весьма сырая и у неё нет исчерпывающей документации. Тем не менее, первая версия бота использовала aioxmpp, но потом переписана для slixmpp. Slixmpp — это SleekXMPP на asyncio, интерфейс там такой же, соответственно, большинство плагинов будут работать. Она используется в консольном jabber-клиенте Poezio. К тому же, у slixmpp замечательная поддержка, которая помогла решить некоторые проблемы с библиотекой. Однопользовательская версия использует slixmpp.ClientXMPP в качестве базового класса, когда как многопользовательская — slixmpp.ComponentXMPP Обработчик событий XMPP выглядит примерно вот так: mucbot.pyimport slixmpp as sx class MUCBot(sx.ClientXMPP): # class MUCBot(sx.ComponentXMPP): # версия для групповых чатов ... # # Event handlers # def _sessionStart(self, event): self.get_roster() ) self.plugin['xep_0045'].joinMUC(self.__mucjid, self.__nick, \n', ' '))) ... # # Presence handler # def _presence(self, presence: sx.Presence): log.debug("Got Presence {}".format(str(presence).replace('\n', ' '))) ... # # Initialization # def __init__(self, db, tgBot, tgChatId, jid, password, mucjid, nick): super().__init__(jid, password) self.__jid = sx.JID(jid) self.__mucjid = sx.JID(mucjid) self.__nick = nick self.__tg = tgBot self.__db = db self.__chat_id = tgChatId ... # настройка плагинов поддержки разных XEP self.register_plugin('xep_XXXX') # Service Discovery ... # подписка на события xmlstream self.add_event_handler("session_start", self._sessionStart) self.add_event_handler("message", self._message) self.add_event_handler("muc::{}::presence".format(mucjid), self._presence) ... Очевидно, обязательным будет подключить XEP-0045 для MUC, еще полезным будет XEP-0199 для пингов и XEP-0092, чтобы показывать всем какие мы классные свою версию. Сообщения из xmpp просто отправляются в чат с пользователя (или групповой чат) с TG_CHAT_ID из конфига. Настройка XMPP-сервера для работы с компонентами Интересная особенность — это использование компонентов xmpp для динамического создания пользователей. При этом не надо создавать отдельный объект для каждого пользователя и хранить данные для авторизации. Минус в том, что не получится использовать свой основной аккаунт. Из соображений лёгкости и простоты выбран Prosody в качестве xmpp-сервера. Описывать конфигурацию не буду, единственное отличие от шаблонна — включение компонента (COMPONENT_JID из конфига бота): Component "tg.xmpp.domain.tld" component_secret = "password" конфигурация Prosody В общем-то, это вся настройка xmpp. Остаётся только перезапустить prosody. Сказ о gunicorn и nginx Если так совпало, что у вас по счастливой случайности наружу смотрит nginx, стоит добавить директиву в секцию server. nginx.cfglocation /path/to/123456 { error_log /path/to/www/logs/bot_error.log; access_log /path/to/www/logs/bot_access.log; alias /path/to/www/bot/public; proxy_pass http://unix:/path/to/www/bot/bot.sock:/; } Настройку HTTPS описывать, думаю, не стоит, но сертификаты получались через letsencrypt. Конфигурацию для примера брал из этого комментария. Полный конфиг можно посмотреть здесь, параметры для шифрования подбирались в Mozilla SSL Generator Вся эта конструкция из… палок работает на VPS с Debian 8.5, так что для systemd написан сервис, который запускает gunicorn: bot.service[Unit] > [Service] > > > > > > > > [Install] > Конечно, не помешает выполнить systemctl daemon-reload и systemctl enable bot. Ссылки на исходники Однопользовательская версия Версия для групповых чатов P.S. На премию красивейший код года не претендую. Хотелось, конечно, сделать хорошо, но получилось как всегда.

Метки:  

Библиотека f для функционального программирования в Питоне

Воскресенье, 17 Июля 2016 г. 14:47 + в цитатник
Привет, коллеги! Я расскажу о библиотеке для Питона с лаконичным названием f. Это небольшой пакет с функциями и классами для решения задач в функциональном стиле. — Что, еще одна функциональная либа для Питона? Автор, ты в курсе, что есть fn.py и вообще этих функциональных поделок миллион? — Да, в курсе. Причины появления библиотеки Я занимаюсь Питоном довольно давно, но пару лет назад всерьез увлекся функциональным программированием и Кложей в частности. Некоторые подходы, принятые в ФП, произвели на меня столь сильное впечатление, что мне захотелось перенести их в повседневную разработку. Подчеркну, что не приемлю подход, когда паттерны одного языка грубо внедряют в другой без учета его принципов и соглашений о кодировании. Как бы я не любил ФП, меня раздражает нагромождение мап и лямбд в попытке выдать это за функциональный стиль. Поэтому я старался оформить мои функции так, чтобы не встретить сопротивление коллег. Например, использовать внутри стандартные циклы с условиями вместо мапов и редьюсов, чтобы облегчить понимание тем, кто не знаком с ФП. В результате некоторые из частей библиотеки побывали в боевых проектах и, возможно, все еще в строю. Сперва я копипастил их из проекта в проект, потом завел файлик-свалку функций и сниппетов, и, наконец, оформил все библиотекой, пакетом в Pypi и документаций. Общие сведения Библиотека написана на чистом Питоне и работает на любой ОС, в т.ч. на Виндузе. Поддерживаются обе ветки Питона. Конкретно я проверял на версиях 2.6, 2.7 и 3.5. Если возникнут трудности с другими версиями, дайте знать. Единственная зависимость — пакет six для гибкой разработки сразу под обе ветки. Библиотека ставится стандартным образом через pip: pip install f Все функции и классы доступны в головном модуле. Это значит, не нужно запоминать пути к сущностям: import f f.pcall(...) f.maybe(...) f.io_wraps(...) f.L[1, 2, 3] Пакет несет на борту следующие подсистемы: набор различных функций для удобной работы с данными модуль предикатов для быстрой проверки на какие-либо условия улучшенные версии коллекций — списка, кортежа, словаря и множества реализация дженерика монады Maybe, Either, IO, Error В разделах ниже я приведу примеры кода с комментариями. Функции Первой функцией, которую я перенес в Питон из другой экосистемы, стала pcall из языка Луа. Я программировал на ней несколько лет назад, и хотя язык не функциональный, был от него в восторге. Функция pcall (protected call, защищенный вызов) принимает другую функцию и возвращает пару (err, result), где либо err — ошибка и result пуст, либо наоборот. Этот подход знаком нам по другим языкам, например, Джаваскрипту или Гоу. import f f.pcall(lambda a, b: a / b, 4, 2) >>> (None, 2) f.pcall(lambda a, b: a / b, 4, 0) >>> (ZeroDivisionError('integer division or modulo by zero'), None) Функцию удобно использовать как декоратор к уже написанным функциям, которые кидают исключения: @f.pcall_wraps def func(a, b): return a / b func(4, 2) >>> (None, 2) func(4, 0) >>> (ZeroDivisionError('integer division or modulo by zero'), None) Используя деструктивный синтаксис, можно распаковать результат на уровне сигнатуры: def process((err, result)): if err: logger.exception(err) return 0 return result + 42 process(func(4, 2)) К большому сожалению, деструктивный синтаксис выпилен в третьем Питоне. Приходится распаковывать вручную. Интерсно, что использование пары (err, result) есть ни что иное, как монада Either, о которой мы еще поговорим. Вот более реалистичный пример pcall. Часто приходится делать ХТТП-запросы и получать структуры данных из джейсона. Во время запроса может произойти масса ошибок: кривые хосты, ошибка резолва таймаут соединения сервер вернул 500 сервер вернул 200, но парсинг джейсона упал сервер вернул 200, но в ответе ошибка Заворачивать вызов в try с отловом четырех исключений означает сделать код абсолютно нечитаемым. Рано или поздно вы забудете что-то перехватить, и программа упадет. Вот пример почти реального кода. Он извлекает пользователя из локального рест-сервиса. Результат всегда будет парой: @f.pcall_wraps def get_user(use_id): resp = requests.get("http://local.auth.server", > Рассмотрим другие функции библиотеки. Мне бы хотелось выделить f.achain и f.ichain. Обе предназначены для безопасного извлечения данных из объектов по цепочке. Предположим, у вас Джанго со следующими моделями: Order => Office => Department => Chief При этом все поля not null и вы без страха ходите по смежным полям: order = > Да, я в курсе про select_related, но это роли не играет. Ситуация справедлива не только для ОРМ, но и для любой другой структуры класов. Так было в нашем проекте, пока один заказчик не попросил сделать некоторые ссылки пустыми, потому что таковы особенности его бизнеса. Мы сделали поля в базе nullable и были рады, что легко отделались. Конечно, из-за спешки мы не написали юнит-тесты для моделей с пустыми ссылками, а в старых тестах модели были заполнены правильно. Клиент начал работать с обновленными моделями и получил ошибки. Функция f.achain безопасно проходит по цепочке атрибутов: f.achain(model, 'office', 'department', 'chief', 'name') >>> John Если цепочка нарушена (поле равно None, не существуте), результат будет None. Функция-аналог f.ichain пробегает по цепочке индексов. Она работает со словарями, списками и кортежами. Функция удобна для работы с данными, полученными из джейсона: data = json.loads('''{"result": [{"kids": [{"age": 7, "name": "Leo"}, {"age": 1, "name": "Ann"}], "name": "Ivan"}, {"kids": null, "name": "Juan"}]}''') f.ichain(data, 'result', 0, 'kids', 0, 'age') >>> 7 f.ichain(data, 'result', 0, 'kids', 42, 'dunno') >> None Обе функции я забрал из Кложи, где их предок называется get-in. Удобство в том, что в микросерверной архитектуре структура ответа постоянно меняется и может не соответствовать здравому смыслу. Например, в ответе есть поле-объект "user" с вложенными полями. Однако, если пользователя по какой-то причине нет, поле будет не пустым объектом, а None. В коде начнут возникать уродливые конструкции типа: data.get('user', {]}).get('address', {}).get('street', '<unknown>') Наш вариант читается легче: f.ichain(data, 'user', 'address', 'street') or '<unknown>' Из Кложи в библиотеку f перешли два threading-макроса: -> и ->>. В библиотеке они называются f.arr1 и f.arr2. Оба пропускают исходное значение сквозь функиональные формы. Этот термин в Лиспе означает выражение, которе вычисляется позже. Другими словами, форма — это либо функция func, либо кортеж вида (func, arg1, arg2, ...). Такую форму можно передать куда-то как замороженное выражение и вычислить позже с изменениями. Получается что-то вроде макросов в Лиспе, только очень убого. f.arr1 подставляет значение (и дальнейший результат) в качестве первого аргумента формы: f.arr1( -42, # начальное значение (lambda a, b: a + b, 2), # форма abs, # форма str, # форма ) >>> "40" f.arr2 делает то же самое, но ставит значение в конец формы: f.arr2( -2, abs, (lambda a, b: a + b, 2), str, ("000".replace, "0") ) >>> "444" Далее, функция f.comp возвращает композицию функций: comp = f.comp(abs, (lambda x: x * 2), str) comp(-42) >>> "84" f.every_pred строит супер-предикат. Это такой предикат, который истиннен только если все внутренние предикаты истинны. pred1 = f.p_gt(0) # строго положительный pred2 = f.p_even # четный pred3 = f.p_not_eq(666) # не равный 666 every = f.every_pred(pred1, pred2, pred3) result = filter(every, (-1, 1, -2, 2, 3, 4, 666, -3, 1, 2)) tuple(result) >>> (2, 4, 2) Супер-предикат ленив: он обрывает цепочку вычислений на первом же ложном значении. В примере выше использованы предикаты из модуля predicate.py, о котором мы еще поговорим. Функция f.transduce — наивная попытка реализовать паттерн transducer (преобразователь) из Кложи. Короткими словами, transducer — это комбинация функций map и reduce. Их суперпозиция дает преобразование по принципу "из чего угодно во что угодно без промежуточных данных": f.transduce( (lambda x: x + 1), (lambda res, item: res + str(item)), (1, 2, 3), "" ) >>> "234" Модуль функций замыкет f.nth и его синонимы: f.first, f.second и f.third для безопасного обращения к элементам коллекций: f.first((1, 2, 3)) >>> 1 f.second((1, 2, 3)) >>> 2 f.third((1, 2, 3)) >>> 3 f.nth(0, [1, 2, 3]) >>> 1 f.nth(9, [1, 2, 3]) >>> None Предикаты Предикат — это выражение, возвращающие истину или ложь. Предикаты используют в математике, логике и функциональном программировании. Часто предикат передают в качестве переменной в функции высшего порядка. Я добавил несколько наиболее нужных предикатов в библиотеку. Предикаты могут унарными (без параметров) и бинарными (или параметрическими), когда поведение предиката зависит от первого аргумента. Рассмотрим примеры с унарными предикатами: f.p_str("test") >>> True f.p_str(0) >>> False f.p_str(u"test") >>> True # особый предикат, который проверяет на int и float одновременно f.p_num(1), f.p_num(1.0) >>> True, True f.p_list([]) >>> True f.p_truth(1) >>> True f.p_truth(None) >>> False f.p_none(None) >>> True Теперь бинарные. Создадим новый предикат, который утверждает, что что-то больше нуля. Что именно? Пока неизвесто, это абстракция. p = f.p_gt(0) Теперь, имея предикат, проверим любое значение: p(1), p(100), p(0), p(-1) >>> True, True, False, False По аналогии: # Что-то больше или равно нуля: p = f.p_gte(0) p(0), p(1), p(-1) >>> True, True, False # Проверка на точное равенство: p = f.p_eq(42) p(42), p(False) >>> True, False # Проверка на ссылочное равенство: ob1 = object() p = f.p_is(ob1) p(object()) >>> False p(ob1) >>> True # Проверка на вхождение в известную коллекцию: p = f.p_in((1, 2, 3)) p(1), p(3) >>> True, True p(4) >>> False Я не буду приводить примеры всех предикатов, это утомительно и долго. Предикаты прекрасно работают с функциями композиции f.comp, супер-предиката f.every_pred, встроенной функцией filter и дженериком, о котором речь ниже. Дженерики Дженерик (общий, обобщенный) — вызываемый объект, который имеет несколько стратегий вычисления результата. Выбор стратегии определяется на основании входящий параметров: их состава, типа или значения. Дженерик допускает наличие стратегии по умолчанию, когда не найдено ни одной другой для переданных параметров. В Питоне нет дженериков из коробки, и особо они не нужны. Питон достаточно гибок, чтобы построить свою систему подбора функции под входящие значения. И все же, мне настолько понравилась реализация дженериков в Коммон-Лиспе, что из спортивного интереса я решил сделать что-то подобное в своей библиотеке. Выглядит это примерно так. Сначала создадим экземпляр дженерика: gen = f.Generic() Теперь расширим его конкретными обработчиками. Декоратор .extend принимает набор предикатов для этого обработчика, по одному на аргумент. @gen.extend(f.p_int, f.p_str) def handler1(x, y): return str(x) + y @gen.extend(f.p_int, f.p_int) def handler2(x, y): return x + y @gen.extend(f.p_str, f.p_str) def handler3(x, y): return x + y + x + y @gen.extend(f.p_str) def handler4(x): return "-".join(reversed(x)) @gen.extend() def handler5(): return 42 Логика под капотом проста: декоратор подшивает функцию во внутренний словарь вместе с назначенными ей предикатами. Теперь дженерик можно вызывать с произвольными аргументами. При вызове ищется функция с таким же количеством предикаторв. Если каждый предикат возвращает истину для соответствующего аргумента, считается, что стратегия найдена. Возвращается результат вызова найденной функции: gen(1, "2") >>> "12" gen(1, 2) >>> 3 gen("fiz", "baz") >>> "fizbazfizbaz" gen("hello") >>> "o-l-l-e-h" gen() >>> 42 Что случится, если не подошла ни одна стратегия? Зависит от того, был ли задан обработчик по умолчанию. Такой обработчик должен быть готов встретить произвольное число аргументов: gen(1, 2, 3, 4) >>> TypeError exception goes here... @gen.default def default_handler(*args): return "default" gen(1, 2, 3, 4) >>> "default" После декорирования функция становится экземпляром дженерика. Интересный прием — вы можете перебрасывать исполнение одной стратегии в другую. Получаются функции с несколькими телами, почти как в Кложе, Эрланге или Хаскеле. Обработчик ниже будет вызван, если передать None. Однако, внутри он перенаправляет нас на другой обработчик с двумя интами, это handler2. Который, в свою очередь, возвращает сумму аргументов: @gen.extend(f.p_none) def handler6(x): return gen(1, 2) gen(None) >>> 3 Коллекции Библиотека предоставляет "улучшенные" коллекции, основанные на списке, кортеже, словаре и множестве. Под улучшениями я имею в виду дополнительные методы и некоторые особенности в поведении каждой из коллекций. Улучшенные коллекции создаются или из обычных вызовом класса, или особым синтаксисом с квадратными скобками: f.L[1, 2, 3] # или f.List([1, 2, 3]) >>> List[1, 2, 3] f.T[1, 2, 3] # или f.Tuple([1, 2, 3]) >>> Tuple(1, 2, 3) f.S[1, 2, 3] # или f.Set((1, 2, 3)) >>> Set{1, 2, 3} f.D[1: 2, 2: 3] >>> Dict{1: 2, 2: 3} # или f.Dict({1: 2, 2: 3}) Коллекции имеют методы .join, .foreach, .map, .filter, .reduce, .sum. Список и кортеж дополнительно реализуют .reversed, .sorted, .group, .distinct и .apply. Методы позволяют получить результат вызовом его из коллекции без передачи в функцию: l1 = f.L[1, 2, 3] l1.map(str).join("-") >>> "1-2-3" result = [] def collect(x, > l1.group(2) >>> List[List[1, 2], List[3]] Не буду утомлять листингом на каждый метод, желающие могут посмотреть исходный код с комментариями. Важно, что методы возвращают новый экземпляр той же коллекции. Это уменьшает вероятность ее случайного измнения. Операция .map или любая другая на списке вернет список, на кортеже — кортеж и так далее: f.L[1, 2, 3].filter(f.p_even) >>> List[2] f.S[1, 2, 3].filter(f.p_even) >>> Set{2} Словарь итерируется по парам (ключ, значение), о чем я всегда мечтал: f.D[1: 1, 2: 2, 0: 2].filter(lambda (k, v): k + v > Улучшенные коллекции можно складывать с любой другой коллекцией. Результатом станет новая коллекция этого (левого) типа: # Слияние словарей a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 5} # Множество + стандартный спосок f.S[1, 2, 3] + ["a", 1, "b", 3, "c"] >>> Set{'a', 1, 2, 3, 'c', 'b'} # Список и обычный кортеж f.L[1, 2, 3] + (4, ) List[1, 2, 3, 4] Любую коллекцию можно переключить в другую: f.L["a", 1, "b", 2].group(2).D() >>> Dict{"a": 1, "b": 2} f.L[1, 2, 3, 3, 2, 1].S().T() >>> Tuple[1, 2, 3] Комбо! f.L("abc").map(ord).map(str).reversed().join("-") >>> "99-98-97" def pred(pair): k, v = pair return k > Монады Последний и самый сложный раздел в библиотеке. Почитав цикл статей о монадах, я отважился добавить в библиотеку их тоже. При этом позволил себе следующие отклонения: Проверки входных значений основаны не на типах, как в Хаскеле, а на предикатах, что делает монады гибче. Оператор > в Хаскеле невозможно перенести в Питон, поэтому он фигурирует как >> (он же __rshift__, битовый сдвиг вправо). Проблема в том, что в Хаскеле тоже есть оператор >>, но используется он реже, чем >. В итоге, в Питоне под >> мы понимаем > из Хаскела, а оригинальный >> просто не используем. Не смотря на усилия, я не смог реализовать do-нотацию Хаскелла из-за ограничений синтаксиса в Питоне. Пробовал и цикл, и генератор, и контекстные менеджеры — все мимо. Maybe Монада Maybe (возможно) так же известна как Option. Этот класс монад представлен двумя экземплярами: Just (или Some) — хранилище положительного результата, в которм мы заинтересованы. Nothing (в других языках — None) — пустой результат. Простой пример. Определим монадный конструктор — объект, который будет преобразовывать скалярные (плоские) значения в монадические: MaybeInt = f.maybe(f.p_int) По-другому это называется unit, или монадная единица. Теперь получим монадные значения: MaybeInt(2) >>> Just[2] MaybeInt("not an int") >>> Nothing Видим, что хорошим результатом будет только то, что проходит проверку на инт. Теперь попробуем в деле монадный конвеер (monadic pipeline): MaybeInt(2) >> (lambda x: MaybeInt(x + 2)) >>> Just[4] MaybeInt(2) >> (lambda x: f.Nothing()) >> (lambda x: MaybeInt(x + 2)) >>> Nothing Из примера видно, что Nothing прерывает исполнения цепочки. Если быть совсем точным, цепочка не обрывается, а проходит до конца, только на каждом шаге возвращается Nothing. Любую функцию можно накрыть монадным декоратором, чтобы получать из нее монадические представления скаляров. В примере ниже декоратор следит за тем, чтобы успехом считался только возрат инта — это значение пойдет в Just, все остальное — в Nothing: @f.maybe_wraps(f.p_num) def mdiv(a, b): if b: return a / b else: return None mdiv(4, 2) >>> Just[2] mdiv(4, 0) >>> Nothing Оператор >> по другому называется монадным связыванием или конвеером (monadic binding) и вызывается методом .bind: MaybeInt(2).bind(lambda x: MaybeInt(x + 1)) >>> Just[3] Оба способа >> и .bind могут принять не только функцию, но и функциональную форму, о которой я уже писал выше: MaybeInt(6) >> (mdiv, 2) >>> Just[3] MaybeInt(6).bind(mdiv, 2) >>> Just[3] Чтобы высвободить скалярное значение из монады, используйте метод .get. Важно помнить, что он не входит в классическое определение монад и является своего рода поблажкой. Метод .get должен быть строго на конце конвеера: m = MaybeInt(2) >> (lambda x: MaybeInt(x + 2)) m.get() >>> 3 Either Эта монада расширяет предыдущую. Проблема Maybe в том, что негативный результат отбрасывается, в то время как мы всегда хотим знать причину. Either состоит из подтипов Left и Right, левое и правое значения. Левое значение отвечает за негативный случай, а правое — за позитивный. Правило легко запомнить по фразе "наше дело правое (то есть верное)". Слово right в английском языке так же значит "верный". А вот и флешбек из прошлого: согласитесь, напоминает пару (err, result) из начала статьи? Коллбеки в Джаваскрипте? Результаты вызовов в Гоу (только в другом порядке)? То-то же. Все это монады, только не оформленные в контейнеры и без математического аппарата. Монада Either используется в основном для отлова ошибок. Ошибочное значение уходит влево и становится результатом конвеера. Корректный результат пробрысывается вправо к следующим вычислениям. Монадический конструктор Either принимает два предиката: для левого значения и для правого. В примере ниже строковые значения пойдут в левое значение, числовые — в правое. EitherStrNum = f.either(f.p_str, f.p_num) EitherStrNum("error") >>> Left[error] EitherStrNum(42) >>> Right[42] Проверим конвеер: EitherStrNum(1) >> (lambda x: EitherStrNum(x + 1)) >>> Right[2] EitherStrNum(1) >> (lambda x: EitherStrNum("error")) \ >> (lambda x: EitherStrNum(x + 1)) >>> Left[error] Декоратор f.either_wraps делает из функции монадный конструктор: @f.either_wraps(f.p_str, f.p_num) def ediv(a, b): if b > IO Монада IO (ввод-вывод) изолирует ввод-вывод данных, например, чтение файла, ввод с клавиатуры, печать на экран. Например, нам нужно спросить имя пользователя. Без монады мы бы просто вызвали raw_input, однако это снижает абстракцию и засоряет код побочным эффектом. Вот как можно изолировать ввод с клавиатуры: IoPrompt = f.io(lambda prompt: raw_input(prompt)) IoPrompt("Your name: ") # Спросит имя. Я ввел "Ivan" и нажал RET >>> IO[Ivan] Поскольку мы получили монаду, ее можно пробросить дальше по конвееру. В примере ниже мы введем имя, а затем выведем его на экран. Декоратор f.io_wraps превращает функцию в монадический конструктор: import sys @f.io_wraps def input(msg): return raw_input(msg) @f.io_wraps def write(text, chan): chan.write(text) input("name: ") >> (write, sys.stdout) >>> name: Ivan # ввод имени >>> Ivan # печать имени >>> IO[None] # результат Error Монада Error, она же Try (Ошибка, Попытка) крайне полезна с практической точки зрения. Она изолирует исключения, гарантируя, что результатом вычисления станет либо экземпляр Success с правильным значением внутри, либо Failture с зашитым исключением. Как и в случае с Maybe и Either, монадный конвеер исполняется только для положительного результата. Монадический конструктор принимает функцию, поведение которой считается небезопасным. Дальнейшие вызовы дают либо Success, либо Failture: Error = f.error(lambda a, b: a / b) Error(4, 2) >>> Success[2] Error(4, 0) >>> Failture[integer division or modulo by zero] Вызов метода .get у экземпляра Failture повторно вызовет исключение. Как же до него добраться? Поможет метод .recover: Error(4, 0).get() ZeroDivisionError: integer division or modulo by zero # value variant Error(4, 0).recover(ZeroDivisionError, 42) Success[2] Этот метод принимает класс исключения (или кортеж классов), а так же новое значение. Результатом становится монада Success с переданным значением внутри. Значение может быть и функцией. Тогда в нее передается экземпляр исключения, а результат тоже уходит в Success. В этом месте появляется шанс залогировать исключение: def handler(e): logger.exception(e) return 0 Error(4, 0).recover((ZeroDivisionError, TypeError), handler) >>> Success[0] Вариант с декоратором. Функции деления и извлечения корня небезопасны: @f.error_wraps def tdiv(a, b): return a / b @f.error_wraps def tsqrt(a): return math.sqrt(a) tdiv(16, 4) >> tsqrt >>> Success[2.0] tsqrt(16).bind(tdiv, 2) >>> Success[2.0] Конвеер с расширенным контекстом Хорошо, когда функции из конвеера требуют данные только из предыдущей монады. А что делать, если нужно значение, полученное два шага назад? Где хранить контекст? В Хаскеле это проблему решает та самая do-нотация, которую не удалось повторить в Питоне. Придется воспользоваться вложенными функциями: def mfunc1(a): return f.Just(a) def mfunc2(a): return f.Just(a + 1) def mfunc3(a, b): return f.Just(a + b) mfunc1(1) >> (lambda x: mfunc2(x) >> (lambda y: mfunc3(x, y))) # 1 2 1 2 >>> Just[3] В примере выше затруднения в том, что функции mfunc3 нужно сразу два значения, полученных из других монад. Сохранить контекст пересенных x и y удается благодаря замыканиям. После выхода из замыкания цепочку можно продолжить дальше. Заключение Итак, мы рассмотрели возможности библиотеки f. Напомню, проект не ставит цель вытеснить другие пакеты с функциональным уклоном. Это всего лишь попытка обобщить разрозненную практику автора, желание попробовать себя в роли мейнтейнера проекта с открытым исходным кодом. А еще — привлечь интерес начинающих разработчиков к функциональному подходу. Ссылка на Гитхаб. Документация и тесты — там же. Пакет в Pypi. Я надеюсь, специалисты по ФП простят неточности в формулировках. Буду рад замечаниям в комментариях. Спасибо за внимание.
Создание блога на Symfony 2.8 lts [ Часть 5.1]

Метки:  

Если вы работаете с государственными организациями

Вторник, 05 Июля 2016 г. 21:14 + в цитатник
По адресу http://regulation.gov.ru/projects# доступен очередной проект закона о внесении очередных изменений в закона «Об информации, информационных технологиях и о защите информации». Точнее на данном портале сейчас выложено два таких проекта, но нас интересует проект закона от ФСТЭК РФ: Что же предполагается изменить в методах защиты и кого касаются изменения? Стоит обратить внимание на то, что проект касается защиты «государственных информационных системах, а также иных информационных системах, в которых на основании договоров или иных законных основаниях содержится (обрабатывается) информация, обладателями которой являются государственные органы или государственные корпорации». Напомним, что требования по защите государственных информационных систем были описаны в семнадцатом приказе ФСТЭК РФ. Проект закона указывает, что требования данного приказа распространяются не только на государственные ИС, но и на все организации, работающие с данными, полученными от них. Требования о защите информации, содержащейся в государственных информационных системах, а также иных информационных системах, в которых на основании договоров или иных законных основаниях содержится (обрабатывается) информация, обладателями которой являются государственные органы или государственные корпорации, устанавливаются федеральным органом исполнительной власти в области обеспечения безопасности и федеральным органом исполнительной власти, уполномоченным в области противодействия иностранным техническим разведкам и технической защиты информации, в пределах их полномочий. При создании и эксплуатации таких информационных систем используемые в целях защиты информации методы и способы ее защиты должны соответствовать указанным требованиям При этом «cоздание и обеспечение функционирования систем защиты информации должно предусматривать»: 1) назначение оператором лиц, ответственных за организацию защиты информации, а также за планирование и разработку, внедрение, мониторинг, поддержание и совершенствование мер защиты информации; 2) издание оператором документов, определяющих политику обеспечения защиты информации, в том числе локальных актов по организации защиты информации, а также локальных актов, устанавливающих процедуры, направленные на обеспечение защиты информации в соответствии с настоящим Федеральным законом; 4) осуществление внутреннего контроля (аудита) соответствия защиты информации требованиям о защите информации..., политике оператора по обеспечению защиты информации, локальным актам оператора; 5) ознакомление работников оператора, непосредственно осуществляющих обработку и защиту информации, с требованиями о защите информации, документами, определяющими политику оператора по обеспечению защиты информации, локальными актами оператора и обучение указанных работников. Самое интересное традиционно находится в конце проекта закона: Операторы государственных информационных систем, а также иных информационных систем, в которых на основании договоров или иных законных основаниях содержится (обрабатывается) информация, обладателями которой являются государственные органы или государственные корпорации, информируют федеральный орган исполнительной власти в области обеспечения безопасности и федеральный орган исполнительной власти, уполномоченный в области противодействия иностранным техническим разведкам и технической защиты информации, о событиях безопасности, в результате которых нарушено или прекращено функционирование информационной системы и (или) нарушена безопасность обрабатываемой в информационной системе информации (компьютерных инцидентах). Предполагается, что все организации, работающие так или иначе с государственными органами и получающие при этом от них данные должны будут передавать данные о инцидентах безопасности. Логично предположить, что вслед за данным проектом закона последует регламент, согласно которому потребуется передавать данные в формате, удовлетворяющем условиям принятия данных в базу данных инцидентов, которая будет вестись ФСТЭК.

Метки:  

Отчет с Moscow Data Science Meetup 27 мая

Воскресенье, 26 Июня 2016 г. 11:04 + в цитатник
27 мая в офисе Mail.Ru Group прошёл очередной Moscow Data Science Meetup. На встрече собирались представители крупных российских компаний и научных организаций, а также энтузиасты в области машинного обучения, рекомендательных систем анализа социальных графов и смежных дисциплин. Гости делились друг с другом своим опытом решения практических задач анализа данных. Предлагаем вашему вниманию видеозаписи и презентации трёх докладов, представленных на встрече. Дмитрий Носов, Rambler&Co, H2O на Spark: как мы пили газировку и чуть не захлебнулись H2O — интересная и многообещающая платформа машинного обучения. Она может порадовать аналитика скоростью работы с большими объемами данных, набором алгоритмов, наличием API для нескольких языков программирования, и, конечно же, красивыми и подробными отчетами по построенным моделям. H2O написана на Java, поэтому работает вездеTM, в том числе на кластере Spark. В докладе спикер поделился своим опытом использования H2O на Spark и YARN, а также причинами отказа от использования H2O в production-окружении, несмотря на все ее положительные качества. Видеозапись выступления: it.mail.ru/video/724 Павел Филонов, «Лаборатория Касперского», Глубокое обучение и извлечение признаков в прогнозировании временных рядов Автоматическое выделение признаков, которые имеет место при построении глубоких сетей, видится перспективным инструментом, способным значительно сократить объём работ по подготовке данных. В докладе рассмотрена задача прогнозирования значений временного ряда и сравнены подходы к ее решениям как с использованием ручного выделения признаков, так и построенные на полностью автоматической обработке сырых данных. Видеозапись выступления: it.mail.ru/video/723 Александр Дьяконов, ВМК МГУ, Решение задачи Search Results Relevance (на платформе Kaggle) Разобрана задача по определению релевантности поисковой выдачи, которая решалась на прошлогоднем «Практическом семинаре по АД kaggle». Был описан очень простой алгоритм, который не использует сложных методов анализа текстов, словарей и ансамблей алгоритмов, и который, тем не менее, смог попасть в десятку сильнейших среди более чем 1300 участников. Видеозапись выступления: it.mail.ru/video/722
[Из песочницы] Пишем свой канал-бот для Telegram как у Хабра на Python

Метки:  

Почему я отказался от 500 000 долларов, послал к черту инвесторов и закрыл свой стартап

Воскресенье, 26 Июня 2016 г. 09:14 + в цитатник
Тим Ромеро основатель Vanguard K.K. в своем блоге на Медиум написал занимательный пост, который мы решили перевести. Я сделал то, чего ни один основатель стартапа, казалось бы, никогда не сделает. Я сдался. Это даже не было одним из тех славных случаев, когда люди учатся на своих ошибках и идут вперед. За спиной было семь месяцев тяжелой работы, мы проверили идею, подготовили абсолютно все и через две недели деньги должны были быть у нас на руках. У нас была хорошая команда, блестящие отзывы бета-пользователей и предварительный договор с инвесторами на 250 000 долларов. Но я свернул дело. Моя команда и большинство инвесторов в ярости, но я уверен, что поступил правильно. По крайней мере, думаю, что уверен. В этом деле была одна неустранимая, с моей точки зрения, проблема. Мои инвесторы и члены команды хотели, чтобы мы взяли средства и придумали решение, прежде чем деньги закончатся. До этого я основывал четыре компании, неоднократно разорялся и уходил, так что я понимаю, что без этого никуда, но на сей раз я не мог снова на это пойти. Эта статья писалась отчасти как объяснение для заинтересованных лиц, отчасти для самоуспокоения и отчасти для других основателей и инвесторов, чтобы узнать, как бы они поступили в такой ситуации. Я начал работать над ContractBeast в октябре прошлого года. Мы предлагали управление жизненным циклом контрактов на основе SaaS. Если вы не работали в крупных ИТ-компаниях, вы, возможно, не слышали об управлении жизненным циклом контрактов, или CLM (Contract Lifecycle Management). Вкратце, CLM занимается вопросами создания, согласования, исполнения и хранения контрактов, как на бумаге, так и в электронной форме, со строгим контролем доступа. Сюда также входят такие услуги как уведомление заказчика об истечении срока контрактов или их автоматическом обновлении и предоставление списка ответственных лиц. CLM – очень фрагментированный сектор рынка с объемом средств 7.6 миллиардов долларов, на котором 80 авторитетных компаний борются за свою долю – если не считать десятки появившихся за последние годы стартапов, занимающихся электронными подписями. Почти все эти компании работают в сфере предпринимательства, где преобладают длинные циклы купли-продажи по стратегии “снизу вверх” и есть возможность получать доход с консультирования и адаптации. Начнем с того, что только рынок крупного бизнеса тяготеет к фрагментации. Рынок среднего и малого бизнеса очень мало обслуживается, а на корпоративном рынке цены неоправданно высокие. ContractBeast – SaaS-продукт с невысокой стоимостью без необходимости консультирования. Мы планировали начать с рынка среднего бизнеса, а затем уйти в корпоративный. Как создавался Beast Целевая аудитория позитивно отозвалась о наших тестовых моделях и мы получили ценный опыт от этих интервью, и многие с энтузиазмом спрашивали, когда появится готовая версия. Я был на верном пути. Следующие несколько месяцев по вечерам и на выходных я разрабатывал минимальный жизнеспособный продукт и получал отзывы о компонентах по мере их появления. Я ушел с работы в январе и теперь мог уделять ContractBeast более 70 часов в неделю. Другие члены команды остались на своих рабочих местах. Да и к лучшему. Это упростило принятие моего последнего решения. Мы выпустили бета-версию в начале марта, и вроде бы всё было отлично. Около 35% зарегистрировавшихся в системе продолжили ее использовать как минимум три раза в неделю. UI нуждался в доработке, но наши пользователи с энтузиазмом обсуждали, как ContractBeast сэкономит их время и нервы. Команда ликовала. Потенциальные инвесторы ждали с нетерпением. Но что-то было не так. Сначала все шло как обычно, но что-то не давало мне покоя. Несмотря на все похвалы, наши пользователи использовали ContractBeast для создания лишь малой части своих контрактов. Следующие две недели я приходил к нашим пользователям, смотрел, как они работают, спрашивал, как они собираются работать с продуктом. Пытаясь узнать, почему они не используют ContractBeast для создания всех контрактов, я получил множество запросов опций. Говорить с пользователями об опциях непросто. Нередко они подают полезные и ценные идеи. Иногда пользователь дает такое понимание ситуации, которое меняет наш взгляд на продукт. Но по большей части, им на самом деле не нужны те опции, о которых они просят. Когда пользователь недоволен и сам не может объяснить, почему, он часто говорит о целом ряде сторонних, незначительных опций, которые ему нужны. Мы получили много обращений с просьбой высылать уведомления в мессенджеры, использовать искусственный интеллект для анализа контрактов, расширить возможности поиска. Я не говорю, что это плохие идеи, но они не объясняют, почему люди не использовали ContractBeast активнее. Я мог бы написать отдельную статью о том, как отличить эти излишние запросы от дельных. Ваши клиенты хотят, как лучше, но создание всех этих функций не поможет удовлетворить их в ближайшем будущем. И я продолжал в больших количествах получать такие сторонние запросы. Я не мог спать. Мои пользователи говорили, что им нравится продукт, и они собираются работать с ним в долгосрочной перспективе. Но на деле они не очень-то его использовали, и я не могу понять, почему. Потягивая кофе без кофеина прохладным майским утром в 5:00, я перечитывал сорок страниц записей, отзывов пользователей и критики. И наконец, меня осенило. ContractBeast позволял достичь высокой точности и эффективности, но только после месяцев использования. Он не давал значительных улучшений сразу. Я боролся с человеческой природой – и я проигрывал. Все клянутся, что начнут правильно питаться и делать зарядку, но единицы это делают. Все согласны, что им нужно с наименьшими затратами обеспечить свою фининсовую безопасность в будущем, но единицы это сделают. Наши пользователи говорили, что будут использовать ContractBeast, чтобы достичь этого долгосрочного результата, но единицы это делали. Я посмотрел на контракты, которые создавали люди, и обнаружил, что в большинстве случаев это были контракты, в которых какая-то опция давала ощутимый мгновенный результат. Как правило, проверка и скрепление договора. Проклятая природа человека… Попытки спасти Beast У этой проблемы было два решения: либо изменить стратегию выхода на рынок, либо изменить продукт. Период с индивидуального внедрения и самообслуживания на стратегию “сверху вниз” и метод консультативных продаж были очевидным решением проблемы. Отдельные пользователи вряд ли пойдут на краткосрочные изменения для достижения долгосрочных результатов, а вот ИТ-директор без проблем поможет им сделать это. Это его работа. К сожалению, продажи снизу вверх гораздо затратнее контент-маркетинга и SEO. Расчеты показали, что нам придется поднять цены до уровня, который вытолкнет нас из рынка среднего бизнеса в зону конкуренции с более авторитетными и хорошо финансируемыми компаниями. Поскольку у нас не было преимущества в этом рыночном сегменте, идея была обречена на провал. Остался лишь один вариант: найти способ удовлетворить покупателей в краткосрочной перспективе. Мы начали искать, что может дать мгновенные результаты. В среднем и малом бизнесе контрактный менеджмент никогда не был проблемой, требующей срочного решения. Практически единственным способом превратить потенциальных пользователей в реальных покупателей было заставить их активно использовать пробную версию ContractBeast. Мы просмотрели все запросы новых функций от наших пользователей. Некоторые из них были отличными предложениями, но ни один не касался главного вопроса: что даст заметный, устойчивый и мгновенный результат? Внедрение этих функций было бы бессмысленным. Неделями мы проводили мозговой штурм, выдвигались десятки предложений, и всё было не то. Ни одного верного способа мгновенно дать нашим пользователям то, чего они подсознательно так жаждали. Инвесторы уже были готовы выделить средства, члены команды были готовы уйти со старой работы, но я не видел никаких перспектив и поэтому решил остановить проект. Как я похоронил Beast Члены команды и некоторые инвесторы настаивали на том, чтобы взять средства и постараться разработать решение проблемы до того, как эти средства закончатся. Таким и должен быть ход игры, и я понимаю, почему все, кто участвовал в проекте, недовольны тем, что я просто поджал хвост и убежал. Может быть, мы бы и нашли решение до истощения фондов, но недели мозгового штурма не дали никаких результатов. Одно дело, если бы нам приходилось выбирать из нескольких вариантов или если бы мы работали над устранением отдельных недостатков, но у нас не было ничего. Я не из тех, кто боится рисковать, но я просчитываю соотношение риска и дохода. Как инвестор, я бы, возможно, посоветовал себе взять деньги и попытаться. Но расчет риска и дохода для инвесторов и основателей отличается. Я просчитывал, стоила ли эта авантюра еще одного года работы по 70+ часов в неделю. Мне нужен больший уровень уверенности, чем инвесторам, потому что время для меня дороже, чем деньги для них.Инвесторы ставят на кон деньги, вкладываясь в компании, а у меня только одна жизнь. Прощание с Beast Через несколько недель, когда прошел первый шок, другие участники проекта, хоть они и были еще немного разочарованы, согласились, что закрыть проект было верным решением. Я тоже перестал сомневаться в правильности такого решения, пока писал эту статью. Не знаю, были ли вы в такой ситуации, но если были, мне было бы интересно узнать, как вы с ней справились. Всем понятно, что лучше вовремя остановиться и избежать лишних убытков, но принять такое решение невероятно сложно. И все же иногда лучше отказаться от риска.
Эффекты в OpenGL

Метки:  

[Из песочницы] Скелетная анимация в играх. Обзор техник и ресурсов

Суббота, 25 Июня 2016 г. 17:52 + в цитатник
Anima — это душа, отличающая живое от мертвого. Аристотелевская душа — это принцип движения, проявляющегося в четырёх видах: перемещение, превращение, убывание и возрастание. Спустя почти две с половиной тысячи лет мы используем те же категории в компьютерной графике. Скелетная анимация определяет перемещение, морфинг служит для превращений, а убывание и возрастание это обычное масштабирование. Анимированная графика оживляет образ, вдыхает в картинку душу, и это, на мой взгляд, даже важнее, чем достоверная игра света и тени. Создание качественных скелетных 3D анимаций сегодня, пожалуй, самая труднодоступная для инди разработчиков задача. Вероятно поэтому так мало инди игр в 3D, и так много проектов в стилях пиксель арта или примитивизма, а также бродилок без персонажей в кадре. Но теперь это соотношение может измениться… Попробуйте сосчитать количество разнообразных анимаций в Uncharted 4. По моим оценкам там около часа уникальных движений, не считая лицевой анимации (850 выражений по словам авторов). Подобные игры задают фантастическую планку качества. Примеры анимации Uncharted 4 (>40мб GIF) Если физический рендеринг и создание качественно освещенных статичных сцен становятся доступны энтузиастам благодаря мощным бесплатным игровым движкам и инструментам 3D моделирования, то создание хорошей анимации требует оборудования для захвата движений и длительной кропотливой работы по их внедрению. Одна из самых доступных систем это костюм neuronmocap стоимостью порядка $1.5к без учета доставки. Мне не удалось отыскать примеров создания хотя-бы близкой по уровню анимации при помощи ручного кадрового подхода или какой-либо процедурной анимации. Максимум что возможно сделать вручную, на мой взгляд, — это простые удары, быстрые движения и стилизованная мультяшная анимация. Но как сделать реалистичную ходьбу по лестнице, где очень много деталей, связанных с переносном центра тяжести и балансом тела? Невозможно их все воспроизвести вручную. Может быть я ошибаюсь, и кто-нибудь покажет работы специалистов такого уровня?.. Все это я вспоминаю для того, чтобы оценить по достоинству щедрый подарок от Mixamo. Он буквально открывает дверь на новый уровень для независимых разработчиков: компания Adobe купила Mixamo, и теперь 2.5 тысячи скелетных анимаций для персонажей они отдают совершенно бесплатно "for unlimited commercial or non commercial use": www.mixamo.com Еще пол года назад можно было их получить только выложив порядка $36 000 (ну или спиратив в сети). Помимо анимаций компания также предлагает бесплатную версию инструмента для ригинга и скининга персонажей, инструмент для создания множественных уровней детализации с минимальными потерями качества (LOD), генератор персонажей и плагин для захвата лицевой анимации. Существуют и не менее проработанные наборы анимаций, доступные для приобретения энтузиастами. Но такой гигантский и качественный набор впервые оказался доступен совершенно бесплатно. Еще одним неплохим источником клипов остается база анимаций Университета Карнеги — Меллон и ее адаптированная под Unity версия, однако качество и содержание этой базы не так хороши. Кроме ручной кадровой анимации и захвата движения актера, существуют и интересные процедурные методы симуляции движений: эволюционное моделирование, нейронные сети, task based locomotion. Что интересно, на конференции SIGGRAPH 2016 этим непростым техникам уделяют много внимания. Но широким кругам независимых разработчиков эти вещи пока не доступны, и мне самому хотелось бы больше узнать о возможности их реального применения. Однако сегодня есть и доступные инструменты, симулирующие мускульную динамику (Euphoria Engine и Puppet Master для Unity3d), которые позволяют привнести разнообразные реакции персонажей на обстоятельства. Получить качественные и разнообразные анимационные клипы это только первая часть задачи. Вторая часть заключается в том, чтобы корректно использовать полученные анимации при управлении персонажем. Для этого сначала нужно решить, как вообще сдвигать персонажа в сцене: на основании данных самой анимации (1), либо на основании каких-то иных соображений (например физики твердого тела) (2). То есть, либо анимация будет вычисляться исходя из произвольного (физического) движения объекта в пространстве (2), либо само смещение в пространстве будет исходить из записанной анимации, игнорируя иные вмешательства (1). У обоих подходов есть достоинства и недостатки. В прежние времена, до массового использования захвата движений, вопрос об этом почти не стоял — персонажи двигались процедурно, на основании каких-то простых принципов, а анимационные клипы просто проигрывались для некоторого соответствия этому движению. Но чем лучше становилась анимация и графика в целом, тем заметнее становилось несоответствие движения ног и смещения персонажа, а также неестветсвенность динамики движения. Одним из ярких примеров может быть игра Guild Wars 2 где анимация движений и графика уже достаточно хороши, но вот большой диапазон возможных скоростей и направлений движения персонажа не обеспечен столь же большим набором анимаций, и персонажи либо буксуют на месте, либо проскальзывают вперед как по льду. Та же проблема долгое время преследует и игры на движке Gamebryo (серия TES: Morrowind, Skyrim), да и многие другие. Настоящее движение человека нелинейно — сначала мы наклоняемся вперед, затем выбрасываем ногу, и только потом начинаем движение, быстро ускоряясь после соприкосновения стопы с землей, и двигаемся по инерции до следующего шага. Подобрать функцию, точно описывающую подобное движение, сложно, и редко кто вообще об этом задумывается. Что уж говорить о более сложных движениях — стрейфе, переходах между направлениями, торможением и поворотами. Поэтому для достижения реализма нам в любом случае потребуется гигантский набор разнообразных клипов с движениями в различных направлениях, с различной скоростью, и т.п… Кроме того, анимационные клипы редко можно использовать изолированно, воспроизводя один за другим. Чаще всего в игре присутствует множество анимаций, между которыми не заготовлено специальных анимированных переходов. Поэтому для их симуляции применяется плавное смешивание через линейную интерполяцию поворотов костей. Для удобной настройки таких переходов используется т.н. конечный автомат или машина состояний (State machine). В UE и Unity для этого есть специальные инструменты: Persona и Mecanim. Каждый узел там это некоторое состояние скелетной модели (заготовленный анимационный клип или результат их смешения — Blend Tree). Когда выполнены некоторые заданные условия, осуществляется плавный переход из одного состояния в другое, во время которого оба оказывают пропорциональное времени влияние на повороты костей и смещение объекта. Таким образом достигается иллюзия непрерывности движения. Состояние может быть не одиночным клипом, а смешанным по тому же принципу набором клипов (Blend Tree / Blend Space). Например из клипов движений персонажа в стороны можно выбрать несколько, смешав их пропорционально вектору желаемого движения, и получить движение под любым произвольным углом. Однако существуют такие анимации, для которых смешивание оборачивается некорректными позами. Например когда одна анимация двигает ноги персонажа вперед, а другая вбок, линейное смешивание может привести к пересечению ног друг с другом. Чтобы этого избежать нужно тщательно подбирать анимационные клипы, синхронизировать их фазу, длину и скорость, либо добавлять отдельный клип специально для данного вида движений. Все это сложная и кропотливая работа. И чем больше возможных состояний и переходов между ними, тем сложнее привести их в согласие друг с другом, и проследить за тем, чтобы все нужные переходы срабатывали когда это требуется. 1) Самым очевидным решением является захват движений реального актера при помощи Motion Capture и привязка смещения персонажа в игре к смещению «корневой кости» в самой анимации — принцип Root Motion. Тогда персонаж будет двигаться ровно так, как двигался актер во время записи. Выглядит очень реалистично. Более того, это единственный способ достоверно воспроизвести сложные маневры вроде выпадов, уворотов и паррирования атак холодным оружием. Но этот подход несет в себе и очевидные проблемы. Допустим, персонаж хочет подвинуться к краю обрыва: актер на записи наклоняется, поднимает ногу и делает смелый широкий шаг по сцене. А персонаж шагает прямо в пропасть… Чтобы этого избежать, нужно прервать шаг где-то посередине, но это не только выглядит неестественно, но и затрудняет игроку выбор нужного момента из-за нелинейности движения, в котором может быть долгая подготовка (наклон), а затем резкое уверенное движение (шаг). Можно записать несколько вариантов движений. Допустим: осторожные маленькие шаги, нормальные, и бег. А затем смешать их по параметру требуемой скорости, который можно увеличивать линейно и предсказуемо. Но что если нам нужны движения в стороны? Значит для каждого варианта ширины шага нам нужны еще три-четыре варианта (за вычетом зеркальных). А еще персонаж должен уметь поворачивать во время движения. Значит для каждого варианта нам нужны движения с поворотом. А если поворот может быть быстрым и медленным? Значит еще раз умножаем число необходимых клипов на два. А теперь нам нужно движение по наклонной поверхности! А потом нам захочется, чтобы персонаж умел делать тоже самое вприсяди. Итого — просто сотни и тысячи вариантов анимации которые нужно смешивать и следить за тем, чтобы это происходило корректно и приводило к движениям с нужной скоростью. И все равно, во многих случаях управление будет ощущаться как «ватное», поскольку инерция актера и наша невозможность предусмотреть все возможные человеческие маневры будет лишать игрока контроля над персонажем. Эту проблему, к слову, прочувствовали на себе игроки в The Witcher 3, поэтому в одном из крупных обновлений разработчики внедрили альтернативный вариант управления, где анимация быстрее отзывается на управление в ущерб реализму. В шутерах же проблема нелинейности движения обретает особенно выраженный характер: игроку часто приходится выглядывать из-за угла и быстро уходить обратно, и момент резкой смены направления может очень отличаться — игроку требуется как можно скорее вернуться обратно за укрытие, а у нас нет возможности предсказать заранее, какой ширины шаг он планировал и проиграть соответствующую анимацию. Игроку, в свою очередь, будет трудно привыкнуть к ширине шага, которую делает его персонаж, и к скорости этого шага, чтобы прервать его вовремя. Во-вторых, Root Motion плохо годится для сетевых игр. Нелинейность движения не только затрудняет игроку предсказание скорости, но и лишает нас возможности интерполировать и экстраполировать движение чтобы компенсировать сетевую задержку, что является очень важным и сложным аспектом в быстрых сетевых играх. Если смещение персонажа задается только анимацией, то трудно аналитически подобрать нужные параметры машины состояний (смешивающей разные анимации), которые приведут к движению персонажа в точно нужном нам направлении и с точно нужной нам скоростью (выбранных для компенсации расхождения). Если же сделать наоборот, так, что анимация будет ориентироваться на фактическое движение, то при коррекции расхождения между сервером и клиентом легко можно будет подобрать наиболее подходящую анимацию, и даже если она будет чуточку несоответствовать фактическому смещению, этого почти никто не заметит. Поэтому техника Root Motion используется часто в одиночных играх от третьего лица, где управление осуществляется контекстуально — в зависимости от наличия укрытия, препятствия, режима движения или других обстоятельств, и редко применяется в сетевом режиме и MMOG. Из последних заметных проектов, использующих Root Motion, можно выделить The Witcher 3. Трудно переоценить усилия, вложенные в производство всех его движений. Пример анимации The Witcher 3 и ее съемки 2) Другое решение обратно принципу Root Motion — нужно приводить анимацию в наиболее точное соответствие с произошедшим или планируемым движением. Тогда многие описанные выше проблемы решаются — движение персонажа можно сделать равноускоренным и предсказуемым с возможностью сколь угодно быстрой смены направления. Но как привести нелинейную и инерционную анимацию в соответствие с таким движением? Интересный комплексный подход описали разработчики игры Paragon. Суть его заключается в том, чтобы находить и проигрывать только нужную серию кадров анимации для достижения требуемого смещения/поворота, пропуская лишние. И использовать инверсную кинематику для модификации ширины шага. Первая очевидная трудность при приведении анимации в соответствие с движением, в том, что движение уже произошло, а анимация еще не проиграна. Поэтому очень пригодится система предсказания движения, вычисляющая положение персонажа для следующего кадра. Затем, зная смещение, которое должен осуществить персонаж за следующий кадр, нужно пропустить столько кадров анимационного клипа движения, сколько будет нужно чтобы достичь требуемого смещения, и проиграть тот кадр, на котором требуемое смещение достигнуто. В таком случае анимация станет воспроизводиться с измененной скоростью, так, чтобы точно соответствовать фактическому смещению, и эта скорость может быть быстрее или медленнее оригинальной, поскольку невозможно заставить реального актера поддерживать постоянное ускорение или скорость. Данный подход позволит сгладить анимацию и привести в соответствие с любой сложной процедурной моделью движения, меняющейся во время игры (персонаж может выпить какое-нибудь ускоряющее зелье или оказаться замедлен противником). Недостатком, разумеется, является то, что анимация может стать менее реалистичной из-за сильных изменений в скорости. Однако на практике это дает очень хорошее окно доступных вариаций в котором нарушения скорости незаметны. А вкупе с поправками ширины шага при помощи инверсной кинематики, покрывает еще больший диапазон. Но, к сожалению, этот метод довольно сильно нарушает привычный подход к анимированию, и поэтому я не смог найти простого способа реализовать его, например, с использованием стандартного анимационного компонента Unity. В Unreal Engine также пока нет необходимого функционала, однако разработчики обещают когда-нибудь перенести низкоуровневые наработки, сделанные для Paragon, в общедоступную версию движка. Основной сложностью является поиск и воспроизведение нужного кадра на основании данных о фактическом смещении и повороте. Для этого авторы предлагают делать пре-процессинг анимационных клипов и генерировать для каждого из них дополнительный блок данных: Distance Curve, в котором будут покадрово сохранены значения смещения и поворота корневой кости относительно начала или конца анимации. Затем, в ходе выборки, можно производить быстрый бинарный поиск нужного кадра, где достигнуты соответствующие параметры смещения и поворота, и воспроизводить его. Пока же можно ограничиться прежним подходом, и делать менее точную подгонку скорости анимации к скорости планируемого движения, ориентируясь только на скорость персонажа за последний кадр. Самое главное — неплохой набор душ для экспериментов теперь имеется!
«Разрубить Гордиев узел» или преодоление проблем шифрования информации в ОС Windows

Метки:  

Dell Storage SC9000: интеллектуальная система хранения для эффективного дата-центра

Суббота, 25 Июня 2016 г. 14:43 + в цитатник
Рост требований к производительности СХД заставляет вендоров искать новые подходы к созданию оптимальной архитектуры систем хранения данных и наряду с традиционными дисками использовать флэш-память. Разработка серверов и систем хранения данных является одним из приоритетов Dell, куда компания инвестирует значительные средства. В настоящее время она предлагает новые системы резервного копирования и хранения данных для разных видов бизнеса. Рассмотрим подробнее систему хранения Dell SC9000. Аппаратная платформа Новый дисковый массив Dell SC9000 выпущен в октябре 2015 года и определенно заслуживает того, чтобы взглянуть на него внимательнее. Это флагманское решение уже можно увидеть в крупных дата-центрах мира. Но к системе стоит присмотреться и средним компаниям. Хранилище SC9000 с многопетабайтной емкостью и операционной системой Storage Center 7.0 предлагает новые возможности для ИТ-подразделений. Аппаратная платформа SC9000, старшая в линейке массивов серии SC, отличается самой высокой производительностью и масштабируемостью — до 960 накопителей SAS SSD и / или HDD на массив, причем массивы можно объединять в группы (федерация). Уже доказавшая свою надежность платформа оснащена новыми 8-ядерными процессорами Intel, вчетверо увеличена емкость системной памяти, а в качестве бэкенда используется интерфейс SAS 12 Гбит/с. Система поддерживает протоколы SAN (FC, iSCSI, FCoE), а также NAS через опциональное устройство FS8600. Производительность системы по сравнению с предыдущими продуктами SC выросла на 40 %. Внутренние тесты показали, что быстродействие массива SC9000 превышает 360 тыс. IOPS при задержке менее миллисекунды. Кроме того, вдвое выросла пропускная способность, а это означает отсутствие узких мест при росте нагрузки. В основе Dell SC9000 – новая серверная платформа Dell PowerEdge 13-го поколения с четырьмя 8-ядерными процессорами Intel Xeon с тактовой частотой 3,2 ГГц и оперативной памятью емкостью до 512 Гбайт. Систему можно конфигурировать как флэш-массив или гибридную СХД. Благодаря применению компонентов с возможностью резервирования и горячего подключения SC9000 является отказоустойчивым и простым в развертывании решением с высокой доступностью. Полки расширения SC400/420, SC200/220 или SC280 позволяют наращивать емкость. Система поддерживает унифицированное управление с массивами SC8000, SC4020, SCv2000. Емкость флэш-массива составляет до 46 Тбайт на 1U (без сжатия данных). Такой плотности удалось добиться благодаря применению в СХД трехуровневой памяти Samsung TLC 3D NAND. Система SC9000 предоставляет более 3 Пбайт чистой емкости, причем массивы можно объединять в группы, если рабочим нагрузкам требуются большие объемы хранения. Полки расширения SC280 (а это 96 HDD 3,5”) дают емкость более 100 Тбайт на 1U. Это можно использовать для медиаархивов или в приложениях, работающих с крупными файлами. Программные средства Несмотря на впечатляющие характеристики аппаратной платформы, многими своими качествами SC9000 обязана софту. Виртуализированная программная среда Storage Center с функциями автоматизации делает систему более экономичной и адекватной широкому спектру задач. Сравнение программных средств массивов серии SC. Программное обеспечение Dell Storage Center 7.0, оснащенное новыми функциями, обеспечивает улучшенную поддержку устройств Dell Storage серии SC в частных облачных средах и других критически важных приложениях. Посмотрим, что тут нового. Улучшенная оптимизация для работы с флэш-памятью Принимая во внимание, что высокая стоимость флэш-памяти является основным барьером для принятия этой технологии, Dell сфокусировалась на повышении эффективности использования накопителей, чтобы снизить их стоимость. Об оптимизации заявляют многие вендоры, но часто используется упрощенный подход с одним уровнем хранения, при котором все виды флэш-памяти ведут себя одинаково. Современные технологии виртуализации Dell позволяют использовать различные типы флэш-памяти в одном и том же массиве для запуска различных рабочих нагрузок и различных сценариев применения. Благодаря этому компания смогла выпустить серию высокоскоростных и экономичных массивов как полностью на базе флэш-памяти, так и в гибридном исполнении. В автоматическом тиринге Dell учитываются разные параметры цены/производительности SSD разного типа. То есть для достижения высокой производительности в IOPS не потребуется выложить запредельную сумму. Вот почему у флэш-массивов Dell стоимость хранения составляет всего 0,65 центов за гигабайт. Ну а в гибридных СХД этот показатель еще ниже. Глубокий тиринг, не ограниченный флэш-памятью Чтобы увеличить срок службы памяти 3D NAND, задействован механизм тиринга – перемещения данных между уровнями хранения. Первый уровень (Tier 1) представлен флэш-памятью SLC или eMLC, выдерживающей большое количество циклов перезаписи, второй (Tier 2) – памятью 3D NAND, в которую записываются относительно редко используемые данные, причем в сжатом виде. В некоторых моделях есть и третий уровень (Tier 3) – HDD. Конфигурацию системы (соотношение емкости разных видов флэш-памяти и жестких дисков) можно подбирать с учетом характера нагрузки: для этого есть соответствующая утилита. WI – для интенсивной записи, RI –- для интенсивного чтения Применяемые Dell методы тиринга – одни из самых полных в отрасли. Массивы SC позволяют создавать унифицированные пулы хранения данных SAN и/или NAS из разнородных систем, формировать тома из носителей разного типа (в том числе включать в них Tier 0 – кэш на стороне сервера), задавать гибкие конфигурации RAID. За счет автоматического размещения данных на соответствующем уровне хранения в реальном времени ускоряется «прогрев» данных и их «остывание». Но главное – упрощается управление, и удается выжать все возможное из накопителей с точки зрения производительности. Интеллектуальное размещение данных и оптимизация хранения на всех уровнях. Запатентованная технология автоматического многоуровневого размещения данных использует основные преимущества различных типов накопителей для оптимизации данных на протяжении всего жизненного цикла. Быстрое внедрение новых технологий Та же виртуализация, которая помогает массивам серии SC демонстрировать свои преимущества в соотношении цена/производительность, позволяет внедрять новые решения. Хороший пример – TLC 3D NAND. Выпустив прошлым летом накопители Mainstream Read-Intensive, Dell вдвое снизила стоимость флэш-памяти Tier 2 без уменьшения долговечности или быстродействия. Память TLC успешно применяется в ее массивах старшего класса, в то время как конкуренты все еще пытаются изменить архитектуру одноуровневых систем младшего класса. Быстрое вертикальное и горизонтальное масштабирование для удовлетворения потребностей в хранении данных и производительности. Одновременная вертикальная и горизонтальная масштабируемость делает массивы SC хорошо расширяемыми. Гибкая самооптимизирующаяся система SC9000 позволяет получить более 3 Пбайт чистой емкости и объединять массивы в группы, обеспечивая необходимой емкостью крупные рабочие нагрузки. Массив SC9000 обеспечивает быстрое модульное расширение благодаря поддержке сетей хранения данных (SAN) и сетевых систем хранения данных (NAS). Его также можно подключать к другим массивам серии SC в более крупных федеративных системах с единым управлением. Программное обеспечение SCOS включает в себя опциональный «гипервизор хранения», позволяющий легко перемещать данные по «федерации» массивов. И даже в случае наращивания одного дискового массива можно получить емкость и производительность крупной распределенной системы с унифицированным управлением. Dell Volume Advisor даст рекомендации по проактивному балансированию нагрузки на основе заданных правил. Он осуществляет мониторинг федерации массивов и советует, где лучше разместить данные. Эффективное использование емкости Массивы серии SC с программным обеспечением SCOS 7.0 поддерживают интеллектуальное сжатие данных на флэш-накопителях и HDD. Тем самым достигается значительная экономия емкости. Функция сжатия интегрирована с тирингом, поэтому сжатие не снижает производительности. При этом активны такие функции, как динамическое распределение емкости. Сжатие данных обеспечивает серьезную экономию емкости хранения, что особенно важно для флэш-памяти. За счет сжатия данных, достигающего 93 % в случае с базами данных Microsoft SQL, решение становится еще более экономичным: флэш-массив оказывается сопоставим по цене с дисковым массивом на базе HDD SAS 15k. Сжатие происходит, когда блоки данных перемещаются на нижние уровни, тем самым уменьшается влияние сжатия данных на производительность системы. При перемещении активных блоков на верхние уровни они остаются сжатыми. Постоянная доступность Новая функция SCOS 7.0 под названием Live Volume Auto-Failover предотвращает незапланированные простои. При отказе ПО Storage Center перенаправляет нагрузку на синхронизированные с основным резервные тома на другом массиве и запускает процедуру восстановления. Вмешательства администратора не требуется. Благодаря переназначению хостов можно вносить изменения в СХД, не влияя на работу пользователей и приложений. Прозрачное для сервера перемещение томов между массивами в федеративном кластере повышает эффективность использования кэша и емкости при растущих нагрузках. Еще одна примечательная технология SC9000 – функция автоматической замены сбойного массива Live Volume, позволяющая работать без простоев. Она дает возможность «растягивать» тома между площадками при помощи средств самого дискового массива. В результате создается недорогое катастрофоустойчивое решение, не требующее перестройки архитектуры хранения данных. Функция Live Volume с автоматическим переключением при отказе обеспечивает непрерывную работу системы при перебоях электропитания и автоматически восстанавливает среду высокой доступности при включении массива. Установка дополнительного оборудования или программного обеспечения не требуется. Функция Live Volume на массивах серии SC хорошо подходит для облачных сред. Она обеспечивает восстановление после сбоев и прозрачное автоматическое переключение на полностью синхронизируемые тома на другом массиве серии SC. Интеграция корпоративных приложений На уровне приложений поддерживаются снепшоты в среде Oracle, облачных средах на платформе Microsoft Azure, VMware Metro Stretch Clusters. Функция Azure Site Recovery обеспечивает резервное копирование данных в облачную инфраструктуру Microsoft. Предусмотрена также интегрированная защита сред Oracle, Microsoft и VMware. Набор программ Application Protection Manager обеспечивает целостность данных на сервере в средах баз данных Oracle, VMware и MS. Опциональные твердотельные накопители и жесткие диски с самошифрованием, сертифицированные по стандарту FIPS, защищают данные от кражи, утери или несанкционированного доступа. А встроенные расширенные возможности включают всесторонние «тонкие» методы управления ресурсами системы. В заключение сравним массив с конкурентами: Массив SC9000 — это подходящее решение для крупных систем хранения данных, серьезных нагрузок и распределенных корпоративных сред. Массив SC9000 не просто увеличивает производительность: его интеллектуальная виртуализированная архитектура автоматически оптимизирует финансовые расходы и использование емкости хранения, обеспечивая максимальную экономию. Массивы хранения Dell SC9000 призваны помочь компаниям с крупными центрами хранения и обработки данных увереннее и быстрее достигать важных целей, расходуя меньше средств и времени. Dell предоставляет заказчикам гибкие комплексные решения, способные быстро адаптироваться под меняющиеся потребности, предлагает решение с рекордно низкой стоимостью хранения гигабайта данных на базе твердотельных накопителей благодаря новому типу памяти TLC 3D.
Кибербезопасность на бескрайних морях

Метки:  

«Разрубить Гордиев узел» или преодоление проблем шифрования информации в ОС Windows

Пятница, 24 Июня 2016 г. 19:58 + в цитатник
Современная операционная система это сложный иерархичный процесс обработки и управления информацией. Актуальные версии ОС Windows в этом вопросе не являются исключением. Для того, чтобы интегрировать средство защиты в среду ОС Windows, зачастую хватает встраивания на прикладном уровне. Однако, если речь заходит о шифровании информации в среде ОС Windows, все становится намного сложнее. Основной «головной болью» разработчика средств шифрования в этом процессе является обеспечение «прозрачности шифрования», т.е. необходимо гармонично встроиться в структуру процессов операционной системы и при этом обеспечить невовлечение пользователей в процесс шифрования и уж тем более его обслуживание. Требования к современным средствам защиты все больше и больше исключают пользователя из процесса защиты информации. Таким образом, для этого самого пользователя создаются комфортные условия, не требующие принятия «непонятных» решений по защите информации. В данной статье будут раскрыты идеи эффективной интеграции средства шифрования информации на диске с процессами файловой системы ОС Windows. Перед разработчиками ставилась цель создать механизм шифрования информации на диске, отвечающий требованиям максимальной прозрачности для пользователей. Требования должны будут выполняться за счет эффективного взаимодействия этого механизма шифрования с процессами операционной системы Windows, которые отвечают за управление файловой системой. Эффективность механизма шифрования должна также подтверждаться высокой производительностью процессов шифрования и рациональным использованием ресурсов операционной системы. Изначально была поставлена задача предоставлять одновременный доступ к зашифрованному и расшифрованному содержимому, а также шифровать имена файлов. Это и порождает основные сложности, т.к. такое требование идет в разрез со сложившейся архитектурой Windows. Чтобы понять суть проблемы, для начала нам следует разобрать некоторые основные моменты данной операционной системы. В Windows все файловые системы полагаются на такие подсистемы, как менеджер памяти и кэш менеджер, а менеджер памяти, в свою очередь, полагается на файловые системы. Казалось бы, замкнутый круг, но все станет ясно дальше. Ниже, на рисунке 1, изображены перечисленные компоненты, а также менеджер ввода/вывода, который принимает запросы от подсистем (например Win32) и от других драйверов системы. Также на рисунке используются термины «фильтр» и «стек файловой системы», о чем подробнее будет рассказано ниже. Рисунок 1 Разберем такой механизм, как отображение файла на память. Суть его заключается в том, что при доступе к виртуальной памяти в реальности читается часть файла. Реализуется это при помощи аппаратных механизмов процессоров и непосредственно самого менеджера памяти. Любые диапазоны виртуальной памяти процесса описываются дескрипторами. Если для какого-то диапазона нет дескриптора, значит, на этом участке виртуальной памяти ничего нет, и доступ к такому диапазону неизбежно ведет к краху процесса. В случае, если для какого-либо диапазона закреплена физическая память, доступ к этим виртуальным адресам ведет к обычному доступу к физической памяти, такую память еще называют анонимной. В случае, если файл отображен на виртуальную память, то при доступе по этим адресам считывается часть файла с диска в физическую память, после чего доступ к ней будет выполняться обычным образом. Т.е. эти два случая очень похожи, разница лишь в том, что для последнего в соответствующую физическую память предварительно будет считана часть файла. Обо всех таких типах доступов дескриптор и содержит информацию. Эти дескрипторы являются структурами менеджера памяти, которыми он управляет для того, чтобы выполнять требуемые задачи. Как не трудно догадаться, для того, чтобы считать часть файла в страницу физической памяти, менеджер памяти должен послать запрос файловой системе. На рисунке 2 изображен пример виртуальной памяти процесса с двумя диапазонами, А и В, доступ к которым еще ни разу не выполнялся. Рисунок 2 На диапазон А отображен исполняемый файл самого процесса, а на диапазон В отображена физическая память. Теперь, когда процесс выполнит первый доступ к диапазону А, управление получит менеджер памяти и первое, что он сделает — оценит тип диапазона. Поскольку на диапазон А отображен файл, менеджер памяти сначала считает из файла соответствующую его часть в физическую память, после чего отобразит ее на диапазон А процесса, таким образом дальнейший доступ к считанному содержимому будет выполняться уже без менеджера памяти. Для диапазона В менеджер памяти выполнит такую же последовательность, единственная разница в том, что вместо считываний данных из файла он просто отобразит свободные физические страницы памяти на диапазон В, после чего доступ к этому диапазону будет выполняться уже без участия менеджера памяти. На рисунке 3 изображен пример виртуальной памяти процесса после первого доступа к диапазонам А и В. Рисунок 3 Как видно из рисунка, при доступе к обоим диапазонам доступ к физической памяти выполняется без участия менеджера памяти, т.к. ранее при первом доступе он отобразил на диапазоны А и В физическую память, а в физическую память диапазона А предварительно считал часть соответствующего файла. Кэш менеджер является центральным механизмом для всех открытых файлов в системе на всех дисках. Использование этого механизма позволяет не только ускорять доступ к файлам, но и экономить физическую память. Кэш менеджер не работает сам по себе, в отличие от менеджера памяти. Он полностью управляется файловыми системами, и вся необходимая информация о файлах (например, размер) предоставляется ими. Всякий раз, когда к файловой системе приходит запрос на чтение/запись, файловая система не читает файл с диска, вместо этого она вызывает сервисы кэш менеджера. Кэш менеджер, в свою очередь, пользуясь сервисами менеджера памяти, отображает файл на виртуальную память и копирует его из памяти в буфер запросчика. Соответственно, при доступе к этой памяти менеджер памяти пошлет запрос файловой системе. И это будет особый запрос, который будет говорить, что файл надо считать непосредственно с диска. Если выполняется доступ к файлу, который ранее уже был отображен кэш менеджером, то повторно отображен на виртуальную память он не будет. Вместо этого кэш менеджер будет использовать виртуальную память, куда файл был отображен ранее. Отображение файла отслеживается посредством структур, которые файловые системы передают кэш менеджеру при вызове его сервисов. Об этих структурах немного подробнее будет рассказано ниже. На рисунке 4 приведен пример чтения файла процессом. Рисунок 4 Как показано на рисунке выше, процесс выполняет чтение файла в буфер В. Чтобы выполнить чтение, процесс обращается к менеджеру ввода/вывода, который формирует и посылает запрос файловой системе. Файловая система, получив запрос, не считывает файл с диска, а вызывает кэш менеджер. Далее кэш менеджер оценивает, отображен ли файл на его виртуальную память, и если нет, то он вызывает менеджер памяти для того чтобы отобразить файл/часть файла. В данном примере файл уже отображен, а доступ к нему ни разу не выполнялся. Далее кэш менеджер копирует в буфер В процесса файл, отображенный на диапазон виртуальной памяти А. Поскольку доступ к диапазону А выполняется первый раз, управление получит менеджер памяти, затем он оценит диапазон, и, поскольку это отображенный на память файл, считает его часть в физическую память, после чего отобразит ее на диапазон виртуальной памяти А. После этого, как уже было описано ранее, доступ к диапазону А будет выполняться, минуя менеджер памяти. Ничто не мешает одновременно кэшировать файл и отображать его на память сколько угодно раз. Даже если файл будет закэширован и отображен на память десятков процессов, физическая память, которая используется для этого файла, будет одна и та же. В этом и заключается суть экономии физической памяти. На рисунке 5 приведен пример, где один процесс читает файл обычным образом, а другой процесс отображает этот же файл на свою виртуальную память. Рисунок 5 Как видно из рисунка выше, физическая память отображается на виртуальную память процесса В и виртуальную память кэш менеджера. Когда процесс А будет выполнять чтение файла в буфер D, он обратится к менеджеру ввода/вывода, который сформирует и пошлет запрос файловой системе. Файловая система, в свою очередь, обратится к кэш менеджеру, который просто скопирует файл, отображенный на диапазон виртуальной памяти С кэш менеджера, в буфер D процесса А. Поскольку в момент обращения к кэш менеджеру файл уже был не только отображен, но и ранее выполнялся доступ к диапазону С, на которую отображен файл, то операция будет выполнена без участия менеджера памяти. Процесс В при чтении/записи диапазона Е по сути получит доступ к тем же самым физическим страницам памяти, к котором при копировании файла получал доступ кэш менеджер. Файловые системы принимают запросы от пользовательского ПО или других драйверов. Перед доступом файл должен быть открыт. В случае успешного выполнения запросов открытия/создания файлов файловая система сформирует структуры памяти, которые используются кэш менеджером и менеджером памяти. Также следует отметить, что эти структуры уникальны для файла. Т.е. если конкретный файл диска был открыт на тот момент, когда пришел такой же запрос на этот же файл, файловая система будет использовать ранее сформированные структуры памяти. По сути, они являются программным представлением файла диска в памяти. На рисунке 6 приведен пример соответствия открытых экземпляров файлов и их структур. Рисунок 6 На рисунке процесс А открыл файл С и файл D, а процесс B открыл файл С два раза. Таким образом, имеется три открытых экземпляра файла С, когда структура, сформированная файловой системой, всего одна. Файл D был открыт один раз, следовательно, имеется один открытый экземпляр, которому соответствует структура, сформированная файловой системой. Любые запросы, направленные к файловой системе, не сразу обрабатываются ею. Запросы сначала проходят по цепочке драйверов, которые желают отслеживать такие запросы. Такие драйвера называют фильтрами. Они имеют возможность просматривать запросы до того, как они достигнут файловой системы, а также после того, как файловая система обработает их. Например, фильтр шифрования файлов может отслеживать запросы чтения/записи для того, чтобы расшифровать/зашифровать данные. Таким образом, не дорабатывая сами файловые системы, мы можем зашифровать данные файла. Фильтры могут привязывать свои уникальные данные к структурам файлов, которые формирует файловая система. Вместе драйвера фильтров и драйвер файловой системы формируют стек файловой системы. Количество фильтров может быть разным, также могут быть разными и сами фильтры. Теоретически их может и не быть совсем, но практически так не бывает. На рисунке 7 изображен стек файловой системы, в состав которого входят три фильтра. Рисунок 7 До того, как запрос достигнет файловой системы, он проходит последовательно через фильтры 1, 2 и 3. Когда запрос будет обработан файловой системой, то фильтрами он виден в обратном порядке, т.е. запрос проходит последовательно через фильтры 3, 2 и 1. Также, на примере выше фильтр 1 и фильтр 3 привязали свои структуры к структуре файла, которую сформировала файловая система после выполнения запроса открывания/создания файла. Подавляющее большинство задач решается посредством фильтрации, но наш случай уникален. Как было ранее отмечено, уникален он тем, что нужно предоставлять одновременный доступ к зашифрованному и расшифрованному содержимому, а также шифровать имена файлов. Тем не менее, мы попытаемся разработать фильтр, который позволит решить такую задачу. На рисунке 8 изображена ситуация, когда файл ранее был открыт расшифрованным. Рисунок 8 Это значит, что фильтры видели расшифрованное имя, и они, как это изображено на рисунке, могут привязать это имя к структуре, которую сформирует файловая система (как было ранее сказано, эта структура уникальна для конкретного файла диска) для дальнейших манипуляций с файлом. И в этот момент файл открывается зашифрованным, что означает, что фильтры видели зашифрованное имя. Как они поведут себя в такой ситуации, когда к структуре файла уже привязано расшифрованное имя? Очевидно, что поведение не предсказуемо, хотя и не обязательно, что последствия будут фатальными. В продолжение описанного выше можно добавить, что при доступе к содержимому файла также возникают проблемы, и гораздо более серьезные. Вернемся к ситуации, когда файл был открыт одновременно расшифрованным и зашифрованным. Эта ситуация изображена на рисунке 9, чтение/запись файла еще ни разу не выполнялись. Рисунок 9 Теперь представим себе, что пришел запрос на чтение расшифрованного содержимого. Файловая система воспользуется услугами кэш менеджера и передаст ему структуру файла, к которой и кэш менеджер, и менеджер памяти привяжут свои уникальные данные для дальнейшего управления отображением и кэшированием файла. Эта ситуация изображена на рисунке 10. Рисунок 10 Далее приходит запрос на чтение зашифрованного содержимого, и файловая система снова передает структуру файла кэш менеджеру, а поскольку кэш менеджер и менеджер памяти ранее к этой структуре привязали уникальные данные для этого файла, они просто воспользуются ими для выполнения запроса. Т.е. теперь в этих структурах будет указано, куда был отображен файл, и кэш менеджер просто скопирует данные файла из виртуальной памяти в буфер запросчика. Мы помним, что файл при первом доступе к нему был закэширован расшифрованным, таким образом при зашифрованном доступе в буфере запросчика окажутся расшифрованные данные. Мы только что разобрали две фундаментальные проблемы. На практике их было больше. Например, в рамках поставленной задачи к каждому зашифрованному файлу необходимо добавлять заголовочную информацию, что тоже не решается посредством фильтрации. Чтобы обойти все эти проблемы разом, было найдено решение — виртуальная файловая система. Виртуальная файловая система, по своей сути, мало чем отличается от обычной. Радикальное отличие состоит в том, что обычная файловая система работает с диском, а виртуальная работает с файлами других файловых систем, т.е. является обычным потребителем сервисов файловых систем. На рисунке 11 изображена концепция виртуальной файловой системы. Рисунок 11 В отличие от обычных файловых систем, виртуальная файловая система не регистрирует себя в системе (об этом не было сказано выше, но для того чтобы операционная система могла пользоваться сервисами конкретной файловой системы, она должна зарегистрироваться), а раз так, то запросы к ней направляться не будут. Чтобы решить эту проблему, мы используем фильтр для обычной файловой системы, но на этот раз его функции будут очень простыми и ограниченными, одна из них (и главная) — это отслеживание доступа к зашифрованным файлам. Как только фильтр увидит такой запрос, он просто перенаправит его к виртуальной файловой системе. Если же будет выполняться доступ к обычному файлу, запрос будет передан оригинальной файловой системе. Теперь давайте еще раз разберем расшифрованный и зашифрованный доступы, но уже в контексте виртуальной файловой системы. На рисунке 12 приведен пример, когда выполнялся доступ к расшифрованному и зашифрованному содержимому конкретного файла. Рисунок 12 Еще раз представим ситуацию, когда файл был открыт расшифрованным. Это значит, что в процессе выполнения запроса открывания файла, наш фильтр увидел его и перенаправил на виртуальную файловую систему. Виртуальная файловая система, получив запрос, оценивает тип доступа (расшифрованный или зашифрованный), и поскольку выполняется расшифрованный доступ, виртуальная файловая система сначала преобразует расшифрованное имя в зашифрованное, а после попытается открыть файл через родную файловую систему по этому имени (т.е. имя файла на родной файловой системе будет зашифрованным). В случае успеха виртуальная файловая система сформирует структуры памяти, которые позже будут использовать кэш менеджер и менеджер памяти. Теперь представим себе, что файл открывается зашифрованным, фильтр снова перенаправляет запрос виртуальной файловой системе, не делая никаких оценок. Виртуальная файловая система оценивает тип доступа, а поскольку доступ зашифрованный, она просто попытается открыть файл через родную файловую систему по этому имени. И опять, в случае успеха, виртуальная файловая система сформирует структуры памяти для кэш менеджера и менеджера памяти. Но в отличие от расшифрованного доступа, это будут уже другие структуры. Теперь, если файл снова будет открыт расшифрованным, виртуальная файловая система использует те же структуры, которые сформировала при первом расшифрованном доступе. В случае если файл снова будет открываться зашифрованным, файловая система использует структуры, которые сформировала при первом зашифрованном доступе. Таким образом, мы разделили доступ к расшифрованному и зашифрованному содержимому. На рисунке 13 изображена ситуация, когда доступ на чтение/запись к расшифрованному и зашифрованному содержимому файла ни разу не выполнялся. Рисунок 13 Теперь если будет выполняться расшифрованное чтение, виртуальная файловая система, пользуясь сервисами кэш менеджера, как показано на рисунке 14, передаст ему структуры памяти, которые она вернула при открывании файла расшифрованным. Рисунок 14 Кэш менеджер отобразит файл на виртуальную память и скопирует данные в буфер запросчика. Соответственно, в процессе копирования менеджер памяти пошлет запрос на чтение виртуальной файловой системе, которая в свою очередь пошлет запрос на чтение родной файловой системе, а поскольку кэш менеджеру были переданы структуры памяти для расшифрованного файла, виртуальная файловая система расшифрует данные и сообщит о завершении менеджеру памяти, так закэшируется расшифрованное содержимое. В случае если будет выполняться зашифрованное чтение, виртуальная файловая система передаст, как изображено на рисунке 15, кэш менеджеру структуры памяти, которые она сформировала при открывании файла зашифрованным. Рисунок 15 Кэш менеджер снова отобразит файл на виртуальную память (поскольку в этих структурах файл еще не отображался) и скопирует данные в буфер запросчика. И опять в процессе копирования менеджер памяти пошлет запрос на чтение виртуальной файловой системе, которая снова пошлет запрос на чтение родной файловой системе, а поскольку кэш менеджеру были переданы структуры памяти для зашифрованного файла, то, не расшифровывая данных, виртуальная файловая система сообщит менеджеру памяти о завершении. Так файл закэшируется зашифрованным. Как мы видим, виртуальная файловая система решает фундаментальные проблемы, не позволяющие иметь одновременный доступ к расшифрованному и зашифрованному содержимому файла, из-за чего приходится отказываться от классических механизмов операционной системы. В процессе фильтрации мы можем только добавлять данные к структурам памяти файлов, которые возвращает файловая система, и, поскольку мы не формируем эти структуры, мы не можем вмешиваться в них и управлять ими. А посредством виртуальной файловой системы мы их полностью формируем, и, следовательно, имеем полный контроль над ними, что необходимо в рамках решения данной задачи. Например, нам нужно обеспечивать согласованность расшифрованного и зашифрованного содержимых файлов. Представьте себе ситуацию, когда были записаны данные в расшифрованный файл и данные находятся еще в кэше, а не на диске. И в этот момент приходит запрос на чтение зашифрованного содержимого файла. В ответ на это виртуальная файловая система выгрузит расшифрованное содержимое на диск и сбросит зашифрованный кэш, что заставит кэш менеджер заново послать запрос на чтение виртуальной файловой системе для зашифрованного чтения. В рамках фильтрации подобная задача не решается в принципе. При разработке виртуальной файловой системы приходилось сталкиваться с необычными проблемами. Отчасти это вызвано тем, что мы работаем с файлами файловых систем, когда обычные файловые системы работают с диском. Так, например, была найдена ошибка в файловой системе NTFS. Проявлялась она в том, что доступ к файлу X:\$mft\<любое имя> приводил к повисанию всего доступа к диску X. В результате исследования было установлено, что NTFS не освобождала механизмы синхронизации для файла $mft, который является перечислителем всех файлов диска. И соответственно, чтобы найти какой-либо файл на диске, сначала нужно прочитать $mft файл, доступ к которому повис. Другой пример, который нельзя назвать необычным, это найденная ошибка в ядре Windows 8, в результате которой менеджер памяти полагает, что структуры памяти файла всегда последней версии. Из-за этого он пытается использовать некоторые части этой структуры, которых в действительности может не быть. И это приводило к BSOD. Реализация виртуальной файловой системы значительно сложнее реализации фильтра, но наличие такого механизма дает большую гибкость при манипуляциях с файлами. В том числе такую, о которой мы только что говорили. Хотя, на первый взгляд, может показаться, что задача тривиальна. В результате применения данного подхода к шифрованию были успешно реализованы функции предоставления одновременного доступа программных процессов к зашифрованному и расшифрованному содержимому, а также реализовано шифрование имен файлов, что позволяет обеспечить высокую степень прозрачности при реализации криптографической защиты информации. Надо отметить, что данный подход по обеспечению «прозрачности» шифрования файлов в ОС Windows успешно реализован в корпоративном продукте Secret Disk Enterprise («Аладдин Р.Д.»), который применяется многими организациями в России. Это в свою очередь доказывает жизнеспособность и перспективность применения данной идеи в процессе создания программ шифрования файлов на диске. В качестве заключения стоит отметить, что технологическая сложность файловой системы ОС Windows и отсутствие стандартных механизмов решения задач, подобных описываемой в данной статье, будут всегда являться препятствием создания удобных и простых программ, обеспечивающих защиту информации. В таком случае единственным верным решением является самостоятельная реализация оригинального механизма, позволяющего обойти данные ограничения без потери функциональности ПО.

Метки:  

Смотрите записи докладов виртуального форума «Данные. Технологии. SQL Server 2016»

Четверг, 23 Июня 2016 г. 19:35 + в цитатник
Доступны записи докладов форума в высоком качестве на Channel9. Программа форума была разделена на 3 трека, см. описание ниже, доклады из каждого трека доступны по ссылке channel9.msdn.com/Events/data-platform-russia/Virtual-Forum-data-technologies-SQL-Server-2016 SQL Server 2016: новые стандарты в мире OLTP. Трек посвящен возможностям новой платформы по повышению производительности и безопасности процессов. Так, скорость обработки транзакций на новой платформе выше в 30 раз, а запросов – в 100 раз, по сравнению с дисковыми реляционными базами. Безопасность системы обеспечивается современными инструментами Always Encrypted и Role Level Security. Бизнес-аналитика: SQL, Power BI, R, Mobile. Обсуждение вариантов практического применения SQL Server 2016 для разработки интеллектуальных приложений, способных анализировать данные и организовывать их в умные системы с помощью технологий бизнес-аналитики BI, а также использования языка R. Azure: новое поколение решений для аналитики, Big Data& IoT. Доклады об обеспечении автоматизации критически-важных процессов в компании благодаря умным аналитическим системам, машинному обучению и ботам, а также интеграции в облако с возможностью масштабирования ИТ-инфраструктуры. Microsoft и экосистема Blockchain (русский язык) Марли Грей, Директор по технологическим стратегиям, Microsoft, США Современная бизнес-отчетность с PowerBI Александра Чижова, Архитектор Business Intelligence и DataWarehouse решений, Microsoft, Россия R в SQL Server 2016: примеры обработки данных Сергей Олонцев, Администратор и разработчик баз данных, Лаборатория Касперского, Россия Самый безопасный SQL сервер. Новое в функционале ограничения доступа к данным в SQL Server 2016 Дмитрий Костылев, Руководитель группы разработки баз данных, Лаборатория Касперского, Россия Все записи виртуального форума «Данные. Технологии. SQL Server 2016» доступны по ссылке channel9.msdn.com/Events/data-platform-russia/Virtual-Forum-data-technologies-SQL-Server-2016

Метки:  

Поиск сообщений в verveukcen
Страницы: [2] 1 Календарь