写点什么

通过基于 Go 的微服务框架 goa,实现对服务 API 的定义、审查与实现

  • 2016-01-05
  • 本文字数:3755 字

    阅读完需:约 12 分钟

Raphael Simon 是来自于 RightScale 的一位高级系统架构师,他创建了一种基于 Go 语言的 HTTP 微服务框架,名为“goa”。这一框架允许开发者通过领域特定语言(DSL)定义服务的API,并且通过自动代码生成功能创建“样板”式的服务端和客户端代码以及文档。

Raphael 在他的博客 Gopher Academy 上发表了一篇介绍 goa 框架的帖子,他提到 RightScale 的工程师团队正在将一个一体性的 Ruby on Rails 应用迁移为一系列基于 Go 语言创建的微服务应用。这次迁移工作的一个主要挑战在于如何创建设计良好的服务 API,为了支持整个微服务 API 的设计、审查以及实现,他们创建了一系列的工具。这一项目所产生的结果之一就是基于 Go 语言的框架 goa 的诞生,它的出现受到了在 RightScale 中所应用的一个基于 Ruby 的 API 开发框架 Praxis 的启发。

InfoQ 与 Simon 进行了一次访谈,他既是 RightScale 的高级系统架构师,也是 goa 的主要贡献者之一。这次访谈主要问及了关于goa 这一微服务框架的设计目标、使用方式以及未来的发展计划。

InfoQ:欢迎你 Raphael!请你为读者说明一下“goa”是个怎样的产品,以及创建这一架构的动力是什么。

Simon:RightScale 正在向微服务风格的架构进行迁移,这项工作已经开展了一段时间了,而最近一段时间团队开始使用 Go 语言编写部分服务。总体来说,无论在开发还是运维方面,Go 都证明了它是一个优秀的选择。这门语言很容易上手,并且所创建的服务表现也很出色。

不过,采用 Go 语言进行开发也意味着在开发与部署阶段要引入一种新的技术栈,因为直至最近,RightScale 基本上都是使用 Ruby 进行开发的。团队在创建与运行 REST API(RightScale 已经将这一使用 Ruby 语言打造、用于创建 REST API 的 Praxis 框架开源了)方面已经具备了丰富的经验。由于目前还没有一种现成的解决方案可以应对我们的需求,因此有理由运用这些经验去打造基于一种 Go 语言的服务开发栈。

这项工作的成果就是 goa 的诞生,它是一个微服务的开发框架,通过它能够以代码的方式描述 API 的设计。与 goa 框架一同推出的还有一个 goagen 工具,它能够通过设计代码生成各种输出,包括 http 服务器的封装、代码脚手架、文档、客户端,甚至是自定义的输出。goa 包还包括大量的支持性模块,服务本身与生成的代码都能够利用这些模块进行服务的实现。

InfoQ:与使用标准的 Go 类库(或者使用 Peter Bourgon 开发的 go-kit)相比,“goa”通过怎样的方式简化了微服务的开发?

Simon:goa 框架能够描述 API 的 _ 意图 _。通过使用 goa 设计语言,开发者能够定义 API 所暴露的资源与行为(即 API 的终结点)。对于每种行为的描述包括所期待的请求状态,以及各种可能产生的响应。这种方式能够带来许多益处:举例来说,它在设计阶段就能够起到很大的作用,各个团队能够通过 Swagger UI 生成 Swagger 的规格说明,从而提出反馈意见。这一反馈循环能够为负责生成 UI 或编写面向用户的文档的团队带来极大的便利。最大的优点在于,这一切都发生在实际编写代码实现之前。

这种方式的另一优点在于,一旦设计完成之后,goa 就将负责生成所有样板逻辑,包括请求的验证以及用于描述请求状态的自定义数据结构。这样一来,设计就变成了实现所必需的一部分。这就体现出了这一方式具有很高价值的一面,否则的话,维持实现与设计之间的同步就成了非常一项非常繁琐的流程。对于每个暴露了访问功能的行为来说,goa 能够生成特定的请求处理逻辑的上下文,从中返回符合设计所描述的数据结构。这种做法减少了对“绑定”方式的需求,也不必手动地验证所传入的请求的格式。

goagen 也能够为 API 生成相应的客户端,包括一个命令行工具、Go 包和 JavaScript 的客户端。这种方式显而易见的好处是免去了手动进行这一过程所花的时间,除此之外,它还有助于维护多个客户端之间的一致性,并且保持他们与 API 的同步。在微服务的世界中,服务的数量是持续增长的,因此保持他们之间的一致性是一种非常有价值的做法,它大大地简化了构建整合的流程。

