【译】从PHP(Laravel)迁移到Go

共 2601字,需浏览 6分钟

 ·

2020-12-26 15:11

今年早些时候,我做出了一个糟糕的商业决定,我决定用Go重写Laravel应用Boxzilla,虽然没有遗憾,最后效果惊人。

    仅仅几个星期后我就部署了Go应用程序。构建它是我几个月来最有趣的事情,我学到了很多东西,最终结果是对旧应用程序的巨大改进、更好的性能、更容易的部署和更高的测试覆盖率。

    该应用程序是一个相当简单的数据库驱动的API和包含帐户管理等应用程序,用户可以在登录以后下载产品,查看发票或更新付款方式。

    Stripe和Braintree用于接受订阅付款。发票使用MoneyBird处理,一些事务性的电子邮件使用Mailgun发送。

    虽然Laravel在这方面做得足够好,但有些事情总是让我感到过于复杂。每隔几个月发布一个新的“主要”版本,如果新的版本包含重大改进,我心里也会觉得这没什么,但是很多时候,感觉都是一些非常简单的改动,例如命名和目录结构进行了更改。

Why Go?

    去年,我已经将几种服务转移到了Go上,所以我对这种语言并不是完全陌生。作为销售基于WordPress的产品的开发人员,我的一部分工作是在一个古老的技术堆栈中工作,该堆栈主要关注最终用户。

如果我不是自雇人士,我会简单地申请一份新工作来弥补这种缺乏性感技术的现象。作为我自己的老板,我有责任使自己的日常工作变得有趣,而不仅仅是追逐更多的即时资金。如果收入允许(并且确实如此),为什么不找点乐子呢?

编写Go代码很高兴,工具很棒,不仅开发速度快,而且最终结果通常也很快。刚读完Go项目的目的(https://golang.org/doc/faq#What_is_the_purpose_of_the_project),就使我对语言产生了浓厚的兴趣。

我认为我们会在未来几年内看到大量人从动态类型的语言(如PHP,Python和JavaScript)切换到Go。

移植代码库

将代码迁移到Go中主要包括正确地进行数据库交互以及将Blade模板移植到我们可以在Go中使用的东西。

ORM总是会阻碍我的一件事,因此我选择了可模拟的数据访问层和简单的SQL查询。使用Meddler摆脱了一些烦恼:将查询结果映射到结构体中。

为了支持分层模板和局部,我开源了grender(https://github.com/dannyvankooten/grender),这是基于Go的标准库html / template包的一个小包装。这使我可以相对轻松地将Blade模板文件移植到Go中,因为我可以使用相同的层次结构和部分模板。

为了与Stripe集成,有官方的Stripe -Go(https://github.com/stripe/stripe-go)软件包。对于Braintree,有一个非正式的braintree-go(https://github.com/lionelbarrow/braintree-go)软件包,该软件包被忽略了一会儿,但最近又受到了新的关注。由于到目前为止,在Moneybird中还没有Go软件包来管理发票,因此我构建并开源了moneybird-go(https://github.com/dannyvankooten/moneybird-go)

对比分析

由于Go是一种编译语言,具有比PHP更好的标准库,因此像我将要比较的那样比较这两种语言并不是很公平。就是说,我认为分享一些数字会很有趣。

性能

wrk用于为两个返回登录页面HTML的应用程序执行一些简单的HTTP基准测试。

 并发平均 潜伏要求/秒传输/秒
Laravel13.87ms261.481.27MB
Laravel100108.86ms917.276.04MB
Go
1325.72μs7365.4834.27MB
Go10011.63ms19967.3192.91MB
Go20037.68ms22653.22105.41MB

不幸的是,一旦我将并发“用户”的数量增加到100以上,Laravel应用程序(或PHP-FPM套接字)就一直崩溃。

NetData提供了以下图表,以查看服务器在所有这些负载下的承受能力。

100个并发连接的Go程序

100个并发连接的Laravel 程序

请注意,我在运行应用程序的同一台计算机上运行了基准测试,因此这会严重影响两个图表。

代码行数

让我们比较两个应用程序中的代码行,包括所有的依赖项。

$ find . -name '*.php' | xargs wc -l
156289 total

Laravel版本包含超过156.000行代码。这还不包括要运行Laravel测试等相关的开发依赖包。

$ find . -name '*.go' | xargs wc -l
33624 total

另一方面,Go版本包含33.000行代码。这是完全相同功能的代码的五分之一。

让我们在Laravel应用程序中排除外部依赖关系,以便知道我实际写了多少行php。

$ find . -name '*.php' -not -path "./vendor/*" | xargs wc -l
13921 total

多少行Go

$ find . -name '*.go' -not -path "./vendor/*" | xargs wc -l
6750 total

即使仅查看托管代码行,结果也要稍微多一些。尽管如此,它还是只使用了原来完全相同的应用程序的一半代码

测试范围

测试是Go中的头等公民,测试文件紧邻实际源文件存在。

license.go
license_test.go
subscription.go
subscription_test.go

这使得应用测试驱动的开发变得异常方便。

在我们的Laravel应用程序中,我们主要进行了集成测试,以检查请求处理程序是否返回正确的响应。总体测试覆盖率很低,主要是由于紧密耦合,而这又主要是我的错。再次编写相同的应用程序确实也有帮助。

TLDR

做了一些您不应该做的事情:用另一种语言重写应用程序,因为我感觉很喜欢。获得了很多乐趣,并且得到了更小,更快的应用程序。

浏览 50
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报