当前位置: 首页 > article >正文

go项目多环境配置

1.java项目配置加载最佳实践

在 Spring Boot 项目中,配置文件的加载和管理是开发过程中不可或缺的一部分。Spring Boot 提供了一套灵活且强大的机制来加载配置文件,使得开发者能够根据不同的环境和需求轻松地管理配置。当多个位置存在相同的配置文件时,springboot会先加载优先级高的配置数据。

springboot加载的逻辑比较复杂,简化版的生产模式大致会以下面的思路:

  1. 对于应用程序本身的内部配置参数,不希望运维同学修改,例如关于spring本身的参数,这类配置统一放在application.xml或application.yml
    spring:
      profiles:
        active: dev
      servlet:
        multipart:
          max-file-size: 50MB
          max-request-size: 50MB
      main:
        banner-mode: off
      ##缓存
      cache:
        type: REDIS
        redis:
          timeToLive: 3600s
          cacheNullValues: true
  2. 在本地开发环境,通过配置spring变量,例如spring.profiles.active=dev,启用多环境配置,读取java项目resources目录下的pplication-dev. yml文件
  3. 在生产环境,如果运维希望覆盖某些配置,例如各种中间件(mysql,s3,redis等等)。则在可执行jar包同级目录下新建一个文件,例如application-prod. yml,并在启动脚本里显式申明 --spring.profiles.active=prod,启用环境变量

     nohup  java  $JVM_ARGS  -jar $jarName  --spring.profiles.active=prod  >  output.txt 2>&1  &

2.Go模仿springboot配置加载策略 

2.1.go项目多环境配置目标

在Go项目,我们也来模仿springboot的配置加载策略,实现以下的效果:

  1. 优先读default.yml文件,应用程序内部配置,项目打包成二进制可执行文件也会嵌入该配置
  2. 在开发环境,若环境变量为xxx,则读取config-xxx.yml(环境变量默认为dev) 
  3. 在生产环境(打包成二进制可执行文件),若环境变量为yyy,则读取config-yyy.yml(环境变量默认为dev)

2.2.使用viper加载配置

在 Go 项目中,Viper 是一个流行的库,用于处理配置文件。它支持多种格式的配置文件,包括 JSON、TOML、YAML 等,并且可以从不同的来源加载配置,如文件、环境变量、命令行参数等。Viper 也支持配置文件的热重载,这意味着在不重启应用程序的情况下,可以重新加载配置文件的更改。

安装命令: go get github.com/spf13/viper

假设我们有一个配置结构体,存储mysql的路径,以及绑定的socket服务地址,如下:

type Config struct {
	DbUrl     string
	ServerUrl string
}

在项目工程新建一个目录,叫做config,并新建一个default.yml的文件,文件内容

db:
  url: root:123456@tcp(localhost:3306)/game_user?charset=utf8mb4&parseTime=True&loc=Local

server:
  addr: 127.0.0.1:9090

 使用viper进行加载,相关代码如下:

    v := viper.New()
	// 设置配置文件名称(不包括扩展名)
	v.SetConfigName("default") // 配置文件名称(不包括扩展名)
	// 设置配置文件类型
	v.SetConfigType("yml")
	// 添加配置文件搜索路径
	v.AddConfigPath("./config")         
	// 读取配置文件
	if err := v.ReadInConfig(); err != nil {
		fmt.Printf("Error reading config: %s\n", err)
		return
	}
    ServerConfig = Config{
		DbUrl:     v.GetString("db.url"),
		ServerUrl: v.GetString("server.addr"),
	}
	fmt.Println("dbUrl", ServerConfig.DbUrl)
	fmt.Println("serverAddr", ServerConfig.ServerUrl)

在本地开发环境,程序运行正常,然而,当程序打包成二进制程序再执行,会报错表示找不到配置文件

这是因为,go build默认只会编译.go文件而不会处理其余静态资源,解决方案,可以引入go-bindata,将配置文件转化为go代码。从 Go 1.16 开始,也可以使用 embed 包将配置文件嵌入到二进制文件中。幸运的是,viper跟embed包搭配起来非常方便。

//go:embed default.yml
var configFS embed.FS

v := viper.New()
v.SetConfigType("yml")
f, err := configFS.Open("default.yml")
if err != nil {
	panic(fmt.Errorf("failed to open config file: %w", err))
}
defer f.Close()
// 从 io.Reader 读取配置
if err := v.ReadConfig(f); err != nil {
	panic(fmt.Errorf("failed to read config: %w", err))
}

根据环境变量读取对应的配置文件,覆盖同名参数

下面实现使用多环境配置,例如config-dev.yml,覆盖同名参数。在config目录下新建一个文件config-dev.yml,编辑内容

server:
  addr: 127.0.0.1:9091

追加代码,如下:

    // 允许 Viper 读取环境变量
	v.AutomaticEnv()
	replacer := strings.NewReplacer(".", "_")
	v.SetEnvKeyReplacer(replacer)

	// 获取环境变量,确定要加载的配置文件
	env := os.Getenv("ENV")
	if env == "" {
		env = "dev"
	}
	v.SetConfigName("config-" + env)
	// ./config路径在开发及部署环境均适用
	v.AddConfigPath("./config")
	// 再次读取配置文件,这次是根据环境变量,使用合并配置的方法确保旧配置被替换
	if err := v.MergeInConfig(); err != nil {
		panic(fmt.Errorf("failed to read config: %w", err))
	}

这里的代码  v.AddConfigPath("./config") 非常关键,它确保了无论是在开发环境还是生产环境,都能加载到对应的多环境配置文件。

在开发环境,由于main.go启动入口与config目录在同一级,且参数里的路径是相应于main函数,而不是代码所在的文件,开发环境加载成功。

在生产环境,我们只需在可执行程序,例如myapp.exe同级目录新建一个config目录,目录下添加一个config-prod.yml即可。

完整的代码如下,去掉注释,空行的话,也就区区50行左右,可以说,viper非常牛逼

package config

import (
	"embed"
	"fmt"
	"github.com/spf13/viper"
	"os"
	"strings"
)

type Config struct {
	DbUrl     string
	ServerUrl string
}

//go:embed default.yml
var configFS embed.FS

var (
	ServerConfig Config
)

// 多环境配置读取规则:
// 加载顺序: default -> 根据开发环境或者部署环境读取相应子目录config/config-env文件
// 先加载的配置会被后加载的同名配置所替换!!!!
// 1.优先读default.yml文件,应用程序内部配置,项目打包成二进制可执行文件也会嵌入该配置
// 2.在开发环境,若环境变量为xxx,则读取config-xxx.yml(环境变量默认为dev)
// 3.在部署环境(打包成二进制可执行文件),若环境变量为yyy,则读取config-yyy.yml(环境变量默认为dev)
func init() {
	// 创建 Viper 实例
	v := viper.New()
	v.SetConfigType("yml")
	// 打包后的二进制文件也要
	f, err := configFS.Open("default.yml")
	if err != nil {
		panic(fmt.Errorf("failed to open config file: %w", err))
	}
	defer f.Close()
	// 从 io.Reader 读取配置
	if err := v.ReadConfig(f); err != nil {
		panic(fmt.Errorf("failed to read config: %w", err))
	}

	// 允许 Viper 读取环境变量
	v.AutomaticEnv()
	replacer := strings.NewReplacer(".", "_")
	v.SetEnvKeyReplacer(replacer)

	// 获取环境变量,确定要加载的配置文件
	env := os.Getenv("ENV")
	if env == "" {
		env = "dev"
	}
	v.SetConfigName("config-" + env)
	// ./config路径在开发及部署环境均适用
	v.AddConfigPath("./config")
	// 再次读取配置文件,这次是根据环境变量,使用合并配置的方法确保旧配置被替换
	if err := v.MergeInConfig(); err != nil {
		panic(fmt.Errorf("failed to read config: %w", err))
	}

	ServerConfig = Config{
		DbUrl:     v.GetString("db.url"),
		ServerUrl: v.GetString("server.addr"),
	}
	fmt.Println("dbUrl", ServerConfig.DbUrl)
	fmt.Println("serverAddr", ServerConfig.ServerUrl)
}

 完整代码请移步:

--> go游戏服务器


http://www.kler.cn/news/315109.html

相关文章:

  • Redis中的数据结构详解与示例
  • Java笔试面试题AI答之单元测试JUnit(7)
  • Winform中使用MySQL数据库
  • Hutool:Java开发者的瑞士军刀
  • 2.使用 VSCode 过程中的英语积累 - Edit 菜单(每一次重点积累 5 个单词)
  • 如何在 Ubuntu 16.04 服务器上安装 Python 3 并设置编程环境
  • JUC并发编程
  • 第二十一节:学习Redis缓存数据库的Hash操作(自学Spring boot 3.x的第五天)
  • 深度学习02-pytorch-08-自动微分模块
  • OctoSQL 查询大量数据库和文件格式
  • Wireshark学习使用记录
  • 学习笔记JVM篇(三)
  • Jumpsever
  • yolov8改进|引入ScConv,轻量化网络
  • Go语言并发编程之Channels详解
  • windows安装Anaconda教程
  • 自学笔记之TVM编译器框架 ,核心特性,模型优化概述,AI应用落地
  • [001-02-001].第2节:java开发环境搭建
  • UE5学习笔记22-武器瞄准和武器自动开火
  • Python计算机视觉 第10章-OpenCV
  • 对网页聊天项目进行性能测试, 使用JMeter对于基于WebSocket开发的webChat项目的聊天功能进行测试
  • Shell篇之编写apache启动脚本
  • Machine Learning Specialization 学习笔记(4)
  • MySQL RANGE 分区规则
  • C# WPF 为何能成为工控上位机开发的首选
  • 常见中间件漏洞(Jboss)靶场
  • PyTorch 目标检测教程
  • 图神经网络的新篇章:通用、强大、可扩展的图变换器
  • 容器技术--Dockerfile 构建镜像
  • 加密与安全_优雅存储二要素(AES-256-GCM )