准备工作

  • docker运行zipkin服务
docker run -d -p 9411:9411 openzipkin/zipkin

一、对grpc服务进行监控

关于Golang使用grpc的内容请转移到这边文章Golang使用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",然后点击右边的搜索按钮,即可看到如下图的调用链监控信息;

Golang使用zipkin进行链路监控-LMLPHP

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

关于Golang使用gin框架构建Web服务的内容请转移到这边文章Go语言Web知识(一) 认识Gin框架

代码改造

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")
}

测试

  • 访问http://localhost:8080/ping,返回"pong",进行一次http请求;
  • 访问http://localhost:9411/zipkin,选择"serviceName"为"zipkin_gin_server",然后点击右边的搜索按钮,即可看到如下图的调用链监控信息;

Golang使用zipkin进行链路监控-LMLPHP

03-26 23:07