快速安装 skywalking
系统设置
sysctl -w vm.max_map_count=262144docker-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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)