Что делать, если это маленькое веб-приложение внезапно стало вирусным

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

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

Я провел некоторое время, путешествуя по миру, что дало мне фантастическую возможность открыть для себя новые культуры, узнать больше о смысле жизни и, конечно же, познакомиться с новыми людьми и собрать много контактов. Чтобы идти в ногу со всеми и не допускать неуважения, читая сообщения и не отвечая на них, я использовал возможности групп Telegram Messenger, чтобы собрать всех в одном месте и позволить обсуждениям развиваться, а дружеским отношениям процветать. . Вскоре после того, как мои друзья начали добавлять своих друзей, которые сочли нашу группу достаточно любезной, чтобы пригласить своих, у нас быстро осталось более 2000 человек, которые обсуждали все, от своей повседневной жизни и университетской борьбы до глобальной экономики и политики. Как обычно в таких случаях, начали появляться некоторые мошеннические элементы, пытающиеся нарушить мирный и дружелюбный характер группы. Пришло время действовать.

Познакомьтесь с ботом LittleGuardian.

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

Урок 1: Никогда, никогда ничего не кодируйте жестко.

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

Вопросы, которые я должен был задать себе тогда.

  • Что, если я добавлю нового администратора?
    Чтобы добавить нового администратора, мне нужно было перезапустить процесс бота. Когда я был в движении, это было далеко не эффективно и невозможно.
  • Что, если кто-то не заслуживает доверия, и я удалю его?
    То же, что и выше, с более высокой степенью срочности, если предположить, что в «мозгу бота» администраторы всегда готовы действовать все, что они хотят.
  • Что, если кто-то добавит бота в новую группу с совершенно другим набором администраторов?
    На этом этапе администраторы были жестко запрограммированы, и я ничего не знал о других группах, в которых использовался бот. на (кроме их идентификаторов). Я никак не мог с этим справиться.

Вторая итерация бота

Версия 2.0 была переписана с нуля, все еще на Ruby, с поддержкой Google Cloud Datastore для постоянного хранения информации в случае перезапуска и поддержки нескольких групп. Здесь много IF и данных для хранения, чтобы сделать бота немного умнее, чем он был раньше. Благодаря постоянному хранилищу данных я, наконец, смог перезапустить бота по своему желанию, несколько групп и сотни активных пользователей не повлияли на эксплуатационные расходы - это была версия, которая испытала наибольший рост функциональности.

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

Последнюю версию веб-сайта можно увидеть здесь - она ​​находится в сети как часть устаревшей программы поддержки пользовательских ботов - https://telegram-bot.in.

Еще одна порция вопросов

  • Подходит ли язык для этой задачи и позволяет ли мне развиваться дальше?
    Мне всегда нравился Ruby, но иногда он может быть немного медленным, все, что я хотел в то время, - это скорость, позволяющая вещи как можно быстрее, чтобы оставаться в топе и создавать продукт, которым все любят пользоваться.
  • Что происходит со счетом, когда трафик резко возрастает?
    Я узнал, что сообщество Telegram может быть непредсказуемым, и если людям что-то понравится, они начнут этим пользоваться. Каждое изменение, которое я применял к боту, требовало перезапуска, что приводило к загрузке данных из хранилища данных, что стоило реальных денег. Нормальное развитие (и возможные ошибки) стало довольно дорогим.
  • Знают ли пользователи, как использовать мой продукт?
    Без документации пользователи понятия не имели, как использовать сервис и получить от него максимальную отдачу. Мне лично отправляли сообщения в разное время дня и ночи (благодаря всемирному охвату и различию часовых поясов) с вопросами о конкретных командах. Было необходимо создание документации, ориентированной на пользователя, с использованием ясного и наглядного языка.

Урок 2: выбирайте инструменты с умом

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

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

Третья итерация

После ответов на вопросы и бесчисленных часов, потраченных на тушение пожаров, я решил все переписать на Golang. Он хорошо известен своей скоростью, а также фактическим компилятором, сообщающим вам о любых потенциальных ошибках, что является приятным изменением по сравнению с тем, что клиенты говорят вам, что что-то не работает. Я также добавил базовую статистику с помощью GCP Stackdriver, чтобы лучше понимать трафик, избавился от шума журналирования, который был приемлем для нескольких групп, но вместе с ростом популярности стал нечитаемым и сложным для понимания. Эта версия была полна ошибок новичков и неверных предположений, которые раздражали клиентов. На тот момент ничего не изменилось на уровне хранения данных, появилось больше платных и бесплатных функций. Это была первая версия, использующая Docker и также развертываемая в кластере Kubernetes в GCP. Я создал конвейеры CI / CD в Google Cloud Build, поэтому вносить изменения было так же просто, как загружать новый код в репозиторий Github.

