Как Создать Микросервис На Paas

Если вас интересует, как можно автоматизировать повседневные задачи разработчиков и построить удобную систему оркестрации зависимостей ваших сервисов, загляните в кат. Об этом рассказал в своем докладе на конференции Golang Live 2020 Иван Королев, разработчик продуктовой команды Авито — Auto B2B. Он затронул тему платформенных решений для создания микросервисов и на живом примере продемонстрировал, как создается и развивается микросервис в Авито.



Как создать микросервис на PaaS

Что такое платформа как услуга и зачем она нужна? Платформа снижает накладные расходы на интеграцию с различными частями инфраструктуры, будь то базы данных или сервис сбора логов и метрик.

Если у компании нет платформы, то каждая продуктовая команда вынуждена заниматься этим вопросом самостоятельно.

В лучшем случае решением могут стать библиотеки.

В худшем случае на каждом СТО у вас есть свои костыли и велосипеды.

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

После этого она предлагает решать проблемы единообразно.

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



Как PaaS появился на Авито

Давайте посмотрим на инструменты инженеров Авито четырехлетней давности.

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

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



Как создать микросервис на PaaS

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

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

Три года назад мы использовали ванильный Kubernetes. А разработчики, получив определенные права на постановку и производство, фактически выполняли роль системных администраторов.

Они не только разработали сервис, но и развернули его, отслеживали и читали логи.

Конечно, существовали конвейеры шаблонов для CI, которые упрощали развертывание.

Мне не пришлось вводить команду в kubectl, чтобы развернуть ее вручную.

Но мы по-прежнему использовали относительно низкоуровневые интерфейсы, такие как kubectl. Позже появились контрольные диаграммы, упрощающие доставку сервиса в виде набора манифестов Kubernetes. Что у нас в итоге получилось? Мы придумали штуку под названием PaaS, и она состоит из двух частей.

Первая — консольная утилита, благодаря которой с сервисом можно делать все необходимое: от его создания до вывода на продакшен, просмотра логов и развертывания в локальной среде.

Вторая часть — это панель управления PaaS. Это графический интерфейс, частично дублирующий консольную утилиту, но предоставляющий определенные удобства.

Все детали, вся внутренняя реализация скрыта от разработчиков за этими двумя частями интерфейса.

В чем заключается концепция PaaS? Максимально автоматизируйте все, что можно автоматизировать, сократив накладные расходы на ручные действия команд разработки продуктов.

Отставание в области PaaS основано на реальных инженерных потребностях, сформированных годами боли и крови.

Кроме того, вы можете проводить опросы о том, что люди ставят в приоритет, а что — меньше.

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

Так формируется бэклог и дорожная карта разработки.

Конечно, PaaS должен иметь низкий входной барьер.

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

В идеале вам необходимо обеспечить нулевые накладные расходы на интеграцию с инфраструктурой.

Например, настройка подключений к базе данных (в том числе секретных), к кэшам, интеграция в систему доставки логов.

Я бы хотел, чтобы разработчики не думали об этих вещах.

Это не всегда получается, но к этому нужно стремиться, что возможно с помощью PaaS. Как это выглядит для пользователя?

Как создать микросервис на PaaS

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

То есть это дашборд статуса сервиса с необходимыми ссылками на Grafana, Jaeger и репозиторий.

Кроме того, имеется сводная информация для быстрого поиска проблем.

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

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

Особенно когда кто-то вместо решения проблем с продуктом половину спринта потратил на развертывание сервиса и PG Bouncer, настройку подключения к базе данных и соединение всех сервисов между собой.

Таких проблем может быть очень много.

Прежде всего, мы переходим от проблем к решениям.

И именно так я продолжу рассматривать весь жизненный цикл создания сервиса.

Сначала обсудим, что нам навредило, а потом, что мы придумали, чтобы сделать жизнь разработчиков лучше.

Жизненный цикл услуги довольно очевиден.

Мы должны создать его.

Затем его нужно протестировать, внедрить в производство, а затем успешно эксплуатировать.



Что необходимо для создания услуги

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

И создать пак ресурсов, различные дашборды, создать пайплайны в CI, проект в Sentry. Разных систем может быть с десяток.

Кажется, это займет всего около часа.

Но вы можете забыть создать какой-то ресурс, сделать это неправильно, узнать об этом через час, через два часа, через день или только в продакшене.

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

Для этого у нас есть утилита Avito Service Create, которая проводит разработчика по шагам выбора шаблона, а также указывает название, описание услуги и тип:

Как создать микросервис на PaaS

В результате мы получаем успешно созданный сервис, клонированный из конкретного шаблонного репозитория, с установленными проектами в TeamCity, Sentry и Grafana. Разработчик может мгновенно развернуть эту услугу.

В результате мы получаем:

Как создать микросервис на PaaS

Все это происходит «под капотом», разработчику не приходится об этом думать.



Разработка сервиса с использованием PaaS

Главное, что мешает разработке без PaaS, — это отсутствие унификации.

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

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

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

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

Пока вы этого не узнаете, вы не сможете развернуть службу.

Интерфейсы взаимодействия сервисов могут не совпадать с разными частями инфраструктуры.

Например, Kafka может иметь несколько разных библиотек.

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

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

Что мы сделали для решения этой проблемы? Мы договорились о единой структуре проекта для каждой технологии.

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

Кроме того, PaaS предоставляет унифицированный протокол RPC для межсервисной связи.

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

Перейдем к настройке сервиса.

Вначале у нас был Kubernetes и, соответственно, его чистые манифесты.

Потом привезли штурваловые схемы, что немного упростило настройку.

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

Интересуйтесь лучшими практиками, натыкайтесь на одни и те же ошибки, даже несмотря на наличие документации.

В результате мы получаем 40 килобайт манифестов в каталоге helm каждого сервиса.

При этом разница между этими манифестами в разных сервисах составляет фактически несколько строк.

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

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

Он представляет собой именно те части сервиса, которые могут меняться: имя, описание, движок под капотом, настройки для развертывания (например, ЦП, память, количество реплик в разных средах):

Как создать микросервис на PaaS

Таким образом, мы заносим в конфигурацию только то, что необходимо изменить.

И файл конфигурации у нас единый, с плоской структурой, в отличие от YAML. Основная проблема с чертами шлема в том, что они очень многословны.

Приходится сидеть с линейкой и мерить, правильно ли сделан отступ этой команды, иначе все сломается и не будет работать.

TOML решает эту проблему.

Кроме того, сервисы настраиваются через переменные среды, а их значения также хранятся в app.toml. Какие были проблемы с управлением секретами? Мы выбрали хранилище для хранения.

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

Нужно помнить о разветвленной древовидной структуре ключей.

Пользовательский интерфейс далеко не самый удобный: он не позволяет просто зайти в корень и перейти к нужной клавише.

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

Казалось бы, ничего сложного, но это действие требует еще и когнитивной нагрузки.

Кроме того, нужно сделать интеграцию в helm-чартах, чтобы были подняты init-контейнеры, которые пойдут в vault и сформируют конфигурацию для подов.

И все это может рухнуть в самый неожиданный момент производства.

Казалось бы, секреты — это та же часть конфигурации.

Зачем сервису вообще нужно знать, что для обычных конфигов нужно идти в переменные Env, а для «секретных» — в vault? Все это можно совместить.

Мы меняем секреты прямо в панели управления PaaS. Они развертываются в пространстве имен.

Таким образом мы можем изолировать сервисы друг от друга.

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

Если он не унифицирован, то для каждого сервиса нужно писать клиент, возможно даже на двух-трех языках.

Необходимо не забывать обрабатывать ошибки и включать общие библиотеки, например, автоматический выключатель.

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

И совсем космическая вещь: выставьте таймауты так, чтобы они вписывались в NFR сервиса.

Простой пример: сервис, который обращается к базе данных при каждом попадании, отвечает через секунду, а кто-то обращается к нему с таймаутом 200 мс.

Я хочу адекватно отслеживать и настраивать такие вещи.

К чему мы пришли в PaaS? У нас есть контракт в одном описании как для клиента, так и для сервера.

