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

2018 год был особенно захватывающим не только с технической точки зрения, но и во всех аспектах бизнеса. В январе мы были отобраны для участия в программе Google Launchpad Accelerator, в июле получили финансирование Серии А и в декабре были названы Новатором года для всей Африки от AABLA. Вся команда невероятно много работала, и есть чем гордиться.

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

Есть несколько аспектов, которые определяют бизнес. Мы разработали внутренние и внешние API (backend); создали продукты (frontend), которые состоят из наших клиентских приложений; и внедрили конвейеры обработки данных (backend), которые преобразуют необработанные изображения в данные, которые направляются через продукт к нашему клиенту.

Что касается веб-интерфейса, инфраструктура масштабирования легко обрабатывается AWS Cloudfront, который представляет собой современную сеть доставки контента. Дополнительные проблемы, с которыми мы столкнулись с точки зрения UI / UX и удовлетворения потребностей клиентов, можно было бы подробно обсудить, но, возможно, в другой раз. В рамках этой статьи я хочу сосредоточиться на технологиях, связанных с серверной частью, поскольку это то, что мы значительно улучшили в течение 2018 года.

Вкратце: мы отправляем пилотов на ферму, чтобы сделать необработанные визуальные и мультиспектральные изображения фруктовых садов. Эти изображения загружаются на наши серверы, запуская наши автоматизированные конвейеры для обработки данных. Эта обработка разбивается на два последовательных компонента, которые мы назвали Map Engine и Tree Engine. Map Engine преобразует необработанные изображения в многослойные карты садов с географической привязкой. Tree Engine использует компьютерное зрение для поиска отдельных деревьев на картах с географической привязкой и извлечения информации по каждому дереву (метрики включают состояние, высоту, объем, площадь). Затем клиент может войти в наше веб-приложение Aeroview и может просматривать свои данные и действовать с ними с помощью инструментов, которые мы предоставляем.

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

Как выглядел наш бэкэнд в конце 2017 года?

Для некоторого контекста, каким был наш масштаб на конец 2017 года: мы обработали кумулятивную сумму (за 3 года) в 33 000 гектаров, включая автоматическое определение местоположения и анализ 2,5 миллионов деревьев.

Я упростил серверную часть на 4 основные области ниже:
Общая инфраструктура, API, Map Engine и Tree Engine .

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

API
У нас был один сервер Django (Python 2.7), работающий на AWS Elastic Beanstalk, подключенный к внешней базе данных PostgreSQL, размещенной на Amazon RDS. Это обрабатывало каждый вызов API вместе с различными заданиями, которые выполнялись ежедневно (с использованием Django Celery).

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

В дополнение к этому, если возникнут проблемы с развернутым новым кодом и сервер выйдет из строя, это повлияет на все остальные приложения / процессы в бизнесе - из-за нашей монолитной реализации. В то время мы не использовали стандартные принципы REST, с этим можно было бы справиться с помощью фреймворка, такого как Django Rest Framework.

Map Engine
Каждый раз, когда завершалась загрузка необработанных изображений полета дрона, запускалась обработка данных. Вычислительный экземпляр c4.xlarge AWS EC2 будет запускаться, загружать все изображения и последовательно соединять каждый сад, выбранный при загрузке. Оглядываясь назад, можно сказать, что это было ужасно неэффективно с точки зрения распараллеливания, потому что загрузка, содержащая 50 садов необработанных изображений, потребовала бы в 50 раз больше времени для обработки, чем загрузка, содержащая только 1 фруктовый сад. Другая проблема заключалась в том, что каждый раз, когда мы хотели обновить код экземпляра, нам приходилось выполнять удаленный вход в существующий экземпляр, исправлять код и затем создавать новый базовый образ.

Tree Engine
Модели машинного обучения были обучены в ML Engine от Google. Программное обеспечение с открытым исходным кодом Pachyderm, которое взаимодействовало с Kubernetes, затем использовалось для выполнения логического вывода на контейнерах Docker, связанных с этими моделями.

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

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

Итак, на чем мы сосредоточились в первой половине 2018 года?

Январь дал мощный старт. Мы присоединились к 24 другим стартапам в Сан-Франциско, чтобы принять участие в программе Google Launchpad Accelerator. Мы общались с некоторыми из самых ярких умов и получили потрясающее наставничество по всем направлениям. С технической точки зрения мы узнали состояние, но самое главное - как правильно думать о проблемах, которые мы пытались решить. Атмосфера, интенсивность и уровень инноваций в Сан-Франциско вдохновляли.

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

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

  1. Что мы собираемся разделить на микросервисы?
    ~ Мы попытались выделить компоненты, которые сильно различались, а затем разделить их. Например: аутентификация пользователя и базы данных была отделена от функций геопространственных вычислений и cronjobs.
  2. Как мы собираемся запускать эти микросервисы?
    ~ Kubernetes. С небольшой помощью моего друга Спинакер (созданный в Netflix). Также нам понадобится сервер сборки и тестирования - Jenkins.

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

