Gpt微信小程序搭建的前后端流程 - 后端微服务框架的搭建(三)

Gpt微信小程序搭建的前后端流程 - 后端基础框架的搭建(三)

Gpt微信小程序 只需要几个API,API上一小节也有讲到。直接用 gin 或者 beego 简单搭web服务器就够了。我们这里还用 go-micro微服务 去搭建,主要也是为了学以致用,把之前go-micro系列播客衔接上,以及后续好的横纵向扩展。


整体的代码框架:

Gpt微信小程序搭建的前后端流程 - 后端微服务框架的搭建(三)_第1张图片

pkg通用库中用到的db数据库,redis和mq队列,大部分都是前面go-micro系列有用到的。internal内部的微服务目录也是在之前go-micro单个微服务目录格式上调整。

这里主要看配置解析, 配置解析用得是toml库, github.com/BurntSushi/toml


pkg目录

Gpt微信小程序搭建的前后端流程 - 后端微服务框架的搭建(三)_第2张图片

配置的代码解析,用一个接口(基类) IConfig

pkg/config/config.go

type IConfig interface {
	//服务名
	AppName() string
	//运行模式
	AppEnv() string

	//日志的定义
	LogFilePath() string
	LogMaxAge() int
	LogMaxSize() int
	LogBackUpNum() int

	//mysql关系型数据库
	SchemeConfig() map[string]*SchemeConfig

	//redis
	RedisConfig() map[string]*RedisConfig

	//rabbitmq
	AmqpConfig() map[string]*AmqpConfig
}

// log日志库基本配置
type LogConfig struct {
	Type         string `yaml:"Type",toml:"Type"`
	LogDir       string `yaml:"LogDir",toml:"LogDir"`
	LogName      string `yaml:"LogName",toml:"LogName"`
	LogMaxAge    int    `yaml:"LogMaxAge",toml:"LogMaxAge"`       // 日志的过期时间,单位为天
	LogMaxSize   int    `yaml:"LogMaxSize",toml:"LogMaxSize"`     // 日志文件的最大
	LogBackUpNum int    `yaml:"LogBackUpNum",toml:"LogBackUpNum"` // 日志文件最多保留个数

}

// 服务配置
type Config struct {
	ConfPath string                   //配置路径
	AppPath  string                   //项目路径
	Scheme   map[string]*SchemeConfig `yaml:"Scheme",toml:"Scheme"`
	Redis    map[string]*RedisConfig  `yaml:"Redis",toml:"Redis"`
	Amqp     map[string]*AmqpConfig   `yaml:"Amqp",toml:"Amqp"`
	Log      *LogConfig               `yaml:"Log",toml:"Log"`
}

// App 的基本配置
type AppBaseConfig struct {
	AppName string `yaml:"AppName",toml:"AppName"`
	Env     string `yaml:"Env",toml:"Env"`
	Version string `yaml:"Version",toml:"Version"` // 版本
}

type AppConfig struct {
	Config
	App AppBaseConfig
}

pkg/config/scheme.go

// 关系型数据库的配置
type SchemeConfig struct {
    // mysql pgsql
    Driver string `yaml:"Driver",toml:"Driver"`
    Dsn string `yaml:"Dsn",toml:"Dsn"`
    // 建立最大的连接数
    MaxOpenConns int `yaml:"MaxOpenConns",toml:"MaxOpenConns"`
    // 最大的空闲连接数
    MaxIdleConns int `yaml:"MaxIdleConns",toml:"MaxIdleConns"`
    // 一条连接存活的最长时间
    ConnMaxLifeTime int `yaml:"ConnMaxLifeTime",toml:"ConnMaxLifeTime"`
}

pkg/config/redis.go

// redis配置
type RedisConfig struct {
	Addr        string `yaml:"Addr",toml:"Addr"` // host:port
	Password    string `yaml:"Password",toml:"Password"`
	MaxConnNum  int    `yaml:"MaxConnNum",toml:"MaxConnNum"`
	InitConnNum int    `yaml:"InitConnNum",toml:"InitConnNum"`
	IdleTimeout int    `yaml:"IdleTimeout",toml:"IdleTimeout"`
	PingStep    int    `yaml:"PingStep",toml:"PingStep"`
	RetryTimes  int    `yaml:"RetryTimes",toml:"RetryTimes"`
}

pkg/config/amqp.go

// rabbitmq
type AmqpConfig struct {
    Addr string `toml:"Addr"`
    Port int `toml:"Port"`
    User string `toml:"User"`
    Pwd string `toml:"Pwd"`
    MaxConnection int `toml:"MaxConnection"`
    MaxChannel int `toml:"MaxChannel"`
    VirtualHost string `toml:"VirtualHost"`
    Type int `toml:"Type"`
}

对应的toml配置格式:
config/test_service/app.toml

[App]
	AppName = "test_service"
	Version = "1.0"
	Env = "dev"

[Log]
   Type = "log"             # 默认是log, 可以是redis, kafka获取是其他的,如果是其他的请在 log中实现
   LogDir = "/log"
   LogName = "error_log.log"
   LogMaxAge = 7            # 单位 day,日志最多可以保存多长时间。只有 Type 为File时才会有效
   LogMaxSize = 10          # 文件大小(M),10M
   LogBackUpNum = 10        # 文件保留最多个数

[Scheme]
	# 放置数据库连接信息
	[Scheme.base]
	    Driver = "mysql"
        Dsn = "root:root@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=true"
        MaxOpenConns = 60
        MaxIdleConns = 20
        ConnMaxLifeTime = 1200

