Skywalking监控gin web服务

Skywalking监控gin web服务,第1张

Skywalking监控gin web服务

快速安装 skywalking
系统设置

sysctl -w vm.max_map_count=262144
docker-compose.yaml
version: '3.3'
services:
  # storage
  elasticsearch:
    image: elasticsearch:6.8.16
    container_name: elasticsearch
    restart: always
    ports:
      - 9200:9200
    environment:
      discovery.type: single-node
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes: 
      - ./elasticsearch/logs:/usr/share/elasticsearch/logs
      - ./elasticsearch/data:/usr/share/elasticsearch/data
      - /etc/localtime:/etc/localtime
  # server
  oap:
    image: apache/skywalking-oap-server:8.6.0-es6
    container_name: oap
    depends_on:
      - elasticsearch
    links:
      - elasticsearch
    restart: always
    ports:
      - 11800:11800
      - 12800:12800
    environment:
      SW_STORAGE: elasticsearch # 默认为 es6,es7 为 elasticsearch7
      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
    volumes: 
      - /etc/localtime:/etc/localtime
  # dashboard
  ui:
    image: apache/skywalking-ui:8.6.0
    container_name: ui
    depends_on:
      - oap
    links:
      - oap
    restart: always
    ports:
      - 8080:8080
    environment:
      SW_OAP_ADDRESS: oap:12800
    volumes: 
      - /etc/localtime:/etc/localtime

第三方库 go2sky 以及 go2sky 的 gin 中间件
go get -u github.com/SkyAPM/go2sky
go get github.com/SkyAPM/go2sky-plugins/gin/v3
两个 gin 服务 demo-server1 和 demo-server2,demo-server1 调用 demo-server2 demo-server2 提供 POST /user/info 接口 demo-server1 提供 GET /tracer 接口

demo-server2.go

package main

import (
  "fmt"
  "time"

  "github.com/SkyAPM/go2sky"
  "github.com/SkyAPM/go2sky/reporter"
  "github.com/gin-gonic/gin"

  v3 "github.com/SkyAPM/go2sky-plugins/gin/v3"
)

const (
  serverName = "demo-server2"
  serverPort = 8082
)

var skyAddr = "localhost:11800"

type Params struct {
  Name string
}

func panicErr(err error) {
  if err != nil {
    panic(err)
  }
}

func main() {
  r := gin.Default()
  // skyAddr 是 skywaling 的 grpc 地址,默认是 localhost:11800, 默认心跳检测时间是 1s
  rp, err := reporter.NewGRPCReporter(skyAddr, reporter.WithCheckInterval(5*time.Second))
  panicErr(err)
  // 初始化一个 tracer,一个服务只需要一个 tracer,其含义是这个服务名称
  tracer, err := go2sky.NewTracer(serverName, go2sky.WithReporter(rp))
  panicErr(err)
  // gin 使用 sky 自带的 middleware
  r.Use(v3.Middleware(r, tracer))

  // 自定义一个接口
  r.POST("/user/info", func(context *gin.Context) {
    // LocalSpan 可以理解为本地日志的 tracer,一般用户当前应用
    span, ctx, err := tracer.CreateLocalSpan(context.Request.Context())
    panicErr(err)
    // 每一个 span 都有一个名字去标实 *** 作的名称!
    span.SetOperationName("UserInfo")
    // 记住重新设置一个 ctx,再其次这个 ctx 不是 gin 的 ctx,而是 http request 的 ctx
    context.Request = context.Request.WithContext(ctx)

    params := new(Params)
    err = context.BindJSON(params)
    panicErr(err)
    // 记录日志信息
    span.Log(time.Now(), "[UserInfo]", fmt.Sprintf(serverName+" satrt, req : %+v", params))
    local := gin.H{
      "msg": fmt.Sprintf(serverName+" time : %s", time.Now().Format("15:04:05.9999")),
    }
    context.JSON(200, local)
    span.Log(time.Now(), "[UserInfo]", fmt.Sprintf(serverName+" end, resp : %s", local))
    // 切记最后要设置 span - end,不然就是一个非闭环的
    span.End()
  })

  r.Run(fmt.Sprintf(":%d", serverPort))
}

demo-server1.go

package main

import (
  "bytes"
  "encoding/json"
  "fmt"
  "io/ioutil"
  "log"
  "net/http"
  "time"

  "github.com/SkyAPM/go2sky"
  "github.com/SkyAPM/go2sky/reporter"
  "github.com/gin-gonic/gin"

  v3 "github.com/SkyAPM/go2sky-plugins/gin/v3"
  agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
)

const (
  serverName       = "demo-server1"
  serverPort       = 8081
  remoteServerName = "demo-server2"
  remoteServerAddr = "localhost:8082"
  remotePath       = "/user/info"
)

var skyAddr = "localhost:11800"

func panicErr(err error) {
  if err != nil {
    log.Fatal(err.Error())
  }
}

type Params struct {
  Name string
}

var tracer *go2sky.Tracer

func skyMiddleware(r *gin.Engine) {
  var err error
  rp, err := reporter.NewGRPCReporter(skyAddr, reporter.WithCheckInterval(5*time.Second))
  panicErr(err)
  tracer, err = go2sky.NewTracer(serverName, go2sky.WithReporter(rp))
  panicErr(err)
  r.Use(v3.Middleware(r, tracer))
}

