使用gin框架构建一个简单的微服务


一个功能齐全的微服务可能需要下面几个功能:

  • 读取命令行参数

  • 读取配置文件

  • 路由

  • 优雅退出

  • 操作数据库

这里实现一个微服务的雏形,实现上面除了操作数据库以外的四个功能,方便以后参考。

想要运行该源码,只需要准备一个配置文件/tmp/config.yaml:

log_path: /tmp/logstash.log.%Y%m%d%H%M # 定义日志文件名称格式

然后执行命令:

go run main.go --config=/tmp/config.yaml

其中使用到的工具库包括:

"github.com/gin-gonic/gin" 路由功能
"github.com/fvbock/endless" 优雅退出
"github.com/spf13/viper" 读取配置文件
rotatelogs "github.com/lestrrat-go/file-rotatelogs" 日志定时清除
"flag" 读取命令行参数

源码:

package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/fvbock/endless"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/spf13/viper"
)

func main() {
	StartServer()
}

func StartServer() {
	// 程序启动命令:go run main.go --config=/tmp/config.yaml (文件内容:log_path: /tmp/logstash.log.%Y%m%d%H%M)

	// 从启动命令读取配置文件路径:config(string类型)
	var configFile = flag.String("config", "", "set config file path by: -config=/path/to/log_file")
	flag.Parse()
	if *configFile == "" {
		panic("please set config file path by: -config=/path/to/log_file")
	}
	fmt.Printf("log file path: %s\n", *configFile)

	// 使用viper读取配置文件
	config := viper.New()
	config.SetConfigFile(*configFile)
	err := config.ReadInConfig()
	if err != nil {
		panic(fmt.Sprintf("failed to read configuration file: %s", *configFile))
	}

	// 日志文件:logstash.log.202105251600;每1小时产生一个日志文件;日志文件24小时以后自动清理
	log_path := config.GetString("log_path")
	logFile, err := rotatelogs.New(log_path,
		rotatelogs.WithRotationTime(time.Duration(1)*time.Hour),
		rotatelogs.WithMaxAge(time.Duration(24)*time.Hour))
	if err != nil {
		log.Fatalln("fail to create log file!")
	}
	log := log.New(logFile, "", log.Ldate|log.Ltime|log.Lshortfile)

	// gin.SetMode(gin.ReleaseMode)
	// gin 的日志输出到日志文件以及控制台
	gin.DefaultWriter = io.MultiWriter(logFile, os.Stdout)
	router := gin.Default()

	v1 := router.Group("/api/v1", func(c *gin.Context) {
		log.Println("group v1...")
	})
	{
		v1.GET("/configs/list", func(c *gin.Context) {
			log.Println("v1 configs/list, wait 10 seconds...")
			time.Sleep(10 * time.Second)
			c.JSON(http.StatusOK, "action: list")
			log.Println("v1 configs/list finished")
		})
		v1.GET("/configs/add", func(c *gin.Context) {
			log.Println("v1 configs/add wait 5 seconds")
			time.Sleep(5 * time.Second)
			c.JSON(http.StatusOK, "action: add")
			log.Println("v1 configs/add finished")
		})
	}
	// SIGHUP will trigger a fork/restart
	// syscall.SIGINT and syscall.SIGTERM will trigger a shutdown of the server (it will finish running requests)
	endless.ListenAndServe(":8080", router)
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM