Здесь, в Dstillery, мы недавно обнаружили новую игрушку: пакет Shiny для R. Это простой и удобный способ превратить таблицы MySQL (или Hive) в интерактивные веб-приложения для визуализации данных, наполненные забавными кнопками, ползунками и ручками. . Вы можете прочитать все об этом здесь, но сначала небольшое предупреждение: если у вас есть реальная работа, вы можете отложить ее и придумывать причины для создания собственных приложений Shiny. Это так круто.

70 строк кода = 1 увлекательная игрушка в стиле радуги

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

Естественно, мы начали писать приложения Shiny для разных вещей и публиковать ссылки на всю компанию. То, что раньше занимало несколько дней, чтобы кодировать в AngularJS и Python, теперь займет несколько часов от этапа разработки концепции до ее представления конечному пользователю. Специалистам по обработке данных в нашей команде это очень понравилось, но инженеры - прирожденные пессимисты - всегда думали о будущем. Как долго это могло продолжаться? Когда же неизбежный обрыв масштабируемости внезапно возникнет из-за ржи?

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

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

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

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

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

  • Код размещен в репозитории Git
  • Maven компилирует и создает RPM
  • RPM развертывается во внутреннем репо.
  • Используя Salt, мы указываем, какая версия какого RPM будет развернута на какой машине (ах).
  • При необходимости соль также можно настроить с помощью шагов после установки.

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

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

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

Однако можно полностью определить среду Packrat с помощью текстового файла сведений о пакете, называемого packrat.lock, и сопутствующего файла конфигурации с именем packrat.opts. Эти два текстовых файла прекрасно вписываются в репозиторий Git вместе с файлом app.R, и мы можем восстановить из них среду с помощью команды packrat :: restore () в R .

Это очень полезно, потому что означает, что мы можем полностью определить как наше приложение, так и нашу виртуальную среду, используя текстовые файлы, и упаковать все это в репозиторий Git. Затем мы можем использовать Salt для вызова сценария после установки, который «воссоздает» среду Packrat внутри установочного каталога после установки RPM.

Для нового разработчика, запускающего проект Shiny server, процесс выглядит следующим образом:

  1. Напишите свой код app.R и протестируйте его локально. Вы можете сделать это без среды Packrat, если хотите.
  2. После завершения кода откройте сеанс R, перейдите в каталог, содержащий ваш app.R, и запустите packrat :: init (). Эта команда прочитает ваш код и построит дерево зависимостей, состоящее из пакетов, на которые вы ссылаетесь в инструкциях library (…) в вашем коде, и всех их зависимостей. Затем он загрузит эти пакеты и поместит их в каталог приложения вместе с файлами packrat.lock и packrat.opts.
  3. Затем введите packrat :: on (), чтобы активировать среду. Теперь, когда вы тестируете свое приложение локально, оно будет использовать среду Packrat и не будет ссылаться на какие-либо пакеты, установленные в системе.
  4. Если каталог вашего приложения еще не является репозиторием Git, вы можете настроить его. Обязательно добавьте каталог packrat / lib / в .gitignore, чтобы большие двоичные файлы не добавлялись как элементы Git.
  5. Добавьте сценарий R после установки и сопровождающий сценарий оболочки Bash в репозиторий Git (как на приведенной выше диаграмме).
  6. Добавьте pom.xml и используйте его для настройки maven-rpm-plugin для создания RPM с содержимым репозитория. (Maven позволяет указать сценарий после установки, но не позволяет. Лучше сделать это в Salt, потому что он дает вам больше контроля над тем, от имени какого пользователя запускать его и какие типы событий квалифицируются как установка. )

Теперь у вас есть репозиторий Git, который можно подключить к среде развертывания Dstillery как есть - никто, кроме вас, даже не должен знать, что это проект R, а не проект Java!

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

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