Все примеры подразумевают использование Python.

Heroku

Регистрация на Heroku

  1. Регистрируемся на heroku.
  2. Идём по гайду, устанавливаем утилиты от heroku.

Конфигурация

В heroku конфигурацию принято хранить в окружении.

  1. Задаём параметры командой: heroku config:set variable="value". Не забудьте кавычки, особенно если в значении есть пробелы.
  2. В коде получаем доступ к ним с помощью os.getenv('variable')

Пример бота

git clone https://github.com/strizhechenko/twitterbot_example.git

Содержимое репозитория:

  • Procfile - объясняет какой командой запускать бота;
  • runtime - какая среда (читай версия python) нужна для запуска бота;
  • requirements.txt - все зависимости бота;
  • bot.py - код бота;
  • morpher.py - вспомогательный модуль для нормализации русскоязычных существительных.

Конфигурация

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

  • самого бота - user_access_token и user_access_secret
  • читателя - strizhechenko_access_token strizhechenko_access_secret

Просмотр конфигурации:

$ heroku config -s
template='%s – это когда тебя любят.'
timeout=30

Регистрация приложения в твиттер

consumer_key и consumer_secret - можно получить зарегистрировав приложение здесь - https://apps.twitter.com/. Это идентификаторы вашего приложения, их лучше никому не знать, в публичный код его зашивать не надо.

Авторизация пользователей

Авторизовать пользователей можно с помощью утилиты в twitterbot_utils:

virtualenv env/
. env/bin/activate
pip install -r requirements.txt
export consumer_key=your_consumer_key
export consumer_secret=your_consumer_secret
python -m twitterbot_utils.TwiAuth

Утилита спросит PIN код, который будет показан в браузере, а затем отдаст: access_token и access_secret. Авторизовать надо и себя и бота, поэтому не забудьте перелогиниться в браузере.

Осталось два парметра template и timeout:

template='%s – это когда тебя любят.'

template - шаблон фразы, в которую будут подставлены существительные, работает как printf почти.

timeout=30

timeout - интервал межд постингом, задаётся в минутах.

Есть ещё две необязательные опции:

tweet_grab = 3
tweets_per_tick = 2
  • tweet_grab - число твитов, которые подтягиваются из ленты reader’а для поиска существительных.
  • tweets_per_tick - число твитов, которые бот постит за один раз.

Deploy в heroku

Итак мы всё настроили, возможно слегка поправили код bot.py. Закомитьтесь, если что-то меняли:

git add -p
git commit -m "блаблабла"

Меняем origin, репозиторий-пример с гитхаба нам больше не нужен.

git remote remove origin
heroku create yourbotname
git push heroku master

После git push heroku должен обнаружить питоновое приложение и собрать его из requirements.txt:

remote: -----> Python app detected

Закончиться всё должно:

remote: Verifying deploy... done.

Запуск

heroku scale worker=1

Дальше остаётся смотреть логи и чинить если что-то не работает:

heroku logs -t

Перезапуск бота:

heroku scale worker=0
heroku scale worker=1

Ферма

Хостить много твиттер-ботов в Heroku сложно. У меня на момент написания статьи было 10-12. Какие были проблемы?

  • Большая часть кода - одинаковая
  • Все они состояли из двух ботов, один читает мою ленту, другой преобразует слова и пишет.
  • Для каждого отдельные средства управления
  • Моя лента - shared-ресурс, но у них не было shared-storage для него.
  • Обращения к twitter API тоже shared-ресурс, поэтому они часто упирались в его rate-limit.
  • В Heroku нет crontab, приходится пихать в приложение APScheduler, 10-12 ботов хватает чтобы выйти за пределы бесплатных dyno-часов из-за простаивающих приложений.

Я сделал ферму.

Основные идеи

1. Никаких virtualenv

Общее окружение для всех ботов - OpenVZ container.

2. Никаких избыточных вызовов API

Бот-читатель сохраняет свою ленту в Redis. Боты-писатели подписываются на него. В итоге запросы ограничиваются:

  • одним home_timeline() запросом в час от бота-читателя.
  • одним update_status() в час на каждого бота-писателя.

3. Одно кольцо чтобы править всеми

Создание, перечисление, получение статистики, уничтожение ботов - это команды. Они стандартные, их не надо каждый раз программировать. Команды вызываются в языке для команд - bash. Я создал утилиту tfctl, по большей части она прозрачная обёртка к python-скрипту и чёрт, отказаться от демонов в пользу crond с вызовами tfctl здорово! Никакого APScheduler, не надо мониторить состояние каждого бота, меньше ресурсов потребляется.

4. С хранилищем меньше повторов

Твиты не повторяются. Это круто.

5. Легче переносимость

Сейчас оно крутится в OpenVZ с 256Мб оперативной памяти. Всё разворачивается с помощью ansible-playbook. У tfctl есть опции export и import, создающие tar-архив, достаточный для восстановления данных, нужных боту (дамп базы redis).

6. Визуализация

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

  • для бота-читателя - число всех сохранённых твитов
  • для ботов-писателей - число необработанных твитов

influxdb and grafana

Проблема - я не определился со стратегией хранения кода

Есть несколько вариантов:

Вариант\Результат Всё унифицировано Форкать и бэкпортить легко Код, которым я горжусь доступен всем Мой стрёмный код доступен всем Требуется управление SSH-ключами
Все боты общедоступны, их список тоже. Можно в виде веток одного репозитория. + + + + -
Что-то общедоступно (github), что-то закрыто (bitbucket) - - + - +
Всё закрыто + + - - +