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

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

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

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

  • Создание приложения Streamlit
  • Не переходите прямо к Heroku, используйте Docker
  • Уменьшение размера изображения: если это Streamlit, не используйте Alpine!
  • Автоматизация последующих развертываний с помощью GitHub Actions Workflow
  • Другие полезные методы (внутреннее устройство Streamlit)

*Барабанная дробь**

Создание приложения Streamlit

Если вы уже знакомы со Streamlit, то знаете, что использовать Streamlit для создания веб-приложений так же просто, как писать простые скрипты Python с несколькими вызовами API здесь и там. Для наших целей вот пример сценария:

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

Чтобы запустить это на локальном сервере, достаточно просто выполнить приведенную ниже команду в терминале / командной строке;

$ streamlit run app.py

Не переходите прямо к Heroku, используйте Docker

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

Обычный метод - создать файлы requirements.txt, Procfile и setup.sh, а затем использовать Git для отправки в приложение Heroku, которое добавляется в качестве удаленного в ваш существующий репозиторий Git. Но приложения Streamlit имеют репутацию очень медленной загрузки на сервере Heroku.

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

Хороший способ решить эту проблему - использовать Docker. Docker - это платформа для очень быстрого создания, доставки и запуска приложений, не беспокоясь о зависимостях инфраструктуры. У одного из моих товарищей по команде возникла проблема с установкой Streamlit на ее машину (вините миллионы зависимостей!), И Docker был хорошим способом преодолеть это неудобство.

Все, что вам понадобится вместе с каталогом кода, - это файл requirements.txt, после чего вы создадите файл Dockerfile. После того, как Docker-образ веб-приложения создан, довольно легко отправить его в реестр контейнеров Heroku, чтобы начать внешний доступ к веб-приложению.

В первой строке кода в качестве базового используется изображение Python. Затем копируем и устанавливаем зависимости, перечисленные в файле requirements.txt. После этого мы копируем содержимое нашего каталога в новый каталог с именем / app и инициализируем его как рабочий каталог. Наконец, последняя строка кода запускает приложение Streamlit.

Чтобы протестировать образ Docker локально, две команды ниже соберут образ Docker и запустят контейнер;

$ docker build -t app:latest .
$ docker run app:latest

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

Развертывание в реестре контейнеров Heroku

Для развертывания в Heroku потребуются приведенные ниже команды;

$ heroku login
$ heroku container:login
$ heroku create app_name
$ heroku container:push web
$ heroku container:release web
$ heroku open

Первые две строки команды необходимы для входа в Heroku и Heroku Container соответственно. Следующая строка команды создает приложение на Heroku с указанным именем. Следующая строка создает образ и помещает его в Реестр контейнеров. Следующая строка команды передает изображение приложению, а последняя строка открывает развернутое приложение в вашем браузере.

Но даже после того, как я сделал это для моего проекта, размер моего образа Docker по-прежнему составляет 3 ГБ +, и для загрузки развернутого веб-приложения требуется вечность. :(

Уменьшение размера изображения: если это Streamlit, не используйте Alpine!

Во время исследования того, как устранить это узкое место, использование Alpine Linux было тем, что рекомендовали почти все ресурсы. Я использовал его, и мой образ Docker просто не собирался. Не удалось установить некоторые зависимости Streamlit.

Я исследовал, почему Капитан Америка, но для изображений меньшего размера не спасет меня, когда он мне нужен больше всего, и я наткнулся на эту потрясающую статью о том, почему Alpine не лучший выбор для изображений меньшего размера, когда дело доходит до Python Docker. Оказалось, что стандартные колеса PyPi не работают на Alpine, а у Streamlit таких прекрасных колес предостаточно. :(

Поэтому я заменил «Alpine Linux» на «Python-slim» в качестве базового образа. Я также использовал флаг «- no-cache-dir» в «pip install», чтобы он не сохранял установочные файлы пакетов в кеше после их установки.

Это резко уменьшило размер образа докера моего проекта с почти 4 ГБ до чуть более 300 МБ. Уу-у-у!

Автоматизация последующих развертываний с помощью GitHub Actions

Если вы хотите продолжать вносить изменения в свое веб-приложение без необходимости каждый раз использовать «heroku container: push» и «heroku container: release», рабочий процесс GitHub Actions станет следующим инструментом DevOps. GitHub Actions можно использовать для автоматизации части развертывания вашего рабочего процесса разработки, что означает, что вам не нужно снова отправлять вручную в Heroku после первого первоначального развертывания.

Все, что вам нужно сделать, это создать файл CI.yml в каталоге вашего проекта в указанном ниже формате;

.github - ›рабочие процессы -› CI.yml

CI.yml будет содержать строки кода, подобные приведенным ниже;

Ключ «name» описывает назначение файла CI.yml. Клавиша «on» запускает рабочий процесс каждый раз, когда выполняется отправка в главный репозиторий. В клавише «задание» находятся команды Heroku для входа в систему, отправки новой сборки и выпуска новой сборки в веб-приложение.

Наконец, чтобы разрешить доступ к Heroku, необходимо добавить ключ доступа в GitHub Secrets. Чтобы сгенерировать ключ аутентификации, следующая строка кода сделает это;

$ heroku authorizations:create

Скопируйте сгенерированный ключ и сохраните его в репозитории GitHub, перейдя в Настройки → Секреты → Новый секрет репозитория. Я бы назвал секретный ключ HEROKU_API_KEY, чтобы он соответствовал имени переменной, используемой Heroku, даже если вы можете изменить имя на любое слово, которое вам нравится. Убедитесь, что вы используете то же имя в файле рабочего процесса.

Другие полезные советы

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

  • Удалите статические файлы из каталога вашего проекта, так как они добавятся к основной части вашего файла. Для вашего приложения было бы лучше, если бы эти статические файлы были сохранены, скажем, на Amazon s3, и загружались в ваше приложение через URL-адреса, что приводит нас к следующему совету;
  • Максимально используйте st.cache. Файлы или функции, которые не используются очень часто, например pd.read_csv, следует строго кэшировать. Это означает, что кешированные файлы не будут перезагружаться каждый раз, когда вы взаимодействуете со своим веб-приложением.
  • Используйте состояние сеанса для хранения переменных при повторных запусках. Помимо помощи со временем перезагрузки, это, честно говоря, избавило меня от стресса, связанного с написанием множества функций, чтобы убедиться, что мои переменные постоянно хранятся для повторного использования.

В заключении;

В этой статье,

  • Я объяснил, почему вы должны использовать Docker для развертывания на Heroku вместо того, чтобы сразу же развертывать веб-приложение на Heroku.
  • Я также подробно рассказал, как уменьшить размер образа Docker, используя Python-slim в качестве базового образа.
  • Мы также узнали, как использовать GitHub Actions для автоматизации последующих развертываний.
  • Наконец, мы рассмотрели другие полезные методы, которые помогут уменьшить размер нашего приложения.

Спасибо, что зашли так далеко. Удачного стриминга!

Не стесняйтесь связываться со мной в LinkedIn и Twitter. Буду рад ответить на любые ваши вопросы или предложения фрилансеров Streamlit :)