Go-kratos 框架商城微服務實戰之使用者服務 (三)

Aliliin發表於2022-02-09

Go-kratos 框架商城微服務實戰之使用者服務 (三) - 鏈路追蹤

這篇主要給服務加入鏈路追蹤Tracing 。寫的不清晰的地方可看原始碼 , 歡迎大佬指教。

注:豎排 … 程式碼省略,為了保持文章的篇幅簡潔,我會將一些不必要的程式碼使用豎排的 . 來代替,你在複製本文程式碼塊的時候,切記不要將 . 也一同複製進去。

  1. jaeger 的安裝
  • docker 的安裝方式
docker run --rm --name jaeger -p14268:14268 -p16686:16686 jaegertracing/all-in-one
// 執行完畢之後,切記別退出服務
  • 瀏覽器訪問 http://127.0.0.1:16686/ 驗證是否安裝成功
  1. 專案程式碼引入
  • user/configs/config.yaml 配置檔案新增
.
.
.
trace:
  endpoint: http://127.0.0.1:14268/api/traces
  • 修改 /user/internal/conf/conf.proto 檔案
syntax = "proto3";
.
.
.

message Bootstrap {
  Server server = 1;
  Data data = 2;
  Trace trace = 3; // 新增 trace
}

.
.
.

message Trace {
  string endpoint = 1;
}
  • 根目錄執行 make config 命令,生成新的配置檔案

  • 修改 user/internal/server/grpc.go 檔案

package server

import (
    .
    .
    .
    "github.com/go-kratos/kratos/v2/middleware/tracing"     // 新增引入
)

// NewGRPCServer new a gRPC server.
func NewGRPCServer(c *conf.Server, u *service.UserService, logger log.Logger) *grpc.Server {
    var opts = []grpc.ServerOption{
        grpc.Middleware(
            recovery.Recovery(),
            tracing.Server(), // 新增 tracing
        ),
    }
    .
    .
    .
    v1.RegisterUserServer(srv, u)
    return srv
}
  • 修改 user/cmd/user/main.go 檔案
package main

import (
    .
    .
    .
    "github.com/go-kratos/kratos/v2/middleware/tracing"
    "go.opentelemetry.io/otel/exporters/jaeger"
    "go.opentelemetry.io/otel/sdk/resource"
    tracesdk "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

.
.
.

// Set global trace provider 新增 tracer 方法
func setTracerProvider(url string) error {
    // Create the Jaeger exporter
    exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
    if err != nil {
        return err
    }
    tp := tracesdk.NewTracerProvider(
        // Set the sampling rate based on the parent span to 100%
        tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0))),
        // Always be sure to batch in production.
        tracesdk.WithBatcher(exp),
        // Record information about this application in an Resource.
        tracesdk.WithResource(resource.NewSchemaless(
            semconv.ServiceNameKey.String(Name),
            attribute.String("env", "dev"),
        )),
    )
    otel.SetTracerProvider(tp)
    return nil
}

func main() {

    .
    .
    .    

    if err := setTracerProvider(bc.Trace.Endpoint); err != nil {
        panic(err)
    }
    app, cleanup, err := initApp(bc.Server, &rc, bc.Data, logger)
    if err != nil {
        panic(err)
    }
    defer cleanup()

    // start and wait for stop signal
    if err := app.Run(); err != nil {
        panic(err)
    }
}
  • 根目錄執行 make wire 命令,生成新的 wire_gen.go 檔案

  • 加入具體跟蹤方法

// user/internal/service/user.go 加入到這個檔案裡
// 具體的手機號查詢的方法

package service

import (
    "context"
    "github.com/go-kratos/kratos/v2/log"
    "github.com/golang/protobuf/ptypes/empty"
    "go.opentelemetry.io/otel"
    "google.golang.org/protobuf/types/known/emptypb"
    "time"
    v1 "user/api/user/v1"
    "user/internal/biz"
)

.
.
.

// GetUserByMobile .
func (u *UserService) GetUserByMobile(ctx context.Context, req *v1.MobileRequest) (*v1.UserInfoResponse, error) {

    //  add trace
    tr := otel.Tracer("service")
    ctx, span := tr.Start(ctx, "get user info by mobile")
    defer span.End()

    user, err := u.uc.UserByMobile(ctx, req.Mobile)
    if err != nil {
        return nil, err
    }
    rsp := UserResponse(user)
    return &rsp, nil
}

.
.
.
  1. 測試是否引入成功
  • 啟動專案 kratos run

  • 修改測試檔案 user/test/user.go 讓其執行 TestGetUserByMobile() 方法

  • http://127.0.0.1:16686/search 瀏覽器訪問,選擇 Service 驗證是否有記錄

本作品採用《CC 協議》,轉載必須註明作者和本文連結
高永立

相關文章