#go-moda golang 通用的 grpc http 基础开发框架
- transport: 集成 http(echo、gin)和 grpc。
- 统一服务启动入口
- config: 通用的配置文件读取模块,支持 toml、yaml 和 json 格式。
- logger: 结构化 统一 logger API, 已 新增 slog 替换zap logger
- pprof: 分析性能
- tracing: openTelemetry 实现微务链路追踪
package main
import (
"net/http"
"github.com/gin-gonic/gin"
app "github.com/webws/go-moda"
examplepb "github.com/webws/go-moda/example/pb/example"
"github.com/webws/go-moda/logger"
"google.golang.org/grpc"
)
var ServerName string
func main() {
// http server default gin
a := app.NewServer().AddHttpServer(":8081", registerHttp)
// grpc
a.AddGrpcServer(":8082", func(sr grpc.ServiceRegistrar) {
examplepb.RegisterExampleServiceServer(sr, &examplepb.ExampleServer{})
})
if err := a.Run(); err != nil {
logger.Fatalw("app run error", "err", err)
}
}
func registerHttp(g *gin.Engine) {
g.GET("/helloworld", func(c *gin.Context) {
logger.Debugw("Hello World")
c.JSON(http.StatusOK, http.StatusText(http.StatusOK))
})
}
go run ./
- 请求 http url https://localhost:8081/helloworld
- grpc 服务 使用 gRPC 客户端调用 SayHello 方法 example_grpc
// "github.com/webws/go-moda/config"
//...
conf := &Config{}
if err := config.NewConfigWithFile("./conf.toml").Load(conf); err != nil {
logger.Fatalw("NewConfigWithFile fail", "err", err)
}
//...
package main
import "github.com/webws/go-moda/logger"
func main() {
// 格式化打印 {"time":"2023-09-08T01:25:21.313463+08:00","level":"INFO","msg":"info hello slog","key":"value","file":"/Users/xxx/w/pro/go-moda/example/logger/main.go","line":6}
logger.Infow("info hello slog", "key", "value") // 打印json
logger.Debugw("debug hello slog", "key", "value") // 不展示
logger.SetLevel(logger.DebugLevel) // 设置等级
logger.Debugw("debug hello slog", "key", "value") // 设置了等级之后展示 debug
// with
newLog := logger.With("newkey", "newValue")
newLog.Debugw("new hello slog") // 会打印 newkey:newValue
logger.Debugw("old hello slog") // 不会打印 newkey:newValue
}
- 使用 opentelemetry 实现微服务链路追踪,目前 exporter 支持 jaeger
- 示例集成了docker 环境,支持 make deploy 同时启动 jaeger,api1,api2,api3,grpc 服务
- 详细示例请看:tracing_example
- server 端使用
var ServerName string
func main() {
// http server default gin
a := app.NewServer().AddHttpServer(":8081", registerHttp)
// grpc
a.AddGrpcServer(":8082", func(sr grpc.ServiceRegistrar) {
pbexample.RegisterExampleServiceServer(sr, &ExampleServer{})
})
// tracing
// Need to start jaeger
shutdown, err := tracing.InitJaegerProvider("https://localhost:14268/api/traces", ServerName)
if err != nil {
logger.Fatalw("InitJaegerProvider", "err", err)
}
defer shutdown(context.Background())
a.SetTracing(true)
if err := a.Run(); err != nil {
logger.Fatalw("app run error", "err", err)
}
}
- tracing.InitJaegerProvider 初始化 Jaeger Provider
- a.SetTracing(true) 设置tracing为true,内部将 请求头的参数 转换成 ctx
- client端: 封装了 CallAPI 方法, 已将span ctx 信息注入到请求头
// ...
_, err := modahttp.CallAPI(ctx, url, "POST", nil)
启动服务默认开启 pprof 性能分析,浏览器打开 https://localhost:8081/debug/ 查看
可视化分析 gouroutine
go tool pprof https://localhost:8081/debug/pprof/goroutine
(pprof) web
可能提示 需要先安装 graphviz, mac 下可以使用 brew 安装
brew install graphviz
- 基本http/grpc服务启动示例:basic example
- gin http 服务示例:example_gin
- echo http 服务示例:example_echo
- grpc 服务示例:example_grpc
- tracing 示例:tracing_example
- docker 本地CD示例:docker_example