Переписывание службы на другом языке никогда не бывает мелочью и всегда сопряжено с риском. Тем не менее, мы решили, что оно того стоило. Вот наша история об отказе от Ruby реализации Cloud Foundry Bits-Service и переписывании ее на Go.

Проблемы с реализацией Ruby

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

Мы использовали Sinatra в качестве фреймворка для Ruby Bits-Service. К сожалению, мы не смогли найти способ использовать правильную инъекцию зависимостей с этим фреймворком. Следовательно, реализация требовала некоторых действительно глупых проверок значений конфигурации для каждого запроса, что казалось очень плохим с точки зрения производительности. Мы решили, что нам нужно перейти на другую платформу, которая позволит нам вводить значения конфигурации.

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

Сервис Ruby требовал nginx в качестве интерфейса. Первоначально это было необязательным, но со временем это стало жесткой зависимостью. К сожалению, nginx был частью версии Bits-Service BOSH, а не самой Bits-Service. Итак, чтобы запустить Bits-Service, нам пришлось танцевать BOSH, т.е.

bosh create-release
bosh upload-release
bosh deploy manifest.yml

Ожидание этого конца может лишить мотивации кого угодно.

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

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

Повторная реализация

Вместо этого мы решили реализовать его заново. - Ладно, это не совсем так. Он у нас уже был готов. В основном. За исключением нескольких мелких особенностей. Небольшая побочная история здесь заключается в том, что я давно хотел исследовать фреймворки веб-сервисов для Go и подумал, что Bits-Service будет действительно хорошим реальным примером для этого (Gorilla mux + Negroni способ).

Итак, у нас была почти готовая повторная реализация Bits-Service, и мы решили ее использовать.

Со стороны может показаться, что мы отказываемся от проверенной в боях реализации Ruby в пользу незрелой реализации Go. Однако это не так. Хотя реализация Ruby существовала около двух лет, она использовалась только в тестовых средах, а не в производственных. Те же самые тестовые среды теперь используются для тестирования версии Go. Мы сохранили все тесты системного уровня и CAT.

Расплачиваться

Это принесло несколько больших преимуществ:

  • Скорость! В GET запросах реализация Go в 1000 раз быстрее при одновременной загрузке службы. Мы не делали никаких конкретных оптимизаций производительности.
  • Половина потребления памяти (300–400 МБ вместо 1 ГБ).
  • Мы получили то, что @ nparsons08 называет Причиной 6 - Возможность создать команду.
  • Проблемы, описанные в статье Переход от Scala к работе и почему мы не вернемся назад, существуют и в базах кода Ruby. И они у нас были. Понимание того, откуда волшебным образом берутся определенные методы, далеко не простое.
  • Мы отказались от протекающей туманной абстракции, существовавшей в версии для Ruby, и предоставили четко определенные свойства.

Заключение

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

В восторге от всего Cloud Foundry и хотите узнать больше о Bits-Service? Bits-Service разрабатывается в IBM-Lab Boeblingen, Германия, и мы обычно размещаемся на cloudfoundry.slack.com в # bits-service. Приходите и поговорите с нами!