Еще вопросы

  • Как мне следить за фактическим трафиком?
    Журналы могут быть отличным источником истины, но их сложно анализировать, особенно когда у вас на глазах текут сотни строк в секунду . Диаграммы были бы лучше - они просты для понимания, вы можете установить базовый уровень и процентили, чтобы быстро выявить проблемы с помощью беглого взгляда.
  • Являются ли вещи, которые я регистрирую и за которыми наблюдаю, действенными?
    Не все, что я записал, было полезным. Они создавали ненужный шум, из-за которого я полностью игнорировал логи. Внесение всего в систему ведения журналов Google позволило выполнить поиск, но на самом деле - сколько из этих созданных строк принесло хоть какую-то ценность?
  • Использую ли я весь потенциал технологий, которые использую?
    В основном это было связано с моей растущей любовью к платформе Google Cloud. Все API, которые они предлагают, были удобны для разработки, удовлетворяли все мои потребности и планы на будущее расширение. Я потратил немало часов на чтение документации по большинству их продуктов, задавая себе вопрос - как я могу использовать это в своем проекте.

Четвертая итерация

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

До этого каждое загруженное изображение или файл сканировалось отдельно - либо VirusTotal, либо Google Vision. Я придумал простое решение как для ускорения ответа бота, так и для уменьшения количества обращений к API (а также для снижения стоимости). Каждое изображение перед сканированием загружается ботом, который затем вычисляет свой хэш MD5 и проверяет с базой данных SQL, если уже известно, что файл возвращает результаты немедленно. В случае совершенно нового файла - бот ждет результатов сканирования и сохраняет их в локальной базе данных для дальнейшего использования. Это особенно полезно для людей, которые делятся файлами мультимедиа и документов в нескольких группах. Я также добавил интеллектуальный фильтр сообщества, который хранит информацию о каждом пользователе и его действиях во всех группах, в которых присутствует бот, поэтому, когда тот же человек присоединяется к другой группе, мы уже знаем, является ли он известным нарушителем спокойствия или образцовым пользователем.

Набор вопросов на этом этапе

  • Достаточно ли оптимизирован мой код для работы при высокой нагрузке?
    Все работает хорошо в тестовой среде или при минимальном трафике. Как ведет себя ваша программа или система при резком всплеске интереса? Что, если пик длится вечно?
  • В каких областях я могу улучшить его производительность?
    Сесть и просмотреть свой код, функция за функцией - это лучший способ. Довольно часто можно увидеть множество специальных строк, которые можно либо сжать, либо полностью отбросить без какого-либо влияния на производительность.
  • Могу ли я упростить программирование, тестирование и развертывание?
    Конвейеры - ваш друг. Любая форма интеграции CI / CD творит чудеса, когда дело доходит до быстрого расширения или когда над проектом работают несколько человек. Нельзя игнорировать и возможность вернуться к предыдущей стабильной версии по желанию.

Урок 4: Постоянное улучшение

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

Пятый и «мы почти у цели».

Наконец-то бот был готов стать полностью публичным. Я решил переписать его еще раз, используя все знания, полученные на предыдущих этапах, добавив тесты, которые нужно запускать непосредственно перед фиксацией изменений в репозитории, и еще больше тестов, выполняемых на стороне Code Build. Я также сильно сосредоточился на сборе статистики о работе бота. Добавление таймеров для каждой функции и действия было отличным шагом - особенно в мире телеграмм, когда спамеры могут массово присоединяться к группе и за несколько секунд наводнять ее нежелательным контентом - я хотел быть быстрее. Тонны оптимизации кода на этом этапе привели к тому, что среднее время ответа прием-анализ-действие составило 30 миллисекунд, что превосходит всех существующих спамеров и делает сам спам почти невидимым для обычных пользователей. Большой успех, но в то же время растущая популярность (на этом этапе почти 200 групп с тысячами пользователей) заставили меня задуматься о сборе дополнительных средств для покрытия стоимости хостинга (кластер Kubernetes, сервер базы данных SQL). У меня не было выбора, кроме как добавить премиум-версию (с использованием платежей в Telegram, так что весь процесс оплаты происходит в вашем приложении Telegram) и установить ограничения на бесплатное сканирование изображений. Я также уменьшил размер контейнера докеров с 210 до 9 МБ за счет использования многоступенчатых сборок, которые позволили мне создавать и развертывать быстрее, тратя меньше средств на хранилище. Вдобавок ко всему, я наконец-то добавил оповещения и интеграцию со слабым сервером, чтобы важная информация всегда была под рукой, и даже если контейнер перезапускается после сбоя бота, я могу исправить основную проблему почти сразу, чтобы она больше никогда не повторилась. Бот также получил официальный канал объявлений, который я постоянно обновляю, информируя пользователей о новых функциях, организуя пулы с предложениями по новым функциям и оставаясь на связи.

Версия Sixt, текущая

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

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

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

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

Текущая версия бота, его панель находится в его новом доме - https://telegram-bot.app. Мобильные приложения находятся в разработке, контент (поверх функций) растет день ото дня, и пользователи уже начали мигрировать в совершенно новый мир (который позволяет им также запускать свою собственную версию с белой этикеткой).

Урок 5:

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

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

Счастливый конец (пока)

  • От 50 до 19000 строк оптимизированного кода.
  • От 1 до 800 групп Telegram в первые несколько месяцев. 9000 групп на момент написания.
  • Обработано более 55 миллионов сообщений.
  • Более 1 миллиона уникальных пользователей.
  • Поддержка 7 языков (спасибо сообществу).
  • Премиум и кастомные версии и страница Patreon для покрытия расходов.