В Dwelo мы написали код для наших шлюзов Интернета вещей на Rust. Это быстро, надежно и безопасно. Но мы начали не с Rust, и мы не писали код за выходные. В этой серии рассказывается о том, где мы были год назад, как мы перешли на Rust и почему вы можете подумать о том, чтобы сделать то же самое. Мы рассмотрим причины использования Rust (или нет!), Многопоточность, аппаратное взаимодействие, бесстрашный параллелизм, взаимодействие с библиотеками C, написание библиотеки MQTT с нуля и уроки, которые мы извлекли на собственном горьком опыте.

Это первая публикация из серии из 5 статей. Вы можете прочитать Часть II здесь и Часть III здесь.

Год назад я присоединился к стартапу IoT с горой устаревшего кода Python, работающего на Raspberry Pi. В течение нескольких лет этот код, как и большинство кодовых баз, разросся органически. Первоначальная цель этого кода состояла в том, чтобы контролировать канал команд MQTT, декодировать и выполнять команды в сети Z-Wave через последовательный порт и сообщать об успехе или неудаче через другой канал команд. Кроме того, код был предназначен для передачи информации об общем состоянии системы и состоянии устройств, подключенных к сети Z-Wave. Где-то по пути программное обеспечение метастазировало для управления светодиодами состояния и управления сотовым модемом через отдельный последовательный порт, а также для связи со встроенным программным обеспечением для управления выпусками.

Старший инженер-программист на моих собеседованиях отчаянно хотел все это переписать, и я покидал магазин C ++, который спокойно двигался вперед на фоне прежних успехов. Спойлеры: он хотел переключить существующий код Python на Rust, и эта перспектива была настолько захватывающей, что я бросил свою прежнюю работу и переехал в города.

Но прежде чем мы перейдем к разговору о том, почему мы выбрали Rust или почему это интересно, почему мы вообще решили переписать? Расхожее мнение гласит никогда не переписывать программное обеспечение, когда у вас есть что-то, что уже работает, даже частично. Но если бы мы следовали этой логике, мы бы по-прежнему использовали программное обеспечение Apollo Guidance Computer в будущих космических миссиях (эй, архитектура является дополнением к 1, но последний отчет об ошибке был в 1969 году, так что он должен быть надежным.) Зачем что-то переписывать, Когда-либо?

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

  • С архитектурной точки зрения существующая архитектура не могла масштабироваться до других технологий или менять направление без огромных усилий. Компания только что была вынуждена перейти на MQTT от другого поставщика IaaS из-за соображений стоимости лицензирования, и переход занял почти год. С выпуском новых устройств каждый год (например, BLE, Wifi, Z-Wave, Zigbee, произвольные REST API) бизнес хочет иметь возможность быстро менять стеки IoT для адаптации к новым технологиям.
  • Были проблемы технического долга, которые никто не понимал или не собирался решать. (Я упоминал, что ни один из первоначальных программистов еще не исправил ошибки или не ответил на вопросы?) Устранение очевидных проблем в одном месте часто приводило к нарушению программы в совершенно несвязанных частях кода.
  • В программе были местами модульные тесты, но не было стандартов кодирования - чей-то «очень умный» конечный автомат выражения генератора управлял протоколом последовательного кадрирования, но потребовались недели, чтобы выяснить, почему он был нарушен.
  • Повсюду был мертвый код, но мы не могли доказать, что это действительно мертвый код.
  • Святая корова, жуки. Я упоминал об ошибках?
  • Существовали возможности заменить подверженный ошибкам исходный код обработчика Python Z-Wave эталонной реализацией, предоставленной поставщиком, написанной на C. Было бы больше усилий взломать существующую реализацию Python вокруг библиотеки C, чем просто переписать вещь.
  • Мы хотели привлечь больше клиентов на более дешевое оборудование. Улучшение этого соотношения напрямую ведет к увеличению прибыли для бизнеса.

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

  • Ему нужно говорить на C и работать с библиотеками C.
  • Есть требования к времени (из-за последовательной связи).
  • Нам нужно иметь возможность запускать его на картофеле (из-за стоимости).
  • Он должен иметь возможность одновременно без ошибок запускать как последовательную связь, так и набор команд / телеметрии.
  • Строковые манипуляции должны быть простыми, потому что все команды и ответы - это JSON.
  • Программное обеспечение должно работать правильно и детерминированно, даже если мы не все гениальные программисты.
  • Это должно быть безопасно.

Как оказалось, Rust отвечал всем требованиям.

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

Почему вы можете не захотеть использовать Rust

  • Если вам нужно быстрое прототипирование и вам нужно делать что-то, ориентированное на пользователя, существует миллиард JS-фреймворков. Электрон на самом деле довольно быстр в наши дни, если у вас достаточно памяти.
  • Если вам нужно быстрое прототипирование и вам нужны цифры для науки, вам, вероятно, понадобится Python. Прекратите тратить деньги на Matlab и сэкономьте деньги на гранты для старшекурсников. Поторопитесь, темная энергия не решится сама собой.
  • Если вы пытаетесь написать потоковое бэкэнд-программное обеспечение на стандартном оборудовании, подумайте о Go или, возможно, Kotlin, если вам нужна инфраструктура библиотеки JVM.
  • Иногда сценарий оболочки просто прекрасен!

Однако, если вы являетесь человеком, пишущим код вместе с другими людьми и чувствуете, что вам нужно написать новый код на C / C ++ (скорость, ограничения ресурсов, временные ограничения, переносимость), вам следует серьезно подумать о написании его на Rust .

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

Переходите к Части II или Части III.