鏈路追蹤 Zipkin
Zipkin是 Twitter 的一個開源專案,基于 Google Dapper實作,使用它來收集各個服務器上請求鏈路的跟蹤資料,及時地發現系統中出現的延遲問題,找出系統的性能瓶頸,

專案中應用
完整代碼:
https://github.com/Justin02180218/micro-kit
組態檔
zipkin:
url: "http://zipkin-server:9411/api/v2/spans"
service_name: "user-service"
reporter:
timeout: 5
batch_size: 1000
batch_interval: 3
max_backlog: 10000
在hosts中配置zipkin-server域名
config.go
type ZipkinConfig struct {
Url string `json:"url" yaml:"url"`
ServiceName string `json:"service_name" yaml:"service_name"`
Reporter struct {
Timeout int `json:"timeout" yaml:"timeout"`
BatchSize int `json:"batch_size" yaml:"batch_size"`
BatchInterval int `json:"batch_interval" yaml:"batch_interval"`
MaxBacklog int `json:"max_backlog" yaml:"max_backlog"`
}
}
pkg/tracers
在 pkg 下新建目錄 tracers,創建 zipkin.go 檔案:

代碼如下:
// 創建 Reporter
func NewZipkinReporter(zipkinCfg *configs.ZipkinConfig) reporter.Reporter {
return zipkinhttp.NewReporter(
zipkinCfg.Url,
zipkinhttp.Timeout(time.Duration(zipkinCfg.Reporter.Timeout)*time.Second),
zipkinhttp.BatchSize(zipkinCfg.Reporter.BatchSize),
zipkinhttp.BatchInterval(time.Duration(zipkinCfg.Reporter.BatchInterval)*time.Second),
zipkinhttp.MaxBacklog(zipkinCfg.Reporter.MaxBacklog),
)
}
// 創建 Tracer
func NewZipkinTracer(serviceName string, reporter reporter.Reporter) *gozipkin.Tracer {
zEP, _ := gozipkin.NewEndpoint(serviceName, "")
tracerOptions := []gozipkin.TracerOption{
gozipkin.WithLocalEndpoint(zEP),
}
tracer, err := gozipkin.NewTracer(reporter, tracerOptions...)
if err != nil {
fmt.Println(err)
return nil
}
return tracer
}
func Zipkin(tracer *gozipkin.Tracer, name string) endpoint.Middleware {
return zipkin.TraceEndpoint(tracer, name)
}
func MakeHttpServerOptions(zipkinTracer *gozipkin.Tracer, name string) []http.ServerOption {
zipkinServiceTrace := zipkin.HTTPServerTrace(zipkinTracer, zipkin.Name(name))
options := []http.ServerOption{zipkinServiceTrace}
return options
}
func MakeHttpClientOptions(zipkinTracer *gozipkin.Tracer, name string) []http.ClientOption {
zipkinClientTrace := zipkin.HTTPClientTrace(zipkinTracer, zipkin.Name(name))
options := []http.ClientOption{zipkinClientTrace}
return options
}
func MakeGrpcServerOptions(zipkinTracer *gozipkin.Tracer, name string) []grpc.ServerOption {
zipkinServiceTrace := zipkin.GRPCServerTrace(zipkinTracer, zipkin.Name(name))
options := []grpc.ServerOption{zipkinServiceTrace}
return options
}
func MakeGrpcClientOptions(zipkinTracer *gozipkin.Tracer, name string) []grpc.ClientOption {
zipkinClientTrace := zipkin.GRPCClientTrace(zipkinTracer, zipkin.Name(name))
options := []grpc.ClientOption{zipkinClientTrace}
return options
}
endpoint層
修改book-rpc-endpoint.go,以library-user-service為例,其他微服務相同,
func MakeFindBooksEndpoint(instance string, tracer *gozipkin.Tracer) endpoint.Endpoint {
conn, err := grpc.Dial(instance, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
return nil
}
findBooksEndpoint := grpctransport.NewClient(
conn, "book.Book", "FindBooksByUserID",
encodeGRPCFindBooksRequest,
decodeGRPCFindBooksResponse,
pbbook.BooksResponse{},
tracers.MakeGrpcClientOptions(tracer, "grpc-transport-findBooks")...,
).Endpoint()
return findBooksEndpoint
}
transport層
修改user_transport.go,以library-user-service為例,其他微服務相同,
func NewHttpHandler(ctx context.Context, endpoints *endpoint.UserEndpoints, tracer *gozipkin.Tracer) *gin.Engine {
r := utils.NewRouter(ctx.Value("ginMod").(string))
e := r.Group("/api/v1")
{
e.POST("register", func(c *gin.Context) {
kithttp.NewServer(
endpoints.RegisterEndpoint,
decodeRegisterRequest,
utils.EncodeJsonResponse,
tracers.MakeHttpServerOptions(tracer, "transport-register")...,
).ServeHTTP(c.Writer, c.Request)
})
......
}
}
修改 main.go
以 library-user-service 為例,其他微服務相同,
reporter := tracers.NewZipkinReporter(config.Conf.ZipkinConfig)
defer reporter.Close()
tracer := tracers.NewZipkinTracer(config.Conf.ZipkinConfig.ServiceName, reporter)
findBooksEndpoint := endpoint.MakeFindBooksEndpoint
grpcClient := registers.GRPCClient(config.Conf, findBooksEndpoint, tracer, logger)
hystrix.ConfigureCommand("Find books", hystrix.CommandConfig{Timeout: 1000})
grpcClient = circuitbreakers.Hystrix("Find books", "book-rpc-service currently unavailable")(grpcClient)
grpcClient = tracers.Zipkin(tracer, "grpc-endpoint-findBooks")(grpcClient)
......
userEndpoints := &endpoint.UserEndpoints{
RegisterEndpoint: tracers.Zipkin(tracer, "endpoint-register")(ratelimit(endpoint.MakeRegisterEndpoint(userService))),
FindByIDEndpoint: tracers.Zipkin(tracer, "endpoint-findByID")(ratelimit(endpoint.MakeFindByIDEndpoint(userService))),
FindByEmailEndpoint: tracers.Zipkin(tracer, "endpoint-findByEmail")(ratelimit(endpoint.MakeFindByEmailEndpoint(userService))),
FindBooksByUserIDEndpoint: tracers.Zipkin(tracer, "endpoint-findBooks")(ratelimit(endpoint.MakeFindBooksByUserIDEndpoint(userService))),
HealthEndpoint: tracers.Zipkin(tracer, "endpoint-health")(ratelimit(endpoint.MakeHealthEndpoint(userService))),
}
啟動 Zipkin
使用 Docker 啟動 zipkin
docker pull openzipkin/zipkin
docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin
啟動服務,通過網關訪問 library-user-service 微服務的 findBooksByUserID 介面,
在瀏覽器地址欄輸入:http://zipkin-server:9411/
點擊 "RUN QUERY" 按鈕

繼續點擊第一行的 "SHOW" 按鈕

下一篇文章,我們在各個微服務中加入服務監控功能,
完整代碼:
https://github.com/Justin02180218/micro-kit
更多【分布式專輯】【架構實戰專輯】系列文章,請關注公眾號

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/306207.html
標籤:其他