InfoQ:“goa”看起来为开发者提供了很多内容,包括一个运行时“引擎”、支持日志记录、能够对“中间件”进行自定义、还支持错误处理。你是否打算为基于 Go 的微服务架构提供一个单一的解决方案?

Simon:goa 中的请求上下文是运行时引擎的核心,它引用了 golang 这个包的开发者所做的工作,主要是跨接口传递上下文的功能,从而实现一些强大的特性,例如设置 deadline,以及在 goroutine 之间共享状态信息。举例来说,上下文信息能够一路传递至负责生成外部请求的软件模块,因此,在整个周期中的任何阶段,都能够获取包括 deadline 在内的整个请求状态。生成的代码将以一种特定于行为的数据结构对上下文进行封装,通过在设计代码中所描述的字段暴露已验证的请求的状态。

而其余部分的行为都是能够进行替换的:goa 的设计遵循了“提供内置支持”的模型。举例来说,如果你对于如何进行错误处理并没有非常确定的想法,那么 goa 将为你提供一种恰当的默认实现(在这种情况下所返回的响应将包括 500 状态码)。不过,开发者也能够方便地覆盖默认的错误处理逻辑,以实现任何自定义的逻辑,goa 还提供了一种备选的错误处理逻辑,在响应中将不包括调用栈的信息。另一个例子是对中间件的支持:goa 定义了一种专用类型的中间件,可以通过它利用丰富的上下文信息,但同时也能够使用普通的 http 中间件。

目前来说,并非所有特性都能够被轻易地替换(例如日志记录),因为 goa 最初的关注点在于代码的生成。总体目标是提供一个完整的、模块化的微服务开发框架,因此,曾使用过 go-kit 或其它 Go 包的开发者依然能够继续使用它们,而同时又能够受益于 goa 所提倡的基于设计的 API 设计方式。

InfoQ:我们很有兴趣了解一下关于生成能够调用服务 API 的客户端代码的特性。通常来说,有关代码生成的讨论总是会得到一些消极的回应,例如生成的代码过于复杂,或是生成过程不够透明、也无法进行自定义。你能否为我们解释一下你选择这种实现方式的原因?

Simon:这里的诀窍在于所生成的代码实现的功能只是一些繁琐的样板代码,这些生成代码的结构与你“手写”这些代码的结果是相同的。goagen 尽了最大努力以试图遵循“尽量减少令人惊讶的部分”的原则。你甚至可以说生成的最终代码看起来更“标准”(并且更高效)。举例来说,它减轻了对反射的依赖,否则的话,实现相同的功能可能要写上几千行代码。我们可以以客户端的 Go 包为例,你恐怕很难想到它居然是自动生成的。好吧,或许有些本地变量的命名看起来有点古怪,这可能会使你查觉到真相 :)

goa 的代码生成还有一个十分重要的特点,即所生成的代码始终处于一个不同的包中,而无需进行手动修改,从而清晰地区分了用户代码与生成的代码。goagen 将始终重新生成整个包,因此不可能出现用户代码与生成代码相混合的情况。这里有一种例外情况,即 goagen 可以在编码的起始阶段生成一种一次性的脚手架代码。

最后,goagen 只会生成必要的代码,所生成的代码将使用 goa 包实现各种通用的功能,例如日志记录、错误处理等等。它提供了一种优秀的方式对生成代码的行为进行自定义,而无需进行手动修改。举例来说,你可以实现一种自定义的服务错误处理逻辑,并且让所有生成代码自动调用这段自定义逻辑。你可以将这种生成代码想象为一种 goa 包的“插件”,并暴露相应的调节器以修改它的行为。

goagen 也支持插件系统,它实质上就是一种标准的 Go 包,其中包含了一个公开的 Generate 函数。由 Brian Ketelsen 所编写的 gorma 插件是对这一项目最早的贡献之一,它能够通过 API 设计中所描述的类型生成 gorm 模型。整个项目最令人惊讶的部分就在于通过代码(以及其他功能)生成所带来的各种可能性。在我看来,这一设想已经很明显地在 Go 语言中得到了很好的表现。

InfoQ:如果 InfoQ 的读者有兴趣加入“goa”项目,或是为其贡献代码,最好的途径是什么?

Simon:在 GitHub 库上的 wiki 中包括一份路线图的文档,其中可以找到许多建议,但这些仅仅是建议而已。这一项目最值得赞扬的一点在于它在社区中得到了快速的应用,而且在我所没有考虑到的方面也得到了许多代码贡献。goa 依然是一个很新的构架,整个项目的发展方向存在于许多可能性。此外,在 gophers.slack.com 上还有一个活跃的#goa slack 频道。因此,建议大家去访问 GitHub 库、加入 slack 频道,并且开始尝试!

本项目确实有一个地方或许需要大家的帮助:它需要一个 logo!它的网站页面可能也需要动一下整形手术 ;)

InfoQ:Raphael,感谢你参加今日的访谈。对于 InfoQ 的读者,你还有什么内容想同大家分享的吗?

Simon:感谢你的邀请!我推荐所有希望创建 API 的读者们去尝试一下 goa,我真的相信它能够帮助你们更高效地打造服务。微服务风格的架构如今已经快速地成长为事实上的标准,这使得设计优秀的 API 这一任务显得更为关键,而优秀的工具能够起到极大的作用。随着 goa 的使用率不断增长,我对于它的发展充满期待,并且迫不及待地想看到用户能够通过它实现哪些功能。

如果想了解有关 goa 微服务框架的更多信息,可以阅读 Gopher Academy 博客上的“ goa: Untangling Microservices ”这篇帖子,并访问 goa 的 GitHub 库

查看英文原文: Defining, Reviewing and Implementing Service APIs with “goa”, a Go-based Microservice Framework

2016-01-05 18:0011469
用户头像

发布了 428 篇内容, 共 191.7 次阅读, 收获喜欢 39 次。

关注

评论 1 条评论

发布
用户头像
dubbo-go
2020-11-20 01:37
回复
没有更多了
发现更多内容

兄弟们,这年头,咱移动客户端工程师还有前途吗,flutter图片压缩上传

android 程序员 移动开发

入职两年的安卓“程序员“跳槽,2021年阿里Android面试题精选

android 程序员 移动开发

架构实战营模块毕业总结

河马先生

架构实战营

全面理解 Flutter(万字长文,深度解析,整理了3家面试问题:美团+字节+腾讯

android 程序员 移动开发

做了5年Android,靠着这份面试题跟答案,我从12K变成了30K

android 程序员 移动开发

关于拼多多被曝删除用户本机照片的一点想法,移动服务框架app下载安装

android 程序员 移动开发

区块链上的房地产:区块链会颠覆房地产吗?

CECBC

全网都刷爆了,不会只有你不知道吧—,android智能手机编程答案

android 程序员 移动开发

全面!2020华为Android岗面试真题(已解析含答案,android蓝牙开发框架

android 程序员 移动开发

架构实战营-模块九-毕业设计

Cingk

关于大厂Android面试必问的事件分发机制,应该没有比这篇讲的更好的了

android 程序员 移动开发

做了六年Android,终于熬出头了,15K到31K全靠这份高级面试题

android 程序员 移动开发

再见!onActivityResult!你好(1),太现实了

android 程序员 移动开发

再见!onActivityResult!你好,android开发电子书阅读器

android 程序员 移动开发

关于拼多多被曝删除用户本机照片的一点想法(1),android程序设计基础

android 程序员 移动开发

关于Android的渲染机制,大厂面试官最喜欢问的7个问题【建议收藏

android 程序员 移动开发

这本“算法宝典”讲得透彻,完全掌握后,我竟拿到字节跳动offer

程序员 算法 字节

元宇宙,如何看待它就是下一代互联网(附下载)

CECBC

05 K8S之kubeadm介绍

穿过生命散发芬芳

k8s 11月日更

写给即将正在找工作的Android攻城狮,移动客户端开发面经

android 程序员 移动开发

关于 Flutter 是不是“大有可为”这件事,androidjetpack教程

android 移动开发

再见!杭州!再见,kotlin数组fold方法

android 程序员 移动开发

写给Android开发者的混淆使用手册,程序员工作2年月薪12K

android 程序员 移动开发

内存泄漏以优化大全,2021非科班生的Android面试之路

android 程序员 移动开发

六年Android从迷茫到大牛的成长之路,不忘初心,方得始终

android 程序员 移动开发

关于MVC_MVP_MVVM的一些错误认识,android面试流程

android 程序员 移动开发

关于使用 Android MVVM + LiveData 模式的一些建议,ffmpeg音视频同步

android 程序员 移动开发

关于程序员35岁的坎:年龄不是挡板,当你匹配了这个年纪该有的能力还有什么畏惧

android 程序员 移动开发

毕业设计—电商秒杀系统

俊杰

架构实战营

写代码还是做管理?安卓开发者的困扰,一文全懂

android 程序员 移动开发

全面复盘Android开发者容易忽视的Backup功能 _ 创作者训练营第二期

android 程序员 移动开发

通过基于Go的微服务框架goa,实现对服务API的定义、审查与实现_语言 & 开发_Daniel Bryant_InfoQ精选文章