diff --git a/README.md b/README.md index dc2a89e..579eaa6 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,8 @@ Algorithm、Review、Tip、Share |week32|[Java8并发操作可没有它看起来那么简单](./week32/review/Java8并发操作可没有它看起来那么简单.md)| |week33|[C++中的虚基类](./week33/review/C++中的虚基类.md)| |week34|[Java传值和传引用](./week34/review/Java传值和传引用.md)| -|week35|[Linux中可清除的内存分配](./week35/review/Linux中可清除的内存分配.md) +|week35|[Linux中可清除的内存分配](./week35/review/Linux中可清除的内存分配.md)| +|week36|[Go和Services等于一个巨大的项目](./week36/review/Go和Services等于一个巨大的项目.md)| ## Tip diff --git "a/week36/review/Go\345\222\214Services\347\255\211\344\272\216\344\270\200\344\270\252\345\267\250\345\244\247\347\232\204\351\241\271\347\233\256.md" "b/week36/review/Go\345\222\214Services\347\255\211\344\272\216\344\270\200\344\270\252\345\267\250\345\244\247\347\232\204\351\241\271\347\233\256.md" new file mode 100644 index 0000000..b39b9a3 --- /dev/null +++ "b/week36/review/Go\345\222\214Services\347\255\211\344\272\216\344\270\200\344\270\252\345\267\250\345\244\247\347\232\204\351\241\271\347\233\256.md" @@ -0,0 +1,82 @@ +# Go和Services等于一个巨大的项目 + +[Go + Services = One Goliath Project](https://engineering.khanacademy.org/posts/goliath.htm) + +可汗学院打算付出巨大的努力来用Go重构服务端到现代技术栈。 + +在可汗学院,我们从来没有逃避挑战。我们带着使命给所有人、所有地方提供一个非营利性的“免费的世界一流的教育”。挑战不会比这大得多。 + +我们的任务要求我们创建和维护软件用来提供工具来帮助教师和教练用来训练学生,和在学校内外的个性化的学习经验。在过去的十年以来,每月都有成千上万的人依赖我们的服务器来提供各种各样的特性。 + +在技术上十年是很长的时间。我们选择Python作为我们后端语言并且成为了我们的生产选择。当然,十年前选择Python2是因为Python3还非常新并且支持的也不好。 + +## Python2生命的尽头 + +现在,在2019年,Python3版本优势非常明显,Python软件基金会也提出[Python2在2020年1月1日将完成使命](https://www.python.org/doc/sunset-python-2/),因此他们将在有限的时间内聚焦于新特性。无疑,这依然有数百万行Python2的代码在那,但是事实已经无可否认。Python2就要离去了。 + +从Python2迁移到Python3可不是一件容易的事情。越过障碍,在其他的地方也有广泛的应用,我们还有一堆其他API在库文件中,发生了巨大的变化。 + +这些不同意味着我们需要将代码分布到至少两个服务(旧版本的Python2代码库和新替换的Python3),在过渡期共存。 + +这样所有的工作,我们将获得这些好处: + +1. 后端服务端程序性能可能有10%-15%的提升 +2. Python3的语言特性 + +## 其他语言 + +鉴于所需的所有工作和相对较少的收益,我们想考虑其他选择。他的性能优势可以为我们节省钱,我们可以通过其他方式将其应用来帮助世界各地的人们学习。如果我们从Python迁移到速度更快一个数量级的语言,我们既可以提高网站的响应速度,也可以大大降低服务器成本。 + +迁移到Kotlin是一个吸引人的选择。在此期间,我们决定深入的了解其他选择。查看在Google App Engine中具有一流支持的语言,出现了另外一个强大的竞争者:Go。Kotlin是一个非常具有表现力的语言,具有令人印象深刻的特性。另一边,Go提供了简单性和一致性。Go团队致力于开发一种可以帮助团队长期可靠的发布软件的语言。 + +当个人编写代码时,由于Go闪电般的编译速度,可以让我们快速的迭代。此外,我们的团队成员拥有多年的经验,并围绕不通的编辑器建立了肌肉记忆。与Kotlin相比,Go可以更好的支持更多的编辑器。 + +最后,我们围绕性能做了一系列测试,发现Go和Kotlin(在JVM上)的性能相似,其中Kotlin可能领先百分之几。但是,Go使用的内存少得多,这意味着可以减少实例。 + +我们仍然喜欢Python,但是Go带给我们的巨大的性能差异不能忽视,并且我们认为多年来我们能够更好的支持在Go上运行的系统。无疑,向Go迁移比起Python3要付出更多的努力,但是仅凭性能方面的胜利就值得。 + +## 从整体服务 + +除了少数例外,我们的服务历来都运行相同的代码,并且可以响应可汗学院任何部分的请求。我们使用单独的服务来存储数据和管理缓存,但是任何请求的逻辑都可以通过我们的代码轻松跟踪,并且无论哪个服务响应,逻辑都是相同的。 + +当一个函数调用另一个函数时,这些调用非常可靠且非常快。这是整体的基本优势。一旦将逻辑分解成服务后,你将在代码的各个部分放下更慢、更脆弱的边界。你还必须考虑将如何进行通讯。你是否在两者之间放置发布/订阅总线?直接进行HTTP还是gRPC调用?通过某些网关转发? + +即使意识到这种增加的复杂性,我们也将整体拆分为服务。这有一定的必要性,因为新的Go代码必须至少与现在的Python分开的流程中运行。 + +服务的复杂性增加了许多好处: + +- 通过拥有更多可以独立部署的服务,部署和测试可以针对单个服务更快的进行移动,这意味着工程师将能够花费更少的时间在部署活动上。这也意味着他们能够在需要时更快的获取更改。 +- 我们可以更加放心,部署问题对站点的其他部分的影响有限。 +- 通过拥有单独的服务,我们还可以选择每种服务所需的正确种类的实例和托管配置,这有助于优化性能和成本。 + +我们发布了一系列博客文章,介绍了我们如何对Python代码进行重大重构,绘制边界以及围绕哪些代码可以导入其他代码创建约束。这些界限为思考如何将代码拆分为服务提供了一个起点。Craig Silverstein和Ben Kraft进行了努力,以找出一套最初的服务以及我们如何适应他们之间的界限。在我们当前的整体中,代码可以自由读取和更新所需的任何数据模型。为了让这一切保持理智,我们制定了一些有关通过服务访问数据的规则,但这又是另外一个话题。 + +## 清理房间 + +在技术上十年是一个很长的时间。GraphQL在2009年不存在,两年前,我们决定将所有HTTP GET API迁移到GraphQL,后来决定也采用GraphQL变动。在React出现后,我们也引入了React到我们的许多web前端。Google Cloud发布了很多特性。服务器体系结构已朝着可独立部署的服务方向发展。 + +对于产品来说十年也是一个很长的时间。我们引入了数量惊人的功能,其中一些功能如今使用很少。我们的某些较早功能是使用我们认为不在适合我们的最佳实践的模式构建的。 + +我们将使用Python进行大量的房屋清理工作。我们非常了解第二系统的影响,我们开展这个工作的目的不是创建完美的系统,而是使其更容易的迁移到Go上。我们较早的开始了其中一些技术迁移,其中一些将继续运行到我们切换到Go的时间点,但最终的结果将会更加现代和连贯。 + +- 我们将会使用React服务端渲染生成网页,从而消除我们一直使用的Jinja服务端模板。 +- 我们将使用GraphQL联合将请求分发到我们的服务(以及过渡期间的旧Python代码)。 +- 在需要提供REST端点的地方,我们将通过网关将请求转换为GraphQL。 +- 我们将更加依赖我们的CDN提供商Fastly,以使更多的请求能够更快的服务于更接近我们的用户,而无需我们的服务器基础架构完全处理该请求。 +- 我们将弃用一些未使用的、过时的功能,这些功能会带来持续的维护负担,并且会拖慢我们的前进速度。 + +我们可能还需要修复其他问题,但是我们正在做出选择,最终将帮助我们更快、更安全的完成项目。 + +## 不变的是什么 + +到目前为止,我所描述的这一切都是巨大的变化,但是很多事情我们都没有改变。我们将尽可能的将逻辑从Python移植到Go,只需确保完成后代码看起来像惯用的Go。 + +从第一天开始,我们就一直在使用Google App Engine,它对我们来说运行良好,并随着我们的成长而自动扩展。因此,我们将继续为新的Go服务使用App Engine。我们将使用Google Cloud Datastore用作该网站的数据库,并且保持不变。这也适用于我们使用其他各种Google Cloud服务,这些服务表现良好并且可以满足我们的需求。 + +## 计划 + +截止2019年12月,我们在Apollo GraphQL网关之后的生产环境中运行了第一批Go服务。这些服务今天很小,因为我们进行迁移的方式使用很小的增量。增量切换是另一个要讨论的话题(订阅我们的RSS Feed或者Twitter账户,以在新帖子上线时阅读他们)。 + +对于我们来说,2020年将充满技术挑战和机会:使用Go将基于Python的大型整体项目转换为基于GraphQL的服务。我们对这个名为Goliath的项目感到非常兴奋(您可以想象我们考虑过的所有“Go-”名称)。这是十年一次的革命性机遇,以及我们践行“质量至上”的工程原理的一个重要例子。 + +如果您对此感兴趣,请查看我们的招聘页面。您可以想象,我们也正在招募工程师!