当前位置: 首页 > news >正文

罗湖高端网站建设费用分销系统软件

罗湖高端网站建设费用,分销系统软件,跨境电商面试自我介绍范文,搜索引擎网址1、metadata 服务间使用 Http 相互调用时,经常会设置一些业务自定义 header 如时间戳、trace信息等,gRPC使用 HTTP/2 协议自然也是支持的,gRPC 通过 google.golang.org/grpc/metadata 包内的 MD 类型提供相关的功能接口。 1.1 类型定义 /…

1、metadata

服务间使用 Http 相互调用时,经常会设置一些业务自定义 header 如时间戳、trace信息等,gRPC使用 HTTP/2

协议自然也是支持的,gRPC 通过 google.golang.org/grpc/metadata 包内的 MD 类型提供相关的功能接口。

1.1 类型定义

// MD is a mapping from metadata keys to values. Users should use the following
// two convenience functions New and Pairs to generate MD.
type MD map[string][]string

metadata.MD 类型的定义非常简单,可以像一个普通的 map 一样直接操作,同时 metadata 包里封装了很多工

具方法供我们使用。

// 使用 New 方法创建
md := metadata.New(map[string]string{"k1":"v1", "k2", "v2"})// 直接使用 make 创建
md := make(metadata.MD)// 使用 Pairs 方法创建
md := metadata.Pairs("k1", "v1-1", "k1", "v1-2")// 一些操作
md.Set("key", "v1", "v2")
md.Append("key", "v3")
md.Delete("key")
vals := md.Get("key")

1.2 发送与接收

1.2.1 客户端

客户端请求的 metadata 是通过设置 context 使用的,metadata 包提供了两个 context 相关的方法,设置好

context 后直接在调用 rpc 方法时传入即可:

md := metadata.New(map[string]string{"k1":"v1", "k2", "v2"})// 使用 NewOutgoingContext 初始化一个新的 context
ctx := metadata.NewOutgoingContext(context.Background(), md)// 使用 AppendToOutgoingContext 向 context 追加 metadata
ctx = metadata.AppendToOutgoingContext(ctx, "k3", "v3")

客户端接收响应中的 metadata 需要区分普通 rpc 和 stream rpc :

// 普通 rpc,使用 grpc.Header 方法包装为 CallOption
var md metadata.MD
res, err := client.Ping(ctx, &pb.PingRequest{Value: "ping"}, grpc.Header(&md))// stream rpc
stream, err := client.MultiPong(context.Background(), &pb.PingRequest{Value: "ping"})
if err != nil {log.Fatal(err)
}// 通过 stream 对象的 Header 方法获取
md, err := stream.Header()
if err != nil {log.Fatal(err)
}
1.2.2 服务端

对应客户端请求的 metadata 是使用 context 设置的,那么服务端在接收时自然也是从 context 中读取,

metadata 包中的 FromIncommingContext 方法就是用来读取 context 中的 metadata数据的:

