要求:根据golang中的环境(如QA,PROD)配置数据库连接。例如:
{"QA":{
"host":"124.44.2.2",
"port":"1234"
},
"PROD":{
"host":"125.65.23.64",
"port":"1234"
}
}
我可以在JSON / YAML等配置它,但问题是当我们构建go时,构建文件不包含非go文件。因此,在将构建部署到不同的实例时,它会丢失配置文件。
另一种解决方案,我尝试在自己设置配置(通过设置常量)。然后根据作为参数传递的环境名称读取常量。但是在docker中,参数在构建文件名后传递,而在go中,只有在构建文件之前传递参数时才能读取参数。
有人推荐最佳解决方案吗?
您通常不会在构建时烘焙运行时环境的配置。您需要一个通用且独立于部署环境的构建二进制(或Docker映像或其他)。应在运行时提供外部资源的任何配置,以便在应用程序启动时延迟绑定配置。
考虑可在互联网上免费获得的第三方组件。它们以通用的方式编写,使其不仅适用于您的环境,而且适用于下载它们的任何人的环境。
这种方法要求您在将应用程序部署到开发,测试,生产或类似方法时提供一种机制来提供配置指令。
您可以使用几种机制来实现此目的。以下列表并非详尽无遗:
在应用程序的顶层定义环境变量,并在生成应用程序二进制文件时传递这些变量。例如,您可以定义环境变量DATABASE_HOSTADDR
并将其设置为等于所需数据库服务器的host:port
。在您的main
方法或类似方法中:
// Load database host address
dbHostAddr, ok := os.LookupEnv("DATABASE_HOSTADDR")
if !ok || dbHostAddr == "" {
log.Fatal("DATABASE_HOSTADDR not specified")
}
// Do something here to use the value retrieved from the env var,
// splitting on the port separator (:) if necessary to retrieve
// the hostname and port number as separate values.
您可以使用库来解析启动时提供给二进制文件的参数。因此,例如,如果您的应用程序名称为somebinary
,则可以使用以下命令调用它:
./somebinary dbserver:12345
或者,如果您使用命令行标志(由Go的内置flag
库提供,等等):
./somebinary --db dbserver:12345
使用标志的示例:
package main
import (
"flag"
"log"
)
var dbHostAddr string
func main() {
flag.Parse()
if dbHostAddr == "" {
log.Fatalf("--db flag must be specified")
}
// Do something with dbHostAddr
}
func init() {
// Bind desired flags
flag.StringVar(&dbHostAddr, "db", "", "Database connection path, in format host:port")
}
使用os.Args
的示例:
package main
import (
"log"
"os"
)
func main() {
if len(os.Args) < 2 {
log.Fatalf("database host address not supplied")
}
dbHostAddr := os.Args[1]
// Do something with dbHostAddr
}
Go支持以各种格式解析配置文件,如果不包含,则有最受欢迎的库。如果您的配置要求更复杂,请考虑编写配置文件并将其与应用程序一起部署。
配置管理解决方案(例如Ansible或Salt)将有助于在代码中定义部署过程和基础架构配置,并可能为您生成配置。如果您的配置简单且静态,则可以将其直接存储到源代码控制中,并将其打包为构建过程中的构建工件。