func trace(context *gin.Context) {
  span, ctx, err := tracer.CreateLocalSpan(context.Request.Context())
  panicErr(err)
  span.SetOperationName("Trace")

  context.Request = context.Request.WithContext(ctx)
  span.Log(time.Now(), "[Trace]", fmt.Sprintf(serverName+" satrt, params : %s", time.Now().Format("15:04:05.9999")))

  result := make([]map[string]interface{}, 0)

  //1、请求一次
  {
    url := fmt.Sprintf("http://%s%s", remoteServerAddr, remotePath)

    params := Params{
      Name: serverName + time.Now().Format("15:04:05.9999"),
    }
    buffer := &bytes.Buffer{}
    _ = json.NewEncoder(buffer).Encode(params)
    req, err := http.NewRequest(http.MethodPost, url, buffer)
    panicErr(err)

    // op_name 是每一个 *** 作的名称
    reqSpan, err := tracer.CreateExitSpan(context.Request.Context(), "invoke - "+remoteServerName, "localhost:8082/user/info", func(headerKey, headerValue string) error {
      req.Header.Set(headerKey, headerValue)
      return nil
    })
    panicErr(err)
    reqSpan.SetComponent(2)
    reqSpan.SetSpanLayer(agentv3.SpanLayer_RPCframework) // rpc 调用

    resp, err := http.DefaultClient.Do(req)
    panicErr(err)
    defer resp.Body.Close()

    reqSpan.Log(time.Now(), "[HttpRequest]", fmt.Sprintf("开始请求,请求服务:%s, 请求地址:%s, 请求参数:%+v", remoteServerName, url, params))
    body, err := ioutil.ReadAll(resp.Body)
    panicErr(err)
    fmt.Printf("接受到消息: %sn", body)
    reqSpan.Tag(go2sky.TagHTTPMethod, http.MethodPost)
    reqSpan.Tag(go2sky.TagURL, url)
    reqSpan.Log(time.Now(), "[HttpRequest]", fmt.Sprintf("结束请求,响应结果:%s", body))
    reqSpan.End()
    res := map[string]interface{}{}
    err = json.Unmarshal(body, &res)
    panicErr(err)
    result = append(result, res)
  }

  //2 、再请求一次
  {
    url := fmt.Sprintf("http://%s%s", remoteServerAddr, remotePath)

    params := Params{
      Name: serverName + time.Now().Format("15:04:05.9999"),
    }
    buffer := &bytes.Buffer{}
    _ = json.NewEncoder(buffer).Encode(params)
    req, err := http.NewRequest(http.MethodPost, url, buffer)
    panicErr(err)

    // 出去必须用这个携带 header
    reqSpan, err := tracer.CreateExitSpan(context.Request.Context(), "invoke - "+remoteServerName, "localhost:8082/user/info", func(headerKey, headerValue string) error {
      req.Header.Set(headerKey, headerValue)
      return nil
    })
    panicErr(err)
    reqSpan.SetComponent(2)
    reqSpan.SetSpanLayer(agentv3.SpanLayer_RPCframework) // rpc 调用

    resp, err := http.DefaultClient.Do(req)
    panicErr(err)
    defer resp.Body.Close()

    reqSpan.Log(time.Now(), "[HttpRequest]", fmt.Sprintf("开始请求,请求服务:%s, 请求地址:%s, 请求参数:%+v", remoteServerName, url, params))
    body, err := ioutil.ReadAll(resp.Body)
    panicErr(err)
    fmt.Printf("接受到消息: %sn", body)

    reqSpan.Tag(go2sky.TagHTTPMethod, http.MethodPost)
    reqSpan.Tag(go2sky.TagURL, url)
    reqSpan.Log(time.Now(), "[HttpRequest]", fmt.Sprintf("结束请求,响应结果:%s", body))
    reqSpan.End()
    res := map[string]interface{}{}
    err = json.Unmarshal(body, &res)
    panicErr(err)
    result = append(result, res)
  }

  // 设置响应结果
  local := gin.H{
    "msg": result,
  }
  context.JSON(200, local)
  span.Log(time.Now(), "[Trace]", fmt.Sprintf(serverName+" end, resp : %s", local))
  span.End()
  {
    span, ctx, err := tracer.CreateEntrySpan(context.Request.Context(), "Send", func(s string) (string, error) {
      return "", nil
    })
    context.Request = context.Request.WithContext(ctx)
    panicErr(err)
    span.SetOperationName("Send")
    span.Log(time.Now(), "[Info]", "send resp")
    span.End()
  }
}

func main() {

  // 这些都一样
  r := gin.Default()
  // 使用 go2sky gin 中间件
  skyMiddleware(r)

  // 调用接口
  r.GET("/trace", trace)

  r.Run(fmt.Sprintf(":%d", serverPort))
}

开始测试发送请求

for i in $(seq 500); do curl -s http://192.168.8.78:8081/trace >/dev/null; sleep 1.5 ; done


demo-server1.go
demo-server1.go

两个服务的log都正常 登录sky






欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5699780.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存