【发布时间】:2016-07-11 03:06:23
【问题描述】:
在 GAE 的 golang 应用程序的 init() 函数中,如何为我的应用程序设置初始值?
如何在 init() 函数中或应用程序启动后立即从 Cloud Datastore 中读取数据?据我了解,服务器无法写入本地文件系统,而 Cloud Datastore 是唯一的选择?
我需要一些全局变量和数据切片..
【问题讨论】:
标签: google-app-engine go google-cloud-datastore
在 GAE 的 golang 应用程序的 init() 函数中,如何为我的应用程序设置初始值?
如何在 init() 函数中或应用程序启动后立即从 Cloud Datastore 中读取数据?据我了解,服务器无法写入本地文件系统,而 Cloud Datastore 是唯一的选择?
我需要一些全局变量和数据切片..
【问题讨论】:
标签: google-app-engine go google-cloud-datastore
在 AppEngine 上,您无权访问主机操作系统的文件系统,但您可以访问 Web 应用程序的文件(您拥有只读权限,不能更改它们,也不能创建应用文件夹中的新文件)。
所以问题是:您的应用程序代码能否更改您要读取并用于初始化的数据?还是使用您的应用代码“静态”部署它是否可以?
如果您不需要更改它(或仅在您重新部署应用程序时),最简单的方法是将其存储为“静态”文件作为 web 应用程序的一部分。您可以使用相对路径引用您的应用程序的文件,其中当前或工作目录是您的应用程序的根目录。例如。如果您的应用在其根目录(app.yaml 所在的位置)中包含一个data 文件夹,并且在data 文件夹内有一个init_values.txt 文件,您可以通过路径:data/init_values.txt 引用它。
一个重要提示:并非每个文件都可以通过代码读取,这取决于应用配置。引用Configuring with app.yaml / Static file handlers:
如果你有数据文件需要应用程序代码读取,数据文件必须是应用程序文件,不能通过静态文件模式匹配。
您不能在处理程序之外使用需要 Context 的 AppEngine 服务(因为创建 Context 需要 *http.Request 值)。这本质上意味着您也不能在包 init() 函数中使用它们。
请注意,您可以从添加到任务队列的 cron 作业和任务中使用它们,因为任务和 cron 作业是通过发出 HTTP 来执行的GET 请求。
您必须重组代码,以便从处理程序调用您的初始化(例如从数据存储区读取)。
使用Once.Do() 实现此目的的示例:
var once = sync.Once{}
func MainHandler(w http.ResponseWriter, r *http.Request) {
ctx := appengine.NewContext(r)
once.Do(func() { mysetup(ctx) })
// do your regular stuff here
}
func mysetup(ctx appengine.Context) {
// This function is executed only once.
// Read from Datastore and initialize your vars here.
}
是的,这可能会导致首次请求的服务时间要长得多。为此(为避免这种情况),我建议您使用Warmup requests。在新实例“上线”之前,在它开始为用户请求提供服务之前,会向它发出预热请求。在您的app.yaml 配置文件中,您可以通过将-warmup 添加到inbound_services 指令来启用预热请求:
inbound_services:
- warmup
这将导致 App Engine 基础架构首先向 /_ah/warmup 发出 GET 请求。您可以向此 URL 注册处理程序并执行初始化任务。与任何其他请求一样,您将在预热处理程序中拥有一个 http.Request。
但请注意:
..您可能会遇到loading requests,即使您的应用中启用了预热请求。
这意味着在极少数情况下,新实例可能不会收到预热请求,因此最好也检查用户处理程序中的初始化状态。
相关问题:
How do I store the private key of my server in google app engine?
Fetching a URL From the init() func in Go on AppEngine
Environment variables specified on app.yaml but it's not fetching on main.go
【讨论】: