乐趣区

关于go:一个-golang-通用的-grpc-http-基础开发框架

go-moda

  • golang 通用的 grpc http 根底开发框架
  • 仓库地址: [https://github.com/webws/go-moda](https://github.com/webws/go-moda
  • 仓库始终在更新, 欢送大家吐槽和指导

个性

  • transport: 集成 http(echo、gin)和 grpc。
  • tracing: openTelemetry 实现微务链路追踪
  • pprof: 剖析性能
  • config: 通用的配置文件读取模块,反对 toml、yaml 和 json 格局。
  • logger: 日志零碎模块,基于 Zap, 并反对全局日志和模块日志。

    疾速应用

    conf.toml
    http_addr = ":8081"
    grpc_addr = ":8082"
    启用 http(gin) 和 grpc 服务
package main

import (
    "context"
    "net/http"

    "github.com/gin-gonic/gin"
    app "github.com/webws/go-moda"
    "github.com/webws/go-moda/config"
    pbexample "github.com/webws/go-moda/example/pb/example"
    "github.com/webws/go-moda/logger"
    modagrpc "github.com/webws/go-moda/transport/grpc"
    modahttp "github.com/webws/go-moda/transport/http"
)

var ServerName string

type Config struct {
    HttpAddr string `json:"http_addr" toml:"http_addr"`
    GrpcAddr string `json:"grpc_addr" toml:"grpc_addr"`
}

func main() {conf := &Config{}
    if err := config.NewConfigWithFile("./conf.toml").Load(conf); err != nil {logger.Fatalw("NewConfigWithFile fail", "err", err)
    }
    // http server
    gin, httpSrv := modahttp.NewGinHttpServer(modahttp.WithAddress(conf.HttpAddr),
    )
    registerHttp(gin)

    // grpc server
    grpcSrv := modagrpc.NewServer(modagrpc.WithServerAddress(conf.GrpcAddr),
    )
    grecExample := &ExampleServer{}
    pbexample.RegisterExampleServiceServer(grpcSrv, grecExample)

    // app run
    a := app.New(app.Server(httpSrv, grpcSrv),
        app.Name(ServerName),
    )
    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))
    })
}

type ExampleServer struct {pbexample.UnimplementedExampleServiceServer}

func (s *ExampleServer) SayHello(ctx context.Context, req *pbexample.HelloRequest) (*pbexample.HelloResponse, error) {return &pbexample.HelloResponse{Message: "Hello" + req.Name}, nil
}
运行
go run ./ -c ./conf.toml
``````
* 申请 http url http://localhost:8081/helloworld  
* grpc 服务 应用 gRPC 客户端调用 SayHello 办法

其余服务启用示例
1. echo http :[example_echo](https://github.com/webws/go-moda/tree/main/example/echohttp)
2. net http :[example_echo](https://github.com/webws/go-moda/blob/main/example/nethttp)
3. grpc [example_grpc](https://github.com/webws/go-moda/tree/main/example/grpc)
## pprof 性能剖析
启动服务默认开启 pprof 性能剖析,浏览器关上 http://localhost:8081/debug/ 查看
![](https://qiniu.taoluyuan.com/2023/blog20230903093830.png?imageMogr2/auto-orient/thumbnail/!70p/blur/9x0/quality/75)
可视化剖析 gouroutine

go tool pprof http://localhost:8081/debug/pprof/goroutine
(pprof) web

 可能提醒 须要先装置 graphviz, mac 下能够应用 brew 装置 

brew install graphviz

![](https://qiniu.taoluyuan.com/2023/blog20230903094758.png?imageMogr2/auto-orient/thumbnail/!70p/blur/9x0/quality/75)

## tracing 链路追踪
* 应用 opentelemetry 实现微服务链路追踪,目前 exporter 反对 jaeger 
* 示例集成了 docker 环境, 反对 make deploy 同时启动 jaeger,api1,api2,api3,grpc 服务
* 具体示例请看:[tracing_example](https://github.com/webws/go-moda/tree/main/example/tracing/moda_tracing)

1. 初始化 jaeger tracing  

import “github.com/webws/go-moda/tracing”
func main(){

//...
shutdown, err := tracing.InitJaegerProvider(conf.JaegerUrl, "grpc-server")
if err != nil {panic(err)
}
defer shutdown(context.Background())
//...

}

2. 在代码被动 tracing start

ctx, span := tracing.Start(c.Request().Context(), “api1”)
defer span.End()

3. 服务之间调用 产生的链路
   
*  server 端: 减少 WithTracing 即可 
//...
gin, httpSrv := modahttp.NewGinHttpServer(modahttp.WithAddress(conf.HttpAddr),
    modahttp.WithTracing(true),
)
 * client 端:  封装了 CallAPI 办法, 已将 span ctx 信息注入到申请头 
// ...
_, err := modahttp.CallAPI(ctx, url, "POST", nil)
    
退出移动版