日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)GoFrame教程:GoFrame鏈路跟蹤-GRPC示例

在本章節(jié)中,我們將之前介紹?HTTP Client&Server?的示例修改為?GRPC?微服務(wù),并演示如何使用?GOFrame?框架開發(fā)一個(gè)簡單的?GRPC?服務(wù)端和客戶端,并且為?GRPC?微服務(wù)增加鏈路跟蹤特性。

成都創(chuàng)新互聯(lián)于2013年開始,先為仲巴等服務(wù)建站,仲巴等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為仲巴企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

目錄結(jié)構(gòu)

Protocol

syntax = "proto3";

package user;

option go_package = "protobuf/user";

import "github.com/gogo/protobuf/gogoproto/gogo.proto";

// User service for tracing demo.
service User {
  rpc Insert(InsertReq) returns (InsertRes) {}
  rpc Query(QueryReq) returns (QueryRes) {}
  rpc Delete(DeleteReq) returns (DeleteRes) {}
}

message InsertReq {
  string Name = 1 [(gogoproto.moretags) = 'v:"required#Please input user name."'];
}

message InsertRes {
  int32 Id = 1;
}

message QueryReq {
  int32 Id = 1 [(gogoproto.moretags) = 'v:"min:1#User id is required for querying."'];
}

message QueryRes {
  int32  Id = 1;
  string Name = 2;
}

message DeleteReq {
  int32 Id = 1 [(gogoproto.moretags) = 'v:"min:1#User id is required for deleting."'];
}

message DeleteRes {}

這里使用到了第三方的 github.com/gogo/protobuf 開源項(xiàng)目,用于注入自定義的Golang struct標(biāo)簽。這里不詳細(xì)介紹,感興趣的小伙伴可以自行了解。未來?Katyusha?微服務(wù)框架的官網(wǎng)文檔也會(huì)做對這塊詳細(xì)介紹,包括?GRPC?工程目錄、開發(fā)規(guī)范、開發(fā)工具、攔截器、注冊發(fā)現(xiàn)、負(fù)載均衡等設(shè)計(jì)話題。

GRPC Server

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/gogf/gf/contrib/trace/jaeger/v2"
	"github.com/gogf/gf/example/trace/grpc_with_db/protobuf/user"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/gogf/katyusha/krpc"
)

type server struct{}

const (
	ServiceName       = "grpc-server-with-db"
	JaegerUdpEndpoint = "localhost:6831"
)

func main() {
	var ctx = gctx.New()
	tp, err := jaeger.Init(ServiceName, JaegerUdpEndpoint)
	if err != nil {
		g.Log().Fatal(ctx, err)
	}
	defer tp.Shutdown(ctx)

	// Set ORM cache adapter with redis.
	g.DB().GetCache().SetAdapter(gcache.NewAdapterRedis(g.Redis()))

	s := krpc.Server.NewGrpcServer()
	user.RegisterUserServer(s.Server, &server{})
	s.Run()
}

// Insert is a route handler for inserting user info into database.
func (s *server) Insert(ctx context.Context, req *user.InsertReq) (res *user.InsertRes, err error) {
	result, err := g.Model("user").Ctx(ctx).Insert(g.Map{
		"name": req.Name,
	})
	if err != nil {
		return nil, err
	}
	id, _ := result.LastInsertId()
	res = &user.InsertRes{
		Id: int32(id),
	}
	return
}

// Query is a route handler for querying user info. It firstly retrieves the info from redis,
// if there's nothing in the redis, it then does db select.
func (s *server) Query(ctx context.Context, req *user.QueryReq) (res *user.QueryRes, err error) {
	err = g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{
		Duration: 5 * time.Second,
		Name:     s.userCacheKey(req.Id),
		Force:    false,
	}).WherePri(req.Id).Scan(&res)
	if err != nil {
		return nil, err
	}
	return
}

// Delete is a route handler for deleting specified user info.
func (s *server) Delete(ctx context.Context, req *user.DeleteReq) (res *user.DeleteRes, err error) {
	err = g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{
		Duration: -1,
		Name:     s.userCacheKey(req.Id),
		Force:    false,
	}).WherePri(req.Id).Scan(&res)
	return
}

func (s *server) userCacheKey(id int32) string {
	return fmt.Sprintf(`userInfo:%d`, id)
}

服務(wù)端代碼簡要說明:

  • 首先,服務(wù)端需要通過?jaeger.Init?方法初始化?Jaeger?。
  • 可以看到,業(yè)務(wù)邏輯和之前HTTP示例項(xiàng)目完全一致,只是接入層修改為了?GRPC?協(xié)議。
  • 我們?nèi)匀煌ㄟ^緩存適配器的方式注入?Redis?緩存:
g.DB().GetCache().SetAdapter(gcache.NewAdapterRedis(g.Redis()))
  • 這里也是通過?Cache?方法啟用?ORM?的緩存特性,之前已經(jīng)做過介紹,這里不再贅述。

GRPC Client

package main

import (
	"github.com/gogf/gf/contrib/trace/jaeger/v2"
	"github.com/gogf/gf/example/trace/grpc_with_db/protobuf/user"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gtrace"
	"github.com/gogf/gf/v2/os/gctx"
)

const (
	ServiceName       = "grpc-client-with-db"
	JaegerUdpEndpoint = "localhost:6831"
)