На основе этого описания автоматически генерируется код. И уже в этот автоматически сгенерированный код (по сути, клиентскую или серверную библиотеку) заложены все паттерны взаимодействия микросервисов.

Туда подключаются трассировка, метрики и т.д. Как это выглядит? У нас есть свой формат описания.

Это подмножество Protobuf или Thrift.

Как создать микросервис на PaaS

В результате описываем сервис, хэндлы RPC, DTO на входе и выходе.

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

В файле описана как серверная часть, генерирующая серверный код, так и клиентская часть.

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

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

Эти поля могут быть лишены приоритета и преобразованы в необязательный статус.

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

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

Синхронное взаимодействие основано на внутреннем протоколе RPC; разработчик практически не имеет доступа к деталям реализации.

Ему не важно, как передаются данные на транспортном уровне: JSON, Protobuf или Msgpack. Таким образом, команда архитекторов освобождает себе руки на будущее и при необходимости может безболезненно внедрять новые протоколы.

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

Подключение библиотек явное и единообразное.

И перенося задачи из сервиса в сервис, вы знаете, как с этим работать.

У нас также есть асинхронное взаимодействие, построенное поверх нашего протокола.

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



Как создать микросервис на PaaS

Таким образом, наш собственный язык описания дает нам единый формат для всего межсервисного взаимодействия.

При этом синтаксис близок к Go, имеет простую структуру без импорта и под капотом даже использует встроенный в Go лексер.

Отсутствие вендор-лока позволяет использовать под капотом любой удобный протокол и защищает разработчиков от возможных проблем несовместимых изменений, как в случае с Protobuf. При этом можно создавать разнообразные проверки.

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

Хранилища данных также подключаются через утилиту авито в 1 клик.

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

Выглядит просто: выбираем репозиторий, например Postgres, вводим одну команду, и зависимость добавляется в app.toml:

Как создать микросервис на PaaS

Redis подключается аналогично: выбираем тип хранилища: кэширование в Kubernetes, с резервными копиями или без них, шардированное за пределами Kubernetes. В app.toml также добавлена зависимость Redis и даны рекомендации по подключению библиотеки к сервису.

Вот так выглядит описание хранилища в app.toml: указывается тип хранилища, его размер и используемая версия.

На основе этих данных генерируются манифесты для рулевой диаграммы:

Как создать микросервис на PaaS

А самое главное, такое описание позволяет упростить локальную разработку.

Для остальных сервисов, от которых мы зависим, переходим на стадирование.

Локальные хранилища развертываются в миникубе, включая локальную шину данных.

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

Местная среда максимально приближена к производственной.



Давайте поговорим о тестировании

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

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

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

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

Мы используем сервисную сетку для маршрутизации трафика между сервисами.

Каков подход? Например, у нас есть пять сервисов, которые взаимодействуют друг с другом.

И мы хотим протестировать новую версию Сервиса 3. Первое, что приходит на ум — развернуть весь набор взаимодействующих друг с другом сервисов в тестовой среде.

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



Как создать микросервис на PaaS

Поэтому поднимаем Сервис 3 в тестовой среде.

Добавляем в запрос специальный заголовок, балансировщик трафика его принимает, парсит и понимает, что Сервис 2 должен идти с этим заголовком к новой версии Сервиса 3, расположенной в тестовой среде.

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

Фактически большая часть задач разработчика уже выполнена.

Но наше развертывание также лежит на командах разработчиков.



Развертывание и эксплуатация

Какие проблемы с развертыванием? Helm — хороший инструмент; его можно использовать для создания высокоуровневого описания службы и всех ее зависимостей.

Однако с этим инструментом довольно сложно работать.

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

В этом случае все ломается, и helm не обеспечивает транзакционные развертывания.

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

В общем, начинаются боли.

Поэтому команда архитекторов написала собственный деплоер — Jibe (он пока не open source, но такие планы у ребят есть).

Это решает проблему развертывания в несколько кластеров.

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

В будущем вы сможете генерировать манифесты самостоятельно.

Например, у нас есть два кластера и версия сервиса V5, которая развернута в обоих кластерах.

Jibe, используя манифесты для новой версии, развертывает версию V6 в обоих кластерах:

Как создать микросервис на PaaS



Как создать микросервис на PaaS

Трафик в это время все еще идет по V5. После завершения проверки готовности переключаем трафик со старых версий на новые.

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

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

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

Если переключение трафика прошло успешно, старая версия гасится.

Что мы получаем? Несколько этапов развертывания, каждый из которых может иметь полуручное управление.

Мы можем откатить сервисы как с помощью Canary, так и сине-зеленого развертывания, и при этом получаем гарантию согласованности версий сервисов на всех кластерах.

Как PaaS помогает нам с операционной точки зрения? Типичная болевая точка для инфраструктурных команд: когда продуктовые группы делают слишком много запросов на мощность, ЦП и память.

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

Эти значения могут со временем устареть.

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

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

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

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

Вначале, когда сервис создается, разработчику предоставляется довольно большой запас для обработки будущей нагрузки.

А когда статистика накапливается, запросы выравниваются.

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

Обнаружение сервисов — это та часть, о которой разработчики тоже не хотят думать.

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

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

И возникает вопрос: а как все это масштабировать, если у нас новый кластер? Что мы наделали? В App.toml есть специальный раздел с зависимостями сервисов:

Как создать микросервис на PaaS

Таким образом, мы решаем две проблемы.

Проблема с конфигурацией.

Из названия сервиса по определенному шаблону формируется переменная ENV, в которую подставляется URL, куда нужно постучать.

И второе: таким образом мы можем сформировать граф зависимостей для каждого сервиса не на основе статистики, а просто на основе манифестов.

И разработчик тоже получает преимущество.

Нет необходимости указывать какие-либо URL-адреса; система автоматически подставит необходимый путь.

А балансировщик, который стоит перед сервисом, переведет подключение на нужный сервис нужной версии.

Например, в продакшене в случае канарейки, или в постановке в случае такого случая с тестированием.

Кроме того, автогенерируемые клиенты автоматически собирают все значения из ENV. Кроме того, у нас есть инструмент с открытым исходным кодом Service Navigator (его можно посмотреть на нашем GitHub), который обеспечивает сетку сервисов и переходы от одного сервиса к другому.

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

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

Все эти политики прозрачно настраиваются командой разработчиков продукта.

Под капотом используется Proxy Envoy, который балансирует трафик, а его динамической настройкой занимается Navigator:

Как создать микросервис на PaaS

Таким образом, у нас есть стандартные дашборды Observability, которые могут показать, что происходит с сервисом.

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

Естественно, Джаггер имеет отношение к розыску.

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



Преимущества и недостатки PaaS

У каждой системы есть недостатки.

Главный недостаток PaaS — со временем накапливается багаж сервисов.

Они хорошо работают, поэтому их никто не хочет трогать, да и деловой необходимости в этом нет. Кроме того, эти услуги могут быть очень специфическими.

Не все случаи покрываются PaaS. Соответственно, миграция существующих сервисов может стать болевой точкой.

Важно найти баланс между автоматизацией и гибкостью настройки.

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

Они могут быть расстроены тем, что PaaS лишает их привычной части работы.

Вам придется тратить время на общение.

По нашему опыту, люди в конечном итоге соглашаются, что PaaS приносит больше радости, чем боли.

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

Какие преимущества у нас есть? Мы экономим время продуктовых команд, наш «зоопарк» технологий под контролем.

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

И технология радара поддается пониманию.

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

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



выводы

PaaS необходим каждой компании, в которой количество разработчиков увеличивается от десятков до сотен.

PaaS можно рассматривать как продукт, который решает реальные проблемы людей и позволяет бизнесу расти.

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

Это верно.

А платформа – это то, что должно появиться в каждой крупной компании.

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

Даже в эпоху пандемии мы очень близки.

Хотите получать полезные материалы о разработке GO? Подписаться Новостная рассылка Конференция ГолангКонф.

Теги: #ИТ-инфраструктура #Микросервисы #golang #микросервисная архитектура #ontico #платформа
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.