Этот пост о переходе с PHP на Go был впервые опубликован в другом месте и переиздан здесь с разрешения автора.
Ранее в этом году я принял возможно плохое деловое решение. Я решил переписать приложение Laravel, включающее Boxzilla в Go .
Хотя не жалею.
Через несколько недель я развернул приложение Go. Создание этого было самым забавным, что у меня было за несколько месяцев, я выучил тонну, и конечный результат — огромное улучшение по сравнению со старым приложением. Лучшая производительность, простота развертывания и более высокий охват тестированием.
Приложение представляет собой довольно простую управляемую базой данных область API и учетную запись, где пользователи могут войти в систему, чтобы загрузить продукт, просмотреть свои счета или обновить способ оплаты.
Stripe и Braintree используются для приема платежей по подписке. Счета обрабатываются с помощью MoneyBird, а некоторые транзакционные электронные письма отправляются с помощью Mailgun .
Хотя Laravel работал достаточно хорошо для этого, некоторые вещи всегда казались мне слишком сложными. И что с выпуском новой «основной» версии каждые несколько месяцев? Было бы неплохо, если бы новые версии содержали значительные улучшения, но во многих случаях мне казалось, что незначительные изменения имен и структуры каталогов меняют.
Зачем идти?
В прошлом году я перевел несколько сервисов на Go, поэтому я не был совершенно новым для этого языка. Как разработчик, продающий продукты на основе WordPress, часть моей работы — работа в древнем техническом стеке, который в основном ориентирован на конечного пользователя.
Если бы я не работал не по найму, я бы просто подал заявку на новую работу, чтобы восполнить недостаток сексуальных технологий. Будучи моим собственным боссом, я обязан сделать так, чтобы моя повседневная работа была интересной, а не просто преследовал более неотложных $$$. Если доход позволяет (и это делает), почему бы не повеселиться?
Писать код на Go — это радость, инструменты потрясающие и не только быстро развивающиеся, но и конечный результат, как правило, тоже безумно быстр. Просто чтение о цели проекта Go продало меня на языке.
Я думаю, что в ближайшие несколько лет мы увидим, как много людей перейдут с динамически типизированных языков, таких как PHP, Python и JavaScript, на Go.
Портирование кодовой базы
Перенос кода на Golang состоял в основном из правильного взаимодействия с базой данных и переноса шаблонов Blade в то, что мы могли бы использовать в Go.
ORM — это одна вещь, которая всегда мешает мне, поэтому я выбрал фиктивный слой доступа к данным и простые SQL-запросы. Meddler использовался, чтобы избавиться от некоторых шаблонов для сканирования результатов запросов в структуры.
Для поддержки иерархических шаблонов и частичных функций я использую grender с открытым исходным кодом , крошечную оболочку стандартного пакета html / template Go. Это позволило мне с относительной легкостью портировать файлы шаблонов Blade на Go, поскольку я мог использовать ту же иерархическую структуру и частичные шаблоны.
Для интеграции с Stripe существует официальный пакет stripe-go . Для Braintree существует неофициальный пакет braintree-go , который некоторое время игнорировался, но в последнее время привлек к себе повышенное внимание. Поскольку в Moneybird еще не было пакета Go для управления счетами, я создал и получил открытый исходный код moneybird-go .
Сравнение яблок и апельсинов
Поскольку Go — это скомпилированный язык с гораздо лучшей стандартной библиотекой, чем PHP, не совсем справедливо сравнивать эти два языка, как я собираюсь. Тем не менее, я думал, что было бы интересно поделиться некоторыми цифрами.
Производительность
wrk использовался для выполнения нескольких простых тестов HTTP для обоих приложений, возвращающих HTML-код для страницы входа в систему.
совпадение | Avg. задержка | Треб / сек | Передача / сек | |
---|---|---|---|---|
Laravel | 1 | 3.87ms | 261,48 | 1.27MB |
Laravel | 100 | 108.86ms | 917,27 | 6.04MB |
Идти | 1 | 325.72μs | 7365,48 | 34.27MB |
Идти | 100 | 11.63ms | 19967,31 | 92.91MB |
Идти | 200 | 37.68ms | 22653,22 | 105.41MB |
К сожалению, приложение Laravel (или сокет PHP-FPM) продолжало падать, как только я увеличил количество одновременных «пользователей» за 100.
NetData предоставила следующие графики, чтобы увидеть, как сервер выдерживал всю эту нагрузку.
Голанг с 100 одновременными соединениями
Laravel с 100 одновременными подключениями
Обратите внимание, что я запускал тест с того же компьютера, на котором работали приложения, так что это сильно влияет на оба графика.
Строки кода
Давайте сравним строки кода в обоих приложениях, включая все зависимости от поставщиков.
find . -name '*.php' | xargs wc -l
156289 total
Версия Laravel состоит из чуть более 156 000 строк кода. Это исключает зависимости разработки, которые, с Laravel, необходимы для запуска тестов и т. Д.
find . -name '*.go' | xargs wc -l
33624 total
Версия Golang, с другой стороны, состоит из 33 000 строк кода. Это одна пятая часть кода для точно такой же функциональности.
Давайте исключим внешние зависимости в приложении Laravel, чтобы мы знали, сколько строк на самом деле было написано мной.
find . -name '*.php' -not -path "./vendor/*" | xargs wc -l
13921 total
И для Голанга.
find . -name '*.go' -not -path "./vendor/*" | xargs wc -l
6750 total
Результат немного больше, даже если просто смотреть на управляемые строки кода. Тем не менее, это точно такое же приложение с половиной кода.
Тестовое покрытие
Тестирование является первоклассным гражданином в Голанге, и тестовые файлы находятся рядом с реальными исходными файлами.
license.go
license_test.go
subscription.go
subscription_test.go
Это делает невероятно удобным применение тестовой разработки.
В нашем приложении Laravel у нас были в основном интеграционные тесты, которые проверяли, вернул ли обработчик запросов правильный ответ. Общее тестовое покрытие было довольно низким, в основном из-за жесткой связи, что, в свою очередь, было моей ошибкой Написание того же приложения во второй раз действительно помогает и здесь.
TLDR
Я сделал то, что вы никогда не должны делать: переписал приложение на другом языке, потому что мне так хотелось. Было очень весело, и взамен я получил гораздо меньшее и быстрое приложение.