func main() {
	var ctx = gctx.New()
	tp, err := jaeger.Init(ServiceName, JaegerUdpEndpoint)
	if err != nil {
		g.Log().Fatal(ctx, err)
	}
	defer tp.Shutdown(ctx)

	StartRequests()
}

func StartRequests() {
	ctx, span := gtrace.NewSpan(gctx.New(), "StartRequests")
	defer span.End()

	var client, err = user.NewClient()
	if err != nil {
		g.Log().Fatalf(ctx, `%+v`, err)
	}

	// Baggage.
	ctx = gtrace.SetBaggageValue(ctx, "uid", 100)

	// Insert.
	insertRes, err := client.User().Insert(ctx, &user.InsertReq{
		Name: "john",
	})
	if err != nil {
		g.Log().Fatalf(ctx, `%+v`, err)
	}
	g.Log().Info(ctx, "insert id:", insertRes.Id)

	// Query.
	queryRes, err := client.User().Query(ctx, &user.QueryReq{
		Id: insertRes.Id,
	})
	if err != nil {
		g.Log().Errorf(ctx, `%+v`, err)
		return
	}
	g.Log().Info(ctx, "query result:", queryRes)

	// Delete.
	_, err = client.User().Delete(ctx, &user.DeleteReq{
		Id: insertRes.Id,
	})
	if err != nil {
		g.Log().Errorf(ctx, `%+v`, err)
		return
	}
	g.Log().Info(ctx, "delete id:", insertRes.Id)

	// Delete with error.
	_, err = client.User().Delete(ctx, &user.DeleteReq{
		Id: -1,
	})
	if err != nil {
		g.Log().Errorf(ctx, `%+v`, err)
		return
	}
	g.Log().Info(ctx, "delete id:", -1)
}

客戶端代碼簡要說明:

  1. 首先,客戶端也是需要通過?jaeger.Init?方法初始化?Jaeger?。
  2. 客戶端非常簡單,內(nèi)部初始化以及默認(rèn)攔截器的設(shè)置已經(jīng)由?Katyusha?框架封裝好了,開發(fā)者只需要關(guān)心業(yè)務(wù)邏輯實(shí)現(xiàn)即可,

效果查看

啟動(dòng)服務(wù)端:

啟動(dòng)客戶端:

這里客戶端的執(zhí)行最后報(bào)了一個(gè)錯(cuò)誤,那是我們故意為之,目的是演示?GRPC?報(bào)錯(cuò)時(shí)的鏈路信息展示。我們打開?jaeger?查看一下鏈路跟蹤信息:

可以看到本次請求涉及到兩個(gè)服務(wù):?tracing-grpc-client?和?tracing-grpc-server?,即客戶端和服務(wù)端。整個(gè)請求鏈路涉及到17個(gè)?span?,客戶端5個(gè)?span?,服務(wù)端12個(gè)?span?,并且產(chǎn)生了2個(gè)錯(cuò)誤。我們點(diǎn)擊查看詳情:

我們點(diǎn)擊查看一下最后接口調(diào)用錯(cuò)誤的?span?情況:

看起來像個(gè)參數(shù)校驗(yàn)錯(cuò)誤,點(diǎn)擊查看?Events/Logs?中的請求參數(shù):

查看?Process?中的?Log?信息可以看到,是由于傳遞的參數(shù)為-1,不滿足校驗(yàn)規(guī)則,因此在數(shù)據(jù)校驗(yàn)的時(shí)候報(bào)錯(cuò)返回了。

GRPC Client

由于?orm?、?redis?、?logging?組件在之前的章節(jié)中已經(jīng)介紹過鏈路信息,因此我們這里主要介紹?GRPC Client&Server?的鏈路信息。

Attributes

Attribute/Tag 說明
net.peer.ip 請求的目標(biāo)IP。
net.peer.port 請求的目標(biāo)端口。
rpc.grpc.status_code GRPC的內(nèi)部狀態(tài)碼,0表示成功,非0表示失敗。
rpc.service RPC的服務(wù)名稱,注意這里是RPC而不是GRPC,因?yàn)檫@里是通用定義,客戶端支持多種RPC通信協(xié)議,GRPC只是其中一種。
rpc.method RPC的方法名稱。
rpc.system RPC協(xié)議類型,如:grpcthrift等。

Events/Logs

Event/Log 說明
grpc.metadata.outgoing GRPC客戶端請求提交的Metadata信息,可能會(huì)比較大。
grpc.request.baggage GRPC客戶端請求提交的Baggage信息,用于服務(wù)間鏈路信息傳遞。
grpc.request.message

GRPC客戶端請求提交的Message數(shù)據(jù),可能會(huì)比較大,最大只記錄512KB,如果超過該大小則忽略。僅對Unary請求類型有效。

grpc.response.message GRPC客戶端請求接收返回的的Message信息,可能會(huì)比較大。僅對Unary請求類型有效。

GRPC Server

Attributes

?GRPC Server?端的?Attributes?含義同?GRPC Client?,在同一請求中,打印的數(shù)據(jù)基本一致。

Events

?GRPC Server?端的?Events?與?GRPC Client?不同的是,在同一請求中,服務(wù)端接收到的?metadata?為?grpc.metadata.incoming?,其他同?GRPC Client?。


本文標(biāo)題:創(chuàng)新互聯(lián)GoFrame教程:GoFrame鏈路跟蹤-GRPC示例
文章路徑:http://m.5511xx.com/article/dhhppce.html