Общая инфраструктура

  • Весь внутренний код был переработан для работы внутри контейнеров Docker (Python 3.6) - это требование для всех будущих разработок. Docker позволяет нам разрабатывать код локально и иметь стопроцентную уверенность в том, что код будет работать в той же среде в производственной среде.
  • Кластеры Kubernetes (управляемые Google Kubernetes Engine) были созданы для работы всех наших контейнеров Docker.
  • Непрерывная интеграция - сервер Jenkins был развернут для создания бэкэнд-контейнеров / пакетов Python, запуска модульных тестов и развертывания интерфейсных приложений в производственной среде.
  • Непрерывное развертывание - Spinnaker был настроен для управления всем, что работает в Kubernetes. Поистине потрясающее программное обеспечение с открытым исходным кодом - я настоятельно рекомендую его всем, кто хочет улучшить свое использование Kubernetes. Спинакер - это, по сути, абстракция Kubernetes. Это позволяет нам настраивать конвейеры данных и стратегии развертывания через простой пользовательский интерфейс, а затем Spinnaker создает различные манифесты в Kubernetes; позволяя Kubernetes делать то, что у него получается лучше всего - управлять контейнерами и обрабатывать масштабирование.

API
Наш монолитный сервер был преобразован в 4 микросервиса на основе Django (Python 3.6 с Django Rest Framework) с автоматически созданной документацией по API Swagger, которая постоянно доставляется в Kubernetes через Spinnaker.

Веб-трафик направляется к каждой из служб с использованием контроллера входящего трафика Kubernetes вместе с certbot для получения нового сертификата SSL от letsencrypt один раз в месяц.

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

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

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

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

Подходит к концу 2018 год ... Принесите данные!

По мере приближения конца года наш бизнес продолжал расти. Лидеры собирались в результате различных маркетинговых кампаний - мы организовали мероприятие Future of Farming, которое проводилось одновременно в 9 местах по всей Южной Африке, с прямой трансляцией друг к другу. Команда продаж занималась твердой почвой по всем потенциальным клиентам; и вообще было довольно много положительного шума в средствах массовой информации, окружающих Aerobotics.

Map Engine на этом этапе еще не был преобразован в контейнеры Docker, обслуживаемые Spinnaker, поэтому обработка данных была неэффективной и медленной. Был период, когда мы изо всех сил пытались получить данные за 3 недели, не говоря уже о 3 днях.

Как только у нас наконец появился новый Map Engine, было выпущено основное узкое место. Если бы мы взяли 10 образцов загрузок, каждая из которых состояла из 50 фруктовых садов - вместо 10 экземпляров EC2, работающих и последовательно обрабатывающих сад за садом, 500 модулей (по сути, 500 экземпляров параллельно) теперь будут запускаться в Kubernetes одновременно, каждый сшивает одиночный фруктовый сад. Время запуска каждого экземпляра несущественно по сравнению с обработкой, поэтому стоимость использования 500 экземпляров в течение часа каждый практически равна стоимости запуска 10 экземпляров в течение 50 часов каждый.

На одном этапе мы обрабатывали данные на процессорах 1600 в общей сложности с 7 ТБ ОЗУ. Что может быть немного по сравнению с некоторыми технологическими гигантами, но по сравнению с тем, где мы были в 2017 году - это было огромно!

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

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

2018 год был для нас американскими горками, особенно ближе к концу, но он загнал нас в глубокий конец, и часто именно здесь мы процветаем. Мы обработали 45 000 гектаров и проанализировали 13 миллионов деревьев (в 6 раз больше деревьев, чем за предыдущие 3 года вместе взятые). В ближайшие пару месяцев в систему будут поступать тысячи гектаров различных культур. Это подтолкнет технологию к новым пределам и протестирует нас в масштабе, который мы никогда раньше не испытывали, но мы подходим к стадии, когда мы можем справиться с этим.

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

Что нас ждет в 2019 году?

Я не особо много говорил об искусственном интеллекте / машинном обучении, потому что в 2018 году многие наши новые продукты AI / ML находились на стадии исследования и тестирования и еще не были полностью запущены в производство.

В этом году ситуация сильно изменится, и есть много чего ожидать. Вот несколько:

  • Автоматическая идентификация дерева проблем на основе визуальных образов
    ~ Простой ответ «да» или «нет» на вопрос, есть ли в дереве проблемы или нет. На основе изображений (визуальных и мультиспектральных) и контекстной информации (временной, пространственной и сезонной)
  • Точная идентификация вредных организмов по крайней мере для одной культуры и типа вредителей
    ~ Заражение трипсами скоро станет управляемым
  • Повышенная точность показателей деревьев
    ~ Мы постоянно работаем над улучшением данных для наших уважаемых производителей
  • Универсальное мобильное приложение Aerobotics In-Field
    ~ Объединение наших мобильных функций в единое приложение для работы в поле

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