在本章节中,我们将之前介绍HTTP Client&Server的示例修改为GRPC微服务,并演示如何使用GOFrame框架开发一个简单的GRPC服务端和客户端,并且为GRPC微服务增加链路跟踪特性。

成都创新互联于2013年开始,先为仲巴等服务建站,仲巴等地企业,进行企业商务咨询服务。为仲巴企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
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 开源项目,用于注入自定义的Golang struct标签。这里不详细介绍,感兴趣的小伙伴可以自行了解。未来Katyusha微服务框架的官网文档也会做对这块详细介绍,包括GRPC工程目录、开发规范、开发工具、拦截器、注册发现、负载均衡等设计话题。
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)
}服务端代码简要说明:
jaeger.Init方法初始化Jaeger。GRPC协议。Redis缓存:g.DB().GetCache().SetAdapter(gcache.NewAdapterRedis(g.Redis()))Cache方法启用ORM的缓存特性,之前已经做过介绍,这里不再赘述。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)
}客户端代码简要说明:
jaeger.Init方法初始化Jaeger。Katyusha框架封装好了,开发者只需要关心业务逻辑实现即可,启动服务端:
启动客户端:
这里客户端的执行最后报了一个错误,那是我们故意为之,目的是演示GRPC报错时的链路信息展示。我们打开jaeger查看一下链路跟踪信息:
可以看到本次请求涉及到两个服务:tracing-grpc-client和tracing-grpc-server,即客户端和服务端。整个请求链路涉及到17个span,客户端5个span,服务端12个span,并且产生了2个错误。我们点击查看详情:
我们点击查看一下最后接口调用错误的span情况:
看起来像个参数校验错误,点击查看Events/Logs中的请求参数:
查看Process中的Log信息可以看到,是由于传递的参数为-1,不满足校验规则,因此在数据校验的时候报错返回了。
由于orm、redis、logging组件在之前的章节中已经介绍过链路信息,因此我们这里主要介绍GRPC Client&Server的链路信息。
| Attribute/Tag | 说明 | 
|---|---|
net.peer.ip  | 
请求的目标IP。 | 
net.peer.port  | 
请求的目标端口。 | 
rpc.grpc.status_code  | 
GRPC的内部状态码,0表示成功,非0表示失败。 | 
rpc.service  | 
RPC的服务名称,注意这里是RPC而不是GRPC,因为这里是通用定义,客户端支持多种RPC通信协议,GRPC只是其中一种。 | 
rpc.method  | 
RPC的方法名称。 | 
rpc.system  | 
RPC协议类型,如:grpc, thrift等。 | 
| Event/Log | 说明 | 
|---|---|
grpc.metadata.outgoing  | 
GRPC客户端请求提交的Metadata信息,可能会比较大。 | 
grpc.request.baggage  | 
GRPC客户端请求提交的Baggage信息,用于服务间链路信息传递。 | 
grpc.request.message  | 
 
  | 
grpc.response.message  | 
GRPC客户端请求接收返回的的Message信息,可能会比较大。仅对Unary请求类型有效。 | 
GRPC Server端的Attributes含义同GRPC Client,在同一请求中,打印的数据基本一致。
GRPC Server端的Events与GRPC Client不同的是,在同一请求中,服务端接收到的metadata为grpc.metadata.incoming,其他同GRPC Client。
                名称栏目:创新互联GoFrame教程:GoFrame链路跟踪-GRPC示例
                
                网站URL:http://www.csdahua.cn/qtweb/news22/29222.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网
成都快上网为您推荐相关内容