1

微服务的可观测性大致分为三大类:Metrics,Tracing 和 Logging

Metrics 监控侧重于技术指标的收集与观测,如服务调用 QPS、响应时间、错误率和资源使用率。
可以使用Prometheus来监控. (
Promtheus 如何使用: https://segmentfault.com/a/11...
PromQL查询:https://segmentfault.com/a/11... )

Logging 侧重于运行日志的采集、存储与检索,通常使用ELK, 可以使用 fileBeat,logurs 等组件,来记录。

Tracing 则偏向于调用链的串联、追踪与 APM 分析,服务与服务之间的调用耗时等等,链路追踪。
对于微服务调用链的监控,开源组件推荐zipkin Jaeger
(jaeger使用: https://segmentfault.com/a/11...)


Prometheus和Grafana用于度量指标收集、监控和警报
Jaeger、开源组件推荐zipkin用于分布式全链路追踪
Kiali为Istio提供基于服务网格的微服务可视化


参考: https://www.cnblogs.com/whuan...

环境安装:
docker下进安装zipkin

docker run -d -p 9411:9411 openzipkin/zipkin

一、对grpc服务进行监控

服务端

const (
  serviceName        = "simple_zipkin_server"
    zipkinAddr         = "http://127.0.0.1:9411/api/v1/spans"
    zipkinRecorderAddr = "127.0.0.1:9000"
)

/*
    获取zipkin的tracer对象,并把tracer封装成ServerInterceptor注入到grpc.ServerOption中
*/
func NewZipkinTracer(opts []grpc.ServerOption) (opentracing.Tracer, []grpc.ServerOption, error) {
    collector, err := zipkin.NewHTTPCollector(zipkinAddr)
    if err != nil {
        log.Fatal(err.Error())
        return nil, opts, err
    }
    recorder := zipkin.NewRecorder(collector, true, zipkinRecorderAddr, serviceName)
    tracer, err := zipkin.NewTracer(recorder, zipkin.ClientServerSameSpan(true), zipkin.TraceID128Bit(true))
    if err != nil {
        log.Fatal(err.Error())
        return nil, opts, err
    }
    opts = append(opts, grpc_middleware.WithUnaryServerChain(
        otgrpc.OpenTracingServerInterceptor(tracer, otgrpc.LogPayloads()),
    ))
    return tracer, opts, nil
}


func main() {
  //...
  go func() {
    //...
    var opts = []grpc.ServerOption{grpc.Creds(cred)}
        _, opts, err = NewZipkinTracer(opts)
        if err != nil {
            log.Fatal(err.Error())
            return
        }
    rpcserver := grpc.NewServer(opts...)
    //...
  }
  //...
}

客户端

const (
  serviceName        = "simple_zipkin_server"
    zipkinAddr         = "http://127.0.0.1:9411/api/v1/spans"
    zipkinRecorderAddr = "127.0.0.1:9000"
)

/*
    获取zipkin的tracer对象,并把tracer封装成ClientInterceptor注入到grpc.DialOption中
*/
func NewZipkinTracer(opts []grpc.DialOption) (opentracing.Tracer, []grpc.DialOption, error) {
    collector, err := zipkin.NewHTTPCollector(zipkinAddr)
    if err != nil {
        log.Fatal(err.Error())
        return nil, opts, err
    }
    recorder := zipkin.NewRecorder(collector, true, zipkinRecorderAddr, serviceName)
    tracer, err := zipkin.NewTracer(recorder, zipkin.ClientServerSameSpan(true), zipkin.TraceID128Bit(true))
    if err != nil {
        log.Fatal(err.Error())
        return nil, opts, err
    }
    opts = append(opts, grpc.WithUnaryInterceptor(
        otgrpc.OpenTracingClientInterceptor(tracer, otgrpc.LogPayloads()),
    ))
    return tracer, opts, nil
}


func main() {
  //...
  var opts = []grpc.DialOption{grpc.WithTransportCredentials(creds)}
    _, opts, err = NewZipkinTracer(opts)
    if err != nil {
        log.Fatal(err.Error())
        return
    }
    conn, err := grpc.Dial(fmt.Sprintf("%v:%d", addr.Service.Address, addr.Service.Port), opts...)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
  //...
}

先后运行server.go和client.go,进行一次grpc的调用;
访问http://localhost:9411/zipkin,选择"serviceName"为"simple_zipkin_server"

image.png


二、对Gin框架的Web服务进行监控

var (
    zkReporter reporter.Reporter
    zkTracer   opentracing.Tracer
)

const (
    serviceName     = "zipkin_gin_server"
    serviceEndpoint = "localhost:8080"
    zipkinAddr      = "http://127.0.0.1:9411/api/v2/spans"
)

func initZipkinTracer(engine *gin.Engine) error {
    zkReporter = zkHttp.NewReporter(zipkinAddr)
    endpoint, err := zipkin.NewEndpoint(serviceName, serviceEndpoint)
    if err != nil {
        log.Fatalf("unable to create local endpoint: %+v\n", err)
        return err
    }
    nativeTracer, err := zipkin.NewTracer(zkReporter, zipkin.WithTraceID128Bit(true), zipkin.WithLocalEndpoint(endpoint))
    if err != nil {
        log.Fatalf("unable to create tracer: %+v\n", err)
        return err
    }
    zkTracer = zkOt.Wrap(nativeTracer)
    opentracing.SetGlobalTracer(zkTracer)
  // 将tracer注入到gin的中间件中
    engine.Use(func(c *gin.Context) {
        span := zkTracer.StartSpan(c.FullPath())
        defer span.Finish()
        c.Next()
    })
    return nil
}

func main() {
  engine := gin.Default()
  
  err := initZipkinTracer(engine)
    if err != nil {
        panic(err)
    }
    defer zkReporter.Close()
  
  engine.GET("/ping", func(c *gin.Context) {
        c.JSON(http.StatusOK, "pong")
    })
 
  //...
  engine.Run(":8080")
}

参考文章:
https://github.com/EDDYCJY/go...

http://www.dockone.io/article...

https://itnext.io/kubernetes-...

https://blog.csdn.net/feizaoS...


goper
413 声望26 粉丝

go 后端开发