英文:
Environment variables specified on app.yaml but it's not fetching on main.go
问题
我已经在app.yaml中指定了我的环境变量,并且在本地运行时可以获取到它,但是一旦部署到Google App Engine上,就无法获取到了。
以下是我的设置:
application: some-application
version: 1
runtime: go
api_version: go1
threadsafe: true
handlers:
- url: /.*
script: main.go
secure: always
env_variables:
ENVIRONMENT_VAR1: 'some key'
ENVIRONMENT_VAR2: 'some key'
ENVIRONMENT_VAR3: 'some key'
我使用os.Getenv("ENVIRONMENT_VAR1")
来获取这个键,当我在本地运行时它可以工作,但是在部署到Google App Engine上时无法工作。
英文:
I've specified my environment variables in app.yaml and it's being fetched when I'm running it on my local machine but once I have it deployed - it's not fetching it.
Here's how I've set it up:
application: some-application
version: 1
runtime: go
api_version: go1
threadsafe: true
handlers:
- url: /.*
script: main.go
secure: always
env_variables:
ENVIRONMENT_VAR1: 'some key'
ENVIRONMENT_VAR2: 'some key'
ENVIRONMENT_VAR3: 'some key'
And I'm using os.Getenv("ENVIRONMENT_VAR1")
to retrieve the key and it works when I run it on my local but fails to work when deployed on google app engine.
答案1
得分: 3
在官方文档中没有记录:定义环境变量,但是在生产环境中在app.yaml
中定义的环境变量在调用init()
函数之前不会被设置。它们只会在处理第一个请求之前被设置。
这个问题在这里有报告。引用一个AppEngine工程师的回答:
> 是的。由于实现的性质,不幸的是,在您的init函数中无法使用环境变量。
虽然它们与请求无关,但它们在所有init函数运行之后才被设置,但在处理第一个请求之前被设置。
> 因此,您可以在主处理程序中使用sync.DoOnce根据环境变量的值执行所需的任何操作,因为在那个时候它将被正确设置。
使用Once.Do()
实现的示例:
var once = sync.Once{}
func MainHandler(w http.ResponseWriter, r *http.Request) {
once.Do(mysetup)
// 在这里执行常规操作
}
func mysetup() {
// 此函数仅执行一次。在这里读取/使用环境变量。
var1 := os.Getenv("ENVIRONMENT_VAR1")
_ = var1 // 使用var1
}
英文:
It is undocumented in the official doc: Defining environment variables, but environment variables defined in app.yaml
in production are not set before init()
functions are called. They are only set before serving the first request.
This issue was reported here. Quoting an AppEngine engineer's answer:
> Right. Due to the nature of the implementation, environment variables are not available in your init functions, unfortunately.
Although they are not tied to requests, they are not set until after all the init functions have already run, but are set before the first request is handled.
> As a result, you could use a sync.DoOnce in your main handler to perform any actions required based on the value of an environment variable since it will be properly set by that time.
Example of achieving this with Once.Do()
:
var once = sync.Once{}
func MainHandler(w http.ResponseWriter, r *http.Request) {
once.Do(mysetup)
// do your regular stuff here
}
func mysetup() {
// This function is executed only once. Read / use env vars here.
var1 := os.Getenv("ENVIRONMENT_VAR1")
_ = var1 // use var1
}
答案2
得分: 0
icza提供的答案对我有用。此外,我将once.Do()调用放在/_ah/start方法的处理程序中,以便在GAE启动我的应用程序时立即调用它。
英文:
The answer icza provided worked for me. In addition, I put the once.Do() call in a handler for the /_ah/start method so that it would be called immediately when GAE started up my application.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论