Переписывание службы на другом языке никогда не бывает мелочью и всегда сопряжено с риском. Тем не менее, мы решили, что оно того стоило. Вот наша история об отказе от 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. Приходите и поговорите с нами!