Go 官方博客
使用 Go Cloud 进行可移植云编程
简介
今天,Google 的 Go 团队发布了一个新的开源项目 Go Cloud,这是一个用于在开放云上开发的库和工具。通过这个项目,我们的目标是让 Go 成为构建可移植云应用程序的开发人员的首选语言。
本文解释了我们为何启动这个项目、Go Cloud 的工作原理细节以及如何参与其中。
为何选择可移植云编程?为何是现在?
我们估计全球现有超过一百万 Go 开发者。Go 为许多最关键的云基础设施项目提供支持,包括 Kubernetes、Istio 和 Docker。Lyft、Capital One、Netflix 以及更多公司都在生产环境中依赖 Go。多年来,我们发现开发者喜欢 Go 进行云开发,因为它高效、高生产力、内置并发和低延迟。
作为我们支持 Go 快速增长工作的一部分,我们一直在采访使用 Go 的团队,以了解他们如何使用该语言以及 Go 生态系统如何进一步改进。许多组织的一个共同主题是跨云提供商的可移植性需求。这些团队希望在多云和混合云环境中部署健壮的应用程序,并在不显著更改其代码的情况下在云提供商之间迁移其工作负载。
为了实现这一点,一些团队试图将他们的应用程序与特定于提供商的 API 解耦,以生成更简单、更可移植的代码。然而,尽快交付功能的短期压力意味着团队常常牺牲为可移植性所做的长期努力。因此,大多数运行在云中的 Go 应用程序与其最初的云提供商紧密耦合。
作为替代方案,团队可以使用 Go Cloud(一组开放的通用云 API)来编写更简单、更可移植的云应用程序。Go Cloud 还为基于这些通用 API 构建可移植云库生态系统奠定了基础。Go Cloud 使团队能够在实现其功能开发目标的同时,保留多云和混合云架构的长期灵活性。Go Cloud 应用程序也可以迁移到最符合其需求的云提供商。
什么是 Go Cloud?
我们识别了云应用程序使用的常见服务,并创建了可在不同云提供商上工作的通用 API。今天,Go Cloud 发布时包含 Blob 存储、MySQL 数据库访问、运行时配置以及配置了请求日志、跟踪和健康检查的 HTTP 服务器。Go Cloud 支持 Google Cloud Platform (GCP) 和 Amazon Web Services (AWS)。我们计划很快与云行业合作伙伴和 Go 社区合作,以添加对更多云提供商的支持。
Go Cloud 旨在为跨云提供商最常用的服务开发厂商中立的通用 API,以便在另一个云上部署 Go 应用程序变得简单容易。Go Cloud 还为其他开源项目编写跨提供商工作的云库奠定了基础。来自各种类型、各个级别开发者的社区反馈将指导 Go Cloud 未来 API 的优先级。
它是如何工作的?
Go Cloud 的核心是一系列用于可移植云编程的通用 API。让我们来看一个使用 Blob 存储的例子。您可以使用通用类型 *blob.Bucket
将文件从本地磁盘复制到云提供商。让我们首先使用包含的 s3blob 包打开一个 S3 bucket
// setupBucket opens an AWS bucket.
func setupBucket(ctx context.Context) (*blob.Bucket, error) {
// Obtain AWS credentials.
sess, err := session.NewSession(&aws.Config{
Region: aws.String("us-east-2"),
})
if err != nil {
return nil, err
}
// Open a handle to s3://go-cloud-bucket.
return s3blob.OpenBucket(ctx, sess, "go-cloud-bucket")
}
一旦程序获得了 *blob.Bucket
,它就可以创建一个实现了 io.Writer
的 *blob.Writer
。然后,程序可以使用 *blob.Writer
将数据写入 bucket,并检查 Close
是否报告错误。
ctx := context.Background()
b, err := setupBucket(ctx)
if err != nil {
log.Fatalf("Failed to open bucket: %v", err)
}
data, err := ioutil.ReadFile("gopher.png")
if err != nil {
log.Fatalf("Failed to read file: %v", err)
}
w, err := b.NewWriter(ctx, "gopher.png", nil)
if err != nil {
log.Fatalf("Failed to obtain writer: %v", err)
}
_, err = w.Write(data)
if err != nil {
log.Fatalf("Failed to write to bucket: %v", err)
}
if err := w.Close(); err != nil {
log.Fatalf("Failed to close: %v", err)
}
请注意,使用 bucket 的逻辑不涉及 AWS S3。Go Cloud 使得更换云存储只需改变用于打开 *blob.Bucket
的函数即可。应用程序可以使用 gcsblob.OpenBucket
构建一个 *blob.Bucket
来使用 Google Cloud Storage,而无需更改复制文件的代码
// setupBucket opens a GCS bucket.
func setupBucket(ctx context.Context) (*blob.Bucket, error) {
// Open GCS bucket.
creds, err := gcp.DefaultCredentials(ctx)
if err != nil {
return nil, err
}
c, err := gcp.NewHTTPClient(gcp.DefaultTransport(), gcp.CredentialsTokenSource(creds))
if err != nil {
return nil, err
}
// Open a handle to gs://go-cloud-bucket.
return gcsblob.OpenBucket(ctx, "go-cloud-bucket", c)
}
虽然访问不同云提供商上的 bucket 需要不同的步骤,但应用程序使用的结果类型是相同的:*blob.Bucket
。这将应用程序代码与特定于云的代码隔离开来。为了增强与现有 Go 库的互操作性,Go Cloud 利用了诸如 io.Writer
、io.Reader
和 *sql.DB
等既定接口。
访问云服务所需的设置代码往往遵循一种模式:更高级的抽象是从更基本的抽象构建而来。虽然您可以手动编写这些代码,但 Go Cloud 使用 Wire 工具自动完成此操作,该工具会为您生成特定于云的设置代码。Wire 文档解释了如何安装和使用该工具,而访客留言簿示例展示了 Wire 的实际应用。
我如何参与并了解更多?
要开始使用,我们建议按照教程进行操作,然后尝试自己构建一个应用程序。如果您已经在使用 AWS 或 GCP,可以尝试将现有应用程序的一部分迁移到使用 Go Cloud。如果您使用的是不同的云提供商或本地服务,可以通过实现驱动程序接口(如 driver.Bucket
)来扩展 Go Cloud 以支持它。
我们感谢您提供的任何和所有关于您使用经验的反馈。Go Cloud 的开发工作在 GitHub 上进行。我们期待您的贡献,包括拉取请求。提交问题,告诉我们哪些方面可以改进,或者项目未来应该支持哪些 API。如需获取项目更新和参与讨论,请加入项目邮件列表。
该项目要求贡献者签署与 Go 项目相同的贡献者许可协议 (Contributor License Agreement)。阅读贡献指南了解更多细节。请注意,Go Cloud 受 Go 行为准则的约束。
感谢您花时间了解 Go Cloud。我们很高兴能与您合作,使 Go 成为构建可移植云应用程序开发人员的首选语言。
下一篇文章:Go 1.11 已发布
上一篇文章:Getting to Go:Go 垃圾回收器的旅程
博客索引