// unary rpc
func (s *PingPongServer) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PongResponse, error) {// 读取请求metadatamd, ok := metadata.FromIncomingContext(ctx)if ok {log.Printf("Got md: %v", md)}// stream rpc
func (s *PingPongServer) MultiPingPong(stream pb.PingPong_MultiPingPongServer) error {md, ok := metadata.FromIncomingContext(stream.Context())if ok {log.Printf("Got md: %v", md)}

服务端设置响应的 metadata 也非常简单,只需要调用封装好的 SetHeaderSendHeader 方法即可:

// unary rpc
func (s *PingPongServer) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PongResponse, error) {// 读取请求metadatamd, ok := metadata.FromIncomingContext(ctx)if ok {log.Printf("Got md: %v", md)}// SetHeader设置响应 metadatagrpc.SetHeader(ctx, metadata.New(map[string]string{"rkey": "rval"}))// 注意 SendHeader 只能调用一次// grpc.SendHeader(ctx, metadata.New(map[string]string{"rkey": "rval"}))// stream rpc, 调用 stream 的 SetHeader 方法
func (s *PingPongServer) MultiPong(req *pb.PingRequest, stream pb.PingPong_MultiPongServer) error {stream.SetHeader(metadata.New(map[string]string{"rkey": "rval"}))// 注意 SendHeader 只能调用一次// stream.SendHeader(metadata.New(map[string]string{"rkey": "rval"}))

1.3 使用案例

1.3.1 proto 文件编写和编译

demo.proto文件内容:

syntax="proto3";
package protos;
option go_package = "./protos;protos";service Greeter {rpc SayHello(HelloRequest) returns(HelloReply){}
}message HelloRequest {string name = 1;
}message HelloReply {string message = 1;
}

编译生成demo.pb.go 文件:

$ protoc --go_out=plugins=grpc:. demo.proto
1.3.2 server端

server.go文件的内容:

package mainimport ("context""flag""fmt""demo/protos""google.golang.org/grpc""google.golang.org/grpc/metadata""log""net"
)var host = "127.0.0.1"var (ServiceName = flag.String("ServiceName", "hello_service", "service name")Port        = flag.Int("Port", 50001, "listening port")
)type server struct {
}func main() {flag.Parse()lis, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", *Port))if err != nil {log.Fatalf("failed to listen:%s", err)} else {fmt.Printf("listen at :%d\n", *Port)}defer lis.Close()s := grpc.NewServer()defer s.GracefulStop()protos.RegisterGreeterServer(s, &server{})addr := fmt.Sprintf("%s:%d", host, *Port)fmt.Printf("server add:%s\n", addr)if err := s.Serve(lis); err != nil {fmt.Printf("failed to server: %s", err)}
}func (s *server) SayHello(ctx context.Context, in *protos.HelloRequest) (*protos.HelloReply, error) {md, ok := metadata.FromIncomingContext(ctx)if !ok {fmt.Printf("get metadata error")}else{fmt.Println("get metadata success: ",md)}if t, ok := md["timestamp"]; ok {fmt.Printf("timestamp from metadata:\n")for i, e := range t {fmt.Printf(" %d. %s\n", i, e)}}if t1, ok1 := md["key1"]; ok1 {fmt.Printf("key1 from metadata:\n")for i, e := range t1 {fmt.Printf(" %d . %s\n", i, e)}}if len(md) > 0 {for k, v := range md {fmt.Printf("%v:%v\n", k, v)}}return &protos.HelloReply{Message: "server: " + in.Name}, nil
}
1.3.3 client端

client.go文件的内容:

package mainimport ("context""fmt""demo/protos""google.golang.org/grpc""google.golang.org/grpc/metadata""time"
)const (timestampFormat = time.StampNano
)func main() {conn, err := grpc.Dial("127.0.0.1:50001", grpc.WithInsecure())if err != nil {panic(err)}client := protos.NewGreeterClient(conn)md := metadata.Pairs("timestamp", time.Now().Format(timestampFormat))md = metadata.New(map[string]string{"key1": "val1", "key2": "val2"})ctx := metadata.NewOutgoingContext(context.Background(), md)resp, err := client.SayHello(ctx, &protos.HelloRequest{Name: "Hello"})if err == nil {fmt.Printf("Reply is : %s\n", resp.Message)} else {fmt.Printf("call server error:%s\n", err)}
}
1.3.4 运行
[root@zsx demo]# go run server.go
listen at :50001
server add:127.0.0.1:50001
get metadata success:  map[:authority:[127.0.0.1:50001] content-type:[application/grpc] key1:[val1] key2:[val2] user-agent:[grpc-go/1.53.0]]
key1 from metadata:0 . val1
:authority:[127.0.0.1:50001]
content-type:[application/grpc]
user-agent:[grpc-go/1.53.0]
key2:[val2]
key1:[val1]
[root@zsx demo]# go run client.go
Reply is : server: Hello
# 项目结构
[root@zsx protoc]# tree demo/
demo/
├── client.go
├── demo.proto
├── go.mod
├── go.sum
├── protos
│   └── demo.pb.go
└── server.go1 directory, 6 files
http://www.sczhlp.com/news/114841/

相关文章:

  • 保险网站建设的目标徐州住房与建设局网站
  • 如何做淘宝二手网站厦门seo代运营
  • 多种语言网站怎么做国家信用信息系统年报
  • 网站原图怎么做郑州网站建设哪家最好
  • 视频生成链接网站家教网站建设模板
  • 小程序网站开发运行合同成都建网站的公司
  • 微网站 免费唐山做网站哪家公司好
  • 我的首个RCE漏洞发现之旅:Apache ActiveMQ远程代码执行实战
  • 电商运营的网站宜昌城市建设学校网站
  • 怎么做视频平台网站吗室内装修设计软件下载
  • 上海公共招聘网站公司网站建网
  • wordpress 适合外贸站番禺人才网官网
  • 福州网站建设招商权威的合肥网站建设
  • wordpress手机app编辑文章h5网站不利于优化吗
  • 上海app网站开发价值惠州网站推广排名
  • 深圳住 建设局网站首页青岛网站排名哪家公司好
  • 免费源码网站微商代运营
  • 餐厅网站建设开封开封县网站建设
  • 国外好的室内设计网站棒的网页设计
  • 帝国网站单页做301外链网站 风险
  • 小团队兼职做网站流量查询网站
  • 网站建设 51下拉平台建设网站入不入无形资产
  • 公司网站模板设计学校网站建设情况介绍
  • 兰州网站seo服务中国有几大网站
  • 水贝做网站公司杭州市建设信用网
  • u网站建设免费传奇网站免费传奇
  • 个人网站开发协议海口制作网站企业
  • 广州网站平台建设定制自己的软件
  • 住房和城乡建设部网站防烟排烟wordpress广告管理
  • 南康网站网站建设四川省建设工程招投标网站