[Redis]
    [Redis.base]
        Addr = "127.0.0.1:6379"
        Password = "11111111"
        MaxConnNum = 20
        InitConnNum = 1
        IdleTimeout = 7200      #最大idle时间
        PingStep = 10           #两次ping之间间隔
        RetryTimes = 3          #获取连接重试次数

[Amqp]
    [Amqp.publish]
        Addr = "127.0.0.1"
        Port = 5672
        User = "guest"
        Pwd = "guest"
        MaxConnection = 4
        VirtualHost = "/"
        Type = 1                # 1生产者;2消费者
    [Amqp.consume]
        Addr = "127.0.0.1"
        Port = 5672
        User = "guest"
        Pwd = "guest"
        MaxConnection = 10
        MaxChannel = 10
        VirtualHost = "/"
        Type = 2                # 1生产者;2消费者

最后的配置解析
pkg/config/parse.go

// 解析配置
func ParseConfig() {
	verifyConf()
	toml.DecodeFile(Conf.ConfPath, Conf)
}

func verifyConf() {
	if fl, err := os.Stat(Conf.ConfPath); err != nil {
		if os.IsNotExist(err) {
			fmt.Println(Conf.ConfPath)
			fmt.Printf("config file %s not exists", Conf.ConfPath)
			os.Exit(0)
		}
	} else {
		fl.Mode().Perm()
	}
}

// 获取项目当前路径
func getRunPath() string {
	rst, err := os.Getwd()
	if err != nil {
		return ""
	}
	return rst
}

这里,通用log日志库,mysql,redis,rabbitmq的配置解析和初始代码就好了,接下来就是微服务的初始化调用和启动了。


微服务目录
Gpt微信小程序搭建的前后端流程 - 后端微服务框架的搭建(三)_第3张图片

微服务初始化代码, init.goelog.go

internal/test_service/init.go

// 服务
type EmicroService struct {
	Server micro.Service
	Host   string
	Port   uint
	Addr   string
}

// 服务的自定义配置
type ServerConfig struct {
	ServerLog   map[string]*config.LogConfig
}

// 服务内部配置
type Conf struct {
	Config       *config.AppConfig  //pkg通用配置
	ServerConfig *ServerConfig
}

// 服务操作对象
var Service *EmicroService

// 日志库操作对象,对pkg的日志再封装
var Logger *zap.Logger

// 服务内部配置操作对象
var Config *Conf

func init() {
    Service = NewService()
    Config = NewConfig()
}

func NewService() *EmicroService {
    service := new(EmicroService)
    return service
}

func NewConfig() *Conf {
    return new(Conf)
}

// 初始化
func Init(confPath string) {
    //指定配置文件路径
    config.Conf.ConfPath = confPath
    
    //解析配置
    config.ParseConfig()
    
    // 处理日志文件路径和日志等级
    config.Conf.Log.LogDir = config.Conf.GetAppPath() + config.Conf.Log.LogDir + "/" + config.Conf.AppName()
    // 默认日志等级为error
    var level string
    if config.Conf.AppEnv() == "dev" {
        level = "debug"
    } else {
        level = "error"
    }
    // 初始化通用日志库
    logObj.LoggerInit(config.Conf, level)
    Logger = logObj.Logger()
    
    // 初始数据库,Redis等
    database.Init(config.Conf)
    
    // 解析服务内部自定义配置
    Config.Config = config.Configer()
    
    var serverConf = new(ServerConfig)
    serverConfPath := Config.Config.GetAppPath() + "/internal/test_service/config/server.toml"
    toml.DecodeFile(serverConfPath, serverConf)
    Config.ServerConfig = serverConf
    // 初始化自定义的log
    initServerLog(level)
}

internal/test_service/elog.go

// 服务自定义的log日志库操作对象
var ServerLogger map[string]*zap.Logger
var logLevel string

// 初始化自定义的log
func initServerLog(level string){
    ServerLogger = make(map[string]*zap.Logger, len(Config.ServerConfig.ServerLog))
    logLevel = level
    for logName, logInfo := range Config.ServerConfig.ServerLog{
        logInfo.LogDir = config.Conf.AppPath + logInfo.LogDir + string(os.PathSeparator) +logName
        log, err := newServerLog(logInfo)
        if err != nil{
            panic("init server log err:" + err.Error())
        }
        ServerLogger[logName] = log
    }
}

func newServerLog(logInfo *config.LogConfig) (*zap.Logger, error){
    var console bool
    if Config.Config.AppEnv() == "dev" {
        console = true
    }else{
        console = false
    }
    logInfo.LogName = getLogFilename()
    return logObj.CreateLogger(logLevel, console, logInfo)
}

func getLogFilename() string {
    currentTime := time.Now()
    return currentTime.Format("2006-01-02") + ".log"
}

启动代码在internal/test_service/server/server.go,跟之前go-micro系列播客的微服务启动一样,这里不再列明。

启动脚本: cmd/test_service/main.go

package main

import(
	"emicro-go-base/internal/test_service/server"
)

func main() {
	server.RunTestService(":8080", "../../config/test_service/app.toml")
}

后端基础的框架就大概这样,一些太细的细节代码就没全贴出来了,后续具体实现API章节会再继续贴

最后

可以先体验如下的微信小程序,该专栏系列都是参考小柠AI智能聊天来展开,小程序整体的gpt交互直接,界面也容易,对我们上手仿照在实现方面也比较友好。

体验方式:
  1. 微信小程序直接搜小柠AI智能聊天
  2. 扫码下图
    小柠AI智能聊天

你可能感兴趣的:(Gpt微信小程序搭建,gpt,微信小程序,golang,微服务,openai)