通向Golang的捷径【20. 使用 Go 语言的 GAE】

20.1 GAE 介绍

GAE 即为谷歌 App 引擎 (Google App Engine), 是一种云计算的解决方案, 它可执行用户的 web 应用, 并将用户数据保存到 Google 架设的大量设备中, 而无须考虑服务器, 网络连接, 操作系统和数据存储等问题, 云端通常会被视为一个资源集合, 但它的维护只会交由 Google 来完成, 因此你只需开发自己的应用, 云端会将你的应用发送给用户, 并会在连接到网络的某台设备上, 运行你的应用, 同时你的软件只需支付一些资源使用费(比如 CPU 的处理时间, 网络带宽, 磁盘用量, 内存用量等), 当出现瞬间峰值时, 云平台可自动为应用程序增加资源, 当附加的资源不再需要时, 可减少附加的资源, 因此伸缩性是云计算的优势之一, 协同应用 (多人创建的不同应用需一起运行, 不同应用之间需共享数据以及通讯), 可向用户提供服务的应用, 以及执行大量计算的应用, 应当优先选择云计算平台, 同时云端应用的典型用户接口, 即为浏览器.

CAE 发布于 2008 年, 并支持 Python 应用,2009 年增加了 Java 应用的支持,2011 年增加了 Go 应用的支持,它的官方主页为 http://code.google.com/appengine/.

GAE 为构建和部署 web 应用, 提供了一种可靠的具有伸缩性的简单方式, 保守估计有一百万个应用被保存在appspot.com 站点上 (每个应用都有自己的特定域名), 它们都在使用 App 引擎, 这是一种服务平台环境, 它比云架构 (比如 Amazon EC2) 更高级, 可实现资源共享的最高效率.

Sandbox

如果你的应用运行在一个安全环境 Sandbox 中, 它可限制来自于底层操作系统的访问, 同时允许 App 引擎将web 请求在多个服务器之间进行分发, 而起始服务器和终点服务器需要满足一些传输要求.sandbox 可将你的应用, 封闭在一个安装可靠的环境中, 同时它与硬件, 操作系统以及 web 服务器的位置无关, 当然也存在以下限制:

• web 应用不能将数据, 写入服务器的文件系统, 同时应用只能读取更新文件, 应用必须使用 App 引擎的
数据集, 内存缓冲或其他服务, 来处理请求中包含的所有数据.

• 运行代码只能为一个 web 请求, 或是一个队列任务, 又或是一个调度任务, 提供所需的响应, 同时响应必须在 60s 内产生, 一个请求处理器不能产生一个子进程, 或是在响应发送后, 依然在执行.

• 基于网络连接, 应用只能通过 URL 地址或是邮件服务, 实现其他 PC 机的访问, 而其他 PC 机也只能通
过标准端口的 HTTP(或 HTTPS) 请求, 与 web 应用进行交互.

web 应用可使用的服务

• 基于 Google 提供的 Bigtable, 数据可保存在 GAE 的数据集中, 这是一个分布式的数据存储服务, 它可
提供一个查询引擎和传输功能, 并能随着数据的增加, 而使存储区自动增加, 所以它并不是一个传统的关
系数据库, 在经典 SQL 数据库中, 上述的添加方式不被允许, 但是 GAE 提供了一种类 SQL 的查询语言
GQL, 其中的数据对象被称为 entity(实体), 它可包含一个类型和一组属性, 基于一个特定的种类, 可查询和获取数据库的实体, 同时也可保存实体的属性, 同时实体的属性值也应当符合所支持的数值类型, 实体可进行编组, 编组可视为传输任务的一个单元, 因此一次传输中必须包含一个实体编组, 所以在应用中,无须给出数据库的处理, 但是必须提供实体所包含的所有数据, 同时可使用优化的并发控制进行更新, 以便获得最新的数据更新.

• 使用集成的 Google Account, 可为 app 进行用户验证.

• URL 获取功能, 使用该服务, 可使 app 可访问互联网资源, 比如 web 或其他数据.

• app 可使用内建的邮件服务.

• memcache(内存缓存) 是一种高性能的内存缓冲 (使用键值对), 适合于短期使用且无须保存到数据集的
数据, 比如临时数据, 或是来自于数据集的数据副本 (以实现高速访问).

• 图片的维护功能

• 任务调度和任务队列: 除了响应 web 请求之外,app 还可执行其他任务, 并能在一个配置好的调度规则中,运行不同的任务, 比如每天的调度或每小时的调度, 也可选择将任务, 添加到应用的队列中, 比如处理请求的后台任务.

20.2 Go 云处理

在 2010 年 5 月 10 日的 Google I/O 大会上, 发布了支持 Go 语言的 GAE 版本, 这是一个实验版本, 只提供给已注册的测试者, 而第一个正式版本发布于 2011 年 7 月 21 日, 在本书的编写时间 (2012 年 1 月) 下,Go App引擎 SDK 的最新版本为 1.6.1(发布于 20111-12-13), 它支持 Linux 和 Mac OS X(10.5 或更高版本) 系统, 并同时支持 32bit 和 64bit 系统, 所使用的 Go 工具链版本为 r60.3, 其中给出的一些修改, 无法完全实现向后兼容,SDK API 的版本为 3.

在 App 引擎中运行的 Go app, 可使用 64bit x86 编译器 (6g) 进行编译, 由于样机中只能运行一个线程, 因此所有的并发协程将运行在一个操作系统的线程中, 所以面对客户端请求不会出现 CPU 的并行.

Go 语言是 App 引擎支持的首个可编译语言, 与其他两种语言相比,Go 具备一些优势, 如下:
• 与 Java 相比: Go 具有更快的启动时间, 以及更好的并发性能
• 与 Python 相比: Go 具有更好的执行性能

20.3 安装 GAE SDK

20.3.1 安装

在 Google App Engine 官网 (http://code.google.com/appengine/downloads.html) 上, 找到与目标平台相符的GAE SDK 压缩 (zip) 安装包. 如果目标平台为 Ubuntu11.10(64bit Linux), 可下载go_appengine_sdk_linux_amd64-1.6.1.zip. 在所需的目录下 (比如 home 目录), 解压该文件, 其中将包含一个目录google_appengine, 它包含了 Go 开发环境所需的完整 App Engine.

在google_appengine 目录下, 包含了开发, 构建和测试本地 app 的所有工具, 其中将给出一个AppEngine服务器 (可用于测试), 同时还包含了一个数据集, 可用于数据存储, 也就是在云端的AppEngine服务器上, app的执行也需要进行数据存储, 同时其他 API 和工具允许你模拟一个 AppEngine, 以实现 app 的开发和测试, 在支持 Go 语言的 AppEngine 环境中, 也包含了 Go 语言的编译器, 包和附带工具.

GAE-Go 与 Go 的区别

在 GAE-Go 中包含了完整的 Go 系统, 几乎所有的标准库, 因此只有少数任务, 无法在 AppEngine 环境中实现, 如下:
• 只包含稳定包, 同时 syscall 包已被剔除
• 不支持 cgo(与 c 库的交互功能), 在 GAE 项目中, 无法使用二进制库 (Go 语言或其他语言), 因此 GAE
项目需要编译和链接所有源码
• 不支持 go install
• CAE 的发布时间通常慢于 Go 语言

另外 Sandbox 环境 (参见 20.1 节) 的限制必须考虑, 否则打开一个 socket 或是写入文件时, 将返回一个
os.EINVAL 错误. 同时 GAE-Go 和 Go 的附带工具是彼此独立的, 如果只需在 GAE 中进行开发, 则不要
使用 Go 的附带工具.

在google_appengine 目录下, 还包含了少量的 Python 脚本, 它将完成 GAE 所需的基本任务, 首先需确认这些脚本可以执行 (如果无法执行, 可使用命令chmod +x *.py), 同时需将该目录加入到 PATH 环境变量中, 以便在调用这些脚本时, 无须指定它们的路径, 比如 bash shell, 可在.bashrc 或.profile 文件中, 加入以下命令:
在这里插入图片描述

其他细节

• 如果已配置了一个可工作的 Go 环境,AppEngine 应实现独立安装, 也就是与 Go 环境互不影响, 尤其是在操作系统中, 不要修改 Go 开发环境,GAE-Go 有自己的独立环境, 它的目标路径为 ~/google_appengine/goroot
• 应当下载 GAE 的文档, 可在官网中, 下载 google-appengine-docs-20111011.zip 文件并解压
• 在 GAE 中, 大量使用 Python 语言, 同时 Mac OS X 和 Linux 系统已默认安装了 Python 环境, 如果未
安装 Python, 可在官网页面www.python.org, 下载 Python 2.5
• CAE-Go 的库和 SDK 也是开源软件, 可在页面http://code.google.com/p/appengine-go/中找到, 并可使用命令hg clone https://code.google.com/p/appengine-go/下载
• app 包含的所有 Go 包, 将构建成一个独立的可执行文件,Go 程序可将需处理的请求派发给该文件, 这与Java SDK 和 Python SDK 的工作机制并不相同

在 20.8 节中, 将看到 CAE 云端如何与 web 应用进行连接, 在执行这一步骤之前, 需要在本地 GAE 环境中,实现 app 的开发, 测试和运行, 同时本地 GAE 环境可模拟云端环境.

20.3.2 检查与测试

安装检查

为保证 google_appengine 目录中包含的 Go 环境, 能够正常工作, 可利用 dev_appserver.py 脚本, 启动本地的 AppEngine 服务器, 如果看到以下输出信息:
在这里插入图片描述
则表示一切正常.

运行 app demo

在 SDK 中包含了一些 app demo, 调用这些 demo, 可了解当前的 GAE 开发环境是否正常.
• 进入google_appengine/demos 目录, 可看到一些文件夹, 比如 helloworld,guestbook 等.
• 进入上述的 demo 目录, 并执行命令dev_appserver.py helloworld, 这将导致 Go 程序的自动编译, 自动链接和自动运行.
• 上述命令可给出一些警告和输出信息, 如果在 8080 端口上, 执行 helloworld 应用, 可使用http://localhost:8080, 之后 helloworld 应用将运行在本地 AppEngine 服务器中, 并能为 8080 端口的用户请求, 提供对应的服务.
• 打开浏览器, 并输入http://localhost:8080 地址, 可显示一个网页, 页面内容为:
在这里插入图片描述
这时 web 应用已成功运行在本地 AppEngine 服务器中. 以下是 helloworld 应用的源码,

例 20.1 helloworld.go

在这里插入图片描述
在这里插入图片描述
以上的 web 应用很简单 (参见第 15 章), 并在 init 函数中, 启动了所有的处理器函数, 同时在处理器函数
(handle) 中, 包含了所需的网页.

20.4 自定义 app(helloworld)

以下将构建与上一节 helloworld demo 相同的一个 web 应用.

20.4.1 创建一个简单的 http 处理器

为自定义 app 创建一个目录, 并命名为 helloapp, 该 app 包含的所有文件都放入该目录中, 在 helloapp 目录中, 创建另一个目录 hello, 其中将包含 Go 源码 (实现 hello 包), 在 hello 目录中, 创建一个文件helloworld2.go, 并在文件中包含以下代码 (以下代码与上一节的 app demo 基本相同),

例 20.2 helloworld2_version1.go

在这里插入图片描述
注意包名 hello, 在编写单独的 Go 程序时, 需要在源码中放入一个 main 包, 但在 GAE-Go 环境中, 运行时管理将为 web 应用, 提供一个 main 包和 http 监听器, 因此可将代码放入一个选定的包中, 这里是 hello 包, 其次, 在 AppEngine 上运行的 web 应用 (Go 语言), 可通过 web 服务器, 实现与外部世界的通讯, 这与独立的web 应用 (Go 语言) 很相似 (参见第 15 章), 所以需要导入 http 包, 并为不同的 url 地址, 定义不同的处理器函数, 同时不会包含 main 函数, 因此处理器的配置将移入 init 函数, 而 web 服务器的启动将由 GAE 完成, 所以 hello 包可响应任意请求, 并能回传一个包含 Hello, world! 消息的影响.

20.4.2 创建配置文件 app.yaml

所有的 GAE app 都需要提供一个 yaml 配置文件 app.yaml, 它将包含可提供给 GAE 的 app 元数据 (yaml是一种文本文件的格式, 常用于开源项目, 如果需要深入了解, 可参考网页www.yaml.org), 该文件可告知 AppEngine, 如何实现运行时管理, 以及当前 web 应用可处理那些 URL 地址, 同时还将为 app demo 保存一个app.yaml 副本, 并会放置在 helloapp 目录中.

以下将给出当前 app 的文件结构:
在这里插入图片描述
只有 app.yaml 是一个必须使用的名称, 而目录名,Go 文件名和包名可使用不同的名称, 但为了便于使用, 上述名称应使用相同或类似的命令, 同时应用的顶层目录 (helloapp) 应包含 app 后缀.

app.yaml 文件能被 AppEngine 读取和解析, 并能在以下情况中, 执行 web 应用.
在这里插入图片描述
app.yaml 文件可使用 #, 标记一个注释, 并能在文件中, 包含以下内容:
在这里插入图片描述
• application: 可给出 web 应用的名称, 这里是 helloworld, 在开发过程中, 可给出任意名称, 该名称将在
AppEngine 中注册 web 应用, 因此需选择一个唯一的名称, 同时该名称也接受更新.

• version: 可指定 app 的版本, 事实上 GAE 可并发运行同一个 app 的不同版本, 但其中一个版本需指定
为默认应用, 它可使用字母, 数字和连号符 (-), 因此可将 T2-31 视为一个测试版本号, 并将 P2-1 视为一
个产品版本号.

• runtime: 可标记 app 的开发语言 (可使用 Java 和 Python), 如果需要对 app 进行版本更新, AppEngine可保存之前的版本, 之后可在管理员控制台中, 回滚到之前的版本.

• api_version: 指定当前 SDK 中 Go API 的版本, 由于存在与之前版本不兼容的可能性, 如果使用之前的
API 版本, 生成了 app 的早期 (开发) 版本, 虽然 GAE 可运行该 app, 但通常会有一个时间限制, 所以必
须将 app 更新到新的 API 版本, 使用 gofix 工具可满足更新要求.

• handlers: 将包含一个路由表, 它将告知 GAE, 会有那些请求会发送给服务器, 每个输入请求都需匹配
url 后续的正则表达式 (在本地开发时,http://localhost:8080/的后续地址将进行匹配, 如果在云端运行,
http://appname.appspot.com/的后续地址将进行匹配).

如果请求的 url 地址与首个 url 模式相匹配, 对应的 script(脚本) 将执行, 在当前文件中, 所有请求都能与
/.* 正则表达式相匹配, 因此 Go 程序需处理所有请求, 在 dev_appserver.py 文件中, 已给出了 _go_app
字符串, 但在云端 App Engine 服务器上, 将被忽略.

在 helloworld demo 的 app.yaml 文件中, 包含了另一个处理器, 如下:
在这里插入图片描述
有些文件 (static_files, 静态文件), 比如图形文件, 无法进行修改 (本例为 favicon.ico), 这类文件将放置在另一个 AppEngine 服务器的公共缓存中, 以便将它们更快地传递给用户, 如果 web 应用中包含了大量的图形文件, 则应放置在一个单独的目录中, 为了便于使用, 可将目录命名为 static 或 images.

当开发 app 时,upload 给出了必须上传到云端的内容, 如果 app 中包含了大量的图形文件 (images/(.ico.gif|*.jpg)|), 应将本地 images 目录下的所有文件, 都上传到 AppEngine 服务器.

在 GAE 运行的大多数应用中, 都会使用模板文件, 这些文件可保存在 app 的根目录, 或是放置在一个特殊目录 tmpl 中. 因此一个 GAE 应用的通用目录结构, 如下:
在这里插入图片描述
在控制台中, 进入 helloapp 目录, 并输入以下命令:
在这里插入图片描述
上述两个命令都可启动 web 服务器, 并监听 8080 端口的请求, 在浏览器中输入http://localhost:8080/, 可测试 web 应用是否运行成功, 之后可在浏览器中, 看到输出结果Hello, world!. 同时在服务器的控制台中, 可看到以下输出信息:
在这里插入图片描述
其中<-(A) 表示服务器就绪,<-(B) 表示服务器已编译和运行了 Go 程序, <-© 表示 app 已接收到请求, 并响应了一个 html 页面.

当服务器终止运行, 或是尚未启动时, 客户端 (浏览器) 给出 http://localhost:8080/请求, 将在浏览器 (Firefox)中, 打印出一条消息, 如下:
在这里插入图片描述

20.4.3 开发的迭代过程

在 app 开发中, 需要对源码文件进行修改, 也就是对源码进行编辑和保存, 当完成源码文件的修改后, 可重新编译, 并重启本地 app, 同时无须使用 dev_appserver.py. 因此可在 web 服务器运行时, 对helloworld2.go 文件进行编辑, 也就是修改Hello, world! 字符串, 在浏览器中重新输入http://localhost:8080/, 可看到 helloworld2.go文件的修改结果, 而上述任务也可编写一个 Rails 或 Django 应用, 以便自动实现.

为了终止 web 服务器, 可在控制台中, 按下 Ctrl+C 组合键, 之后在控制台中, 可看到以下消息:
在这里插入图片描述
其中<-(D) 表示 web 服务器可获知 app 的修改和重新编译,<-(E) 表示 web 服务器已经终止运行.

20.4.4 GoClipse IDE 的用法

• 使用 Window / Preferences / Go 菜单, 可指向 GAE-Go 的根目录.
• 使用 Run / External Tools / External Tools Configuration / Program 菜单, 可在对话框中, 点击 New按钮, 可创建一个新的配置文件, 如下:
在这里插入图片描述
再使用 Apply / Run 菜单, 可运行 app

在 GoClipse IDE 中, 配置一个外部工具 (可参考页面 http://code.google.com/p/goclipse/wiki/DeployingToGoogleAppEngineFromEclipse), 可使 app 的开发更加简单.

20.5 用户服务

GAE 可基于 Google 的大量硬件设备, 提供一些有价值的服务, 如 20.1 节所述,GAE 可提供用户服务, 因此可在你的 web 应用中, 集成 Google 的账号验证, 基于用户服务, 需要使用 web 应用的用户, 可使用 Google 账号, 并登录到你的 web 应用, 因此用户服务可简化 web 应用的私有化.

编辑 helloworld2.go 文件, 加入所需的账号验证服务, 如下

例 20.3 helloworld2_version2.go

在这里插入图片描述
在这里插入图片描述
在浏览器中重新载入之前的页面, 这时在你的 web 应用中, 将出现一个链接, 并可重定向到 Google 的登录页面 (本地版本), 这可用于 web 应用的测试, 如果在浏览器中任意输入一个用户名,web 应用将获取到一个伪造的 user.User 数值 (基于用户名产生的数值), 在 AppEngine 中运行的 web 应用, 可使用户看到Google 的账号登录页面, 之后如果成功登录, 将重定向到你的 web 应用, 否则将重定向到账号创建页面.

用户 API

为了实现上述操作, 需要导入 GAE 提供的一些 Go 包, 比如 appengine 和 appengine/user 包, 在处理器(handler) 中, 首先将创建一个与当前请求 r 关联的 Context(上下文) 对象, 如c := appengine.NewContext®, appengine.NewContext 函数可返回一个名为 c 的 appengine.Context 对象, 它可被 Go 语言的 AppEngineSDK 的大多数函数所使用, 以便与 AppEngine 服务进行通讯, 从这个上下文对象中, 可检查用户是否完成了登录操作, 即u := user.Current©.

如果登录成功,user.Current 可返回一个 user.User 指针 (可表示一个有效用户), 否则 user.Current 将返回 nil, 如果登录不成功, 将满足u == nil 条件, 之后将使用url, err := user.LoginURL(c, r.URL.String()), 使得用户浏览器重定向到 Google 的账号登录页面, 其中的第二个参数r.URL.String(), 即为当前请求的 url 地址, 当成功登录后,Google 的账号登录机制可产生一个重定向 (即定向到所请求的 url 地址), 同时会设定一个 Location头, 并返回一个 http 状态码 302(表示所请求的 url 地址已经找到).

LoginURL() 函数可返回一个错误码, 同时该函数不太可能出现错误, 但是在实际编程中, 推荐检查该错误码, 并显示检查结果, 如下:
在这里插入图片描述
当用户登录后, 可显示一个与用户账号关联的私有信息, 即fmt.Fprintf(w, ”Hello, %v!”, u), 在这种情况下, fmt.Fprintf函数可使用 user.User 的 String 方法, 以获取用户账号的字符串, 更多细节可参考页面 http://
code.google.com/appengine/docs/go/users/.

20.6 表单处理

从 15.6 和 15.7 节可知, 在 web 应用中, 经常会使用 template(模板) 包, 这也适用于 GAE app, 在以下代码中, 可允许用户输入一段文本, 首先它可显示一个游客 (guestbook) 表单 (基于/(根地址) 处理器), 之后该表单将投递给 sign(登录) 处理器, 而不是作为文本, 被添加到响应 html 中, 同时 sign 函数可调用r.FormValue, 获取到表单数据, 并将数据传递给 signTemplate.Execute, 同时 signTemplate.Execute 又可将生成的模板, 传递给 http.ResponseWriter. 修改 helloworld2.go 文件, 实现上述功能, 如下:

例 20.4 helloworld2_version3.go

在这里插入图片描述
在这里插入图片描述

20.7 数据存储集合

web 应用需要从来自于用户的 html 表单中, 收集所需的信息, 通常情况下, 将会预定义一些固定的信息位置, 以便从表单中获取或写入, 而 GAE 则提供了 DataStore(数据存储) 功能, 可将数据保存在多个 web 服务器, 甚至是多个设备上, 以此实现一个分布式数据库 (非关系数据库), 所以用户的下一次请求可传递给另一台 PC机的 web 服务器, 但 GAE 组织架构将在一个简单的 API 中, 细心操作所有数据的分布式处理, 响应处理和负载平衡, 同时还提供了一个强大的查询引擎.

以下将对之前的示例进行扩展, 首先将创建一个 Greeting 结构, 其中包含了作者, 内容和时间等信息, 因此需要保存该结构, 所以需为 entity 程序创建一个匹配的数据结构 (即处理器能够操作的对象), 通常是一个结构类型, 在运行的程序中, 放置在内存中的结构所包含的数据, 都来自于 entity 的 DataStore.

程序可接收的 url 地址, 如下

• url 根地址 (/): 可获取所有已保存的请求, 并通过 template 包, 将其显示出来, 参见 15.7 节.
• url 地址 (/sign): 将一个新的请求, 保存到 DataStore 中.

在以下示例中, 还需要导入 appengine/datastore 包,

例 20.5 helloworld2_version4.go

在这里插入图片描述
在这里插入图片描述
sign 处理器构建了一个 Greeting 变量 g, 其中使用表单内容进行初始化, 之后使用了 datastore.Put() 进行存储,DataStore 内部将为每次数据存储, 生成一个唯一的 key, 为了实现上述功能, 在 Put 函数的调用中, 将使用datastore.NewIncompleteKey(c, ”Greeting”, nil) 作为第 2 个参数 (该函数需传入一个结构类型名), 第 3 个参数即为 Greeting 变量 g 的指针.

datastor 包还提供了一个 Query 类型, 用于 DataStore 的查询, 在根地址处理器中, 将构建一个查询变量 q, 其中将使用请求的 Greeting 对象, 并以日期的降序方式, 对 DataStore 进行查询, 查询结果限制在 10 个以内.
在这里插入图片描述
查询结果将保存在一个结构中, 即一个 Greeting 类型的 slice, 之后调用 q.GetAll(c, &greetings), 将 slice 转存到 greetings 中, 并检查查询结果中是否存在错误.

当上述操作都通过后, 可将查询结果的日期数据, 都合并到一个模板中,
在这里插入图片描述
它可实现一个 range 结构, 参见 15.7.6 节. 再次测试 helloworld2.go 文件的修改, 在两次请求之间, 关闭浏览器, 这时你会发现, 依然可看到之前的请求.

清除服务器的 DataStore

在开发过程中,web 服务器将使用一个本地 DataStore, 对 web 应用进行测试, 其实就是一个临时文件, 请求数据会一直保留在临时文件中,web 服务器在没有得到指令的情况下, 不会清除这些文件, 如果在开发过程中, 需要清空 DataStore 并重新启动, 可在启动服务器时, 加入–clear_datastore 选项,
在这里插入图片描述

调试

在 Go 环境中, 可运行 gdb 调试器 (可参考页面http://golang.org/doc/debugging_with_gdb.html), 可将 gdb附加到一个运行进程中, 在通常情况下, 可使用 dev_appserver.py, 并在 localhost:8080 地址上, 启动 app, 使用命令 ps ax | grep _go_app, 可查找到 _go_app 的路径和 PID, 这时可将 gdb 附加到 _go_app 进程, 之后可给出一个 http 请求, 因此 app 的运行将遇到, 在代码中设置的断点, 如果对 Go 代码进行了修改, 必须重新编译并执行另一个 _go_app 进行调试.

20.8 云端上传

在上一节的示例中, 使用了 Google 的账号验证功能, 它可实现消息发送, 显示其他已离开用户的信息, 或是在基本功能上实现更复杂的功能, 因此需要在云端进行开发, 如果你的应用需动用大量的资源, 则应当进行调整,因为 GAE 处理具有自动化的伸缩性.

首先你需要申请一个 Google 账号, 比如使用 gmail 邮件地址, 作为你的用户名, 在页面www.google.com/accounts可快速申请一个 Google 账号.

在页面https://appengine.google.com/出现的 App Engine Administration Console(App Engine 管理员控制台) 中, 可创建和管理 App Engine web 应用.

完成 SMS 验证后, 可获得 Create an Application(创建 web 应用) 页面, 选择 application identifier(应用标识, 它必须是一个唯一名称, 在 GAE 包含的所有应用中), 比如 ib-tutgae.appspot.com, 加上 http://前缀, 则可变成 web 应用的 url 地址, 后续无法对应用标识进行修改, 因此可在应用名中, 加入个人喜欢, 以生成一个私有 app, 或是加入公司名称, 以生成一个商用 app, 之后可选择 application title(应用标题), 这在 app 中可见, 同时后续可对标题进行修改, 比如 Tutorial GAE App, 去除默认的 Google 验证功能和高速 Datastore 功能 (Google Authentication,High Replication Datastore), 以便在 GAE 中运行 web 应用时, 不会产生费用问题, 之后点击 Create Application 按钮, 将出现一条消息 Application Registered Successfully (应用注册成功), 之后可将 app 应用上传到云端, 如下:
• 编辑 app.yaml 文件, 修改 web 应用的数值, 将 helloworld 变更为 ib-tutgae
• 为了将 web 应用上传到 GAE 并进行配置, 可使用 appcfg.py 脚本命令, 即 appcfg.py update helloapp/

当你的 Google 账号验证成功后,web 应用将上传到运行, 并能在 App Engine 中开发了.

如果需要更新 web 应用的新版本, 首先需要处理代码中出现的错误, 完成 app 的编译后, 才可将 app 上传到云端, 否则上传没有任何意义, 使用页面http://application-id.appspot.com, 可在云端上, 对 web 应用进行测试, 其中 application-id 即为唯一的应用标识, 这里是http://ib-tutgae.appspot.com, 这类测试同时支持工作在Windows,Linux,OS X 平台的浏览器.

对 web 应用进行监控

进入https://appengine.google.com/页面, 可给出一个列表, 其中包含了你的所有应用, 点击某个应用, 将弹出它的控制面板, 其中可提供 web 应用的监控服务, 如下图,
在这里插入图片描述
监控功能是相当重要的, 因为 web 应用工作在云端, 这意味着你只能进行访问, 无法掌控代码运行的状态或是进行调试, 而从监控功能的图形结果中可知,web 应用的负载状况 (每秒的请求数), 消耗的资源数 (CPU 用量, 带宽, 存储用量, 数据复制, 后台用量), 费用产生的明细, 可查看负载信息, 即每个 url 地址的请求数和 cpu 负载, 或是查看错误信息, 即 web 应用出现错误时, 所给出的信息, 数据面板 (Data Panel) 和 Datastore 查看器 (Viewer) 可查看和查询你的 Datastore 数据, 使用 Administration 查看方式, 还可得到一些特殊信息, 以及GAE 文档的链接, 选择 Main/Logs 路径, 可参看每次请求的日志, 以及错误异常的日志记录 (而异常不会显示给用户).

在这里插入图片描述