GRPC的metadata使用
文章目录
在http请求当中我们可以设置header用来传递数据,grpc底层采用http2协议也是支持传递数据的,采用的是metadata。 Metadata 对于 gRPC 本身来说透明, 它使得 client 和 server 能为对方提供本次调用的信息。就像一次 http 请求的 RequestHeader 和 ResponseHeader,http header 的生命周期是一次 http 请求, Metadata 的生命周期则是一次 RPC 调用。
一、简析
项目源代码路径:google.golang.org/grpc/metadata
项目文档路径:https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md
以下翻译自官方文档
1、创建metadata
MD 类型实际上是map,key是string,value是string类型的slice。
type MD map[string][]string
创建的时候可以像创建普通的map类型一样使用new关键字进行创建:
md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"})
或者使用Pairs创建,相同的key值会被组合成slice。
md := metadata.Pairs(
"key1", "val1",
"key1", "val1-2", // "key1" will have map value []string{"val1", "val1-2"}
"key2", "val2",
)
key不区分大小写,会被统一转成小写。
2、发送metadata
md := metadata.Pairs("key", "val")
// 新建一个有 metadata 的 context
ctx := metadata.NewOutgoingContext(context.Background(), md)
// 单向 RPC
response, err := client.SomeRPC(ctx, someRequest)
更多发送方法见项目文档
3、接收metadata
利用函数 FromIncomingContext
从context中获取metadata:
func (s *server) SomeRPC(ctx context.Context, in *pb.SomeRequest) (*pb.SomeResponse, err) {
md, ok := metadata.FromIncomingContext(ctx)
// do something with metadata
}
二、代码举例
官方测试项目:https://github.com/grpc/grpc-go/tree/master/examples/features/metadata
详细的使用方法可以参考官方文档,下面是我写的一个简单练手的代码:
1、proto文件编写
syntax = "proto3";
package protos;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
2、server端编写
package main
import (
"flag"
"fmt"
"log"
"net"
pb "github.com/zhanben/go_server/protos"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
var host = "127.0.0.1"
var (
ServiceName = flag.String("ServiceName", "hello_service", "service name")
Port = flag.Int("Port", 50001, "listening port")
)
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()
pb.RegisterGreeterServer(s, &server{})
addr := fmt.Sprintf("%s:%d", host, *Port)
fmt.Printf("server addr:%s\n",addr)
if err := s.Serve(lis); err != nil {
fmt.Printf("failed to serve: %s", err)
}
}
// server is used to implement helloworld.GreeterServer.
type server struct{}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
fmt.Printf("get metadata error")
}
if t, ok := md["timestamp"]; ok {
fmt.Printf("timestamp from metadata:\n")
for i, e := range t {
fmt.Printf(" %d. %s\n", i, e)
}
}
//fmt.Printf("%v: Receive is %s\n", time.Now(), in.Name)
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
3、client端编写
package main
import (
"fmt"
"time"
pb "github.com/zhanben/go_client/protos"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
const (
timestampFormat = time.StampNano // "Jan _2 15:04:05.000"
)
func main() {
conn, err := grpc.Dial( "127.0.0.1:50001", grpc.WithInsecure())
if err != nil {
panic(err)
}
client := pb.NewGreeterClient(conn)
md := metadata.Pairs("timestamp", time.Now().Format(timestampFormat))
ctx := metadata.NewOutgoingContext(context.Background(), md)
resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "hello, world"})
if err == nil {
fmt.Printf("Reply is %s\n", resp.Message)
}else{
fmt.Printf("call server error:%s\n", err)
}
}
root@localhost go_client # ./client
Reply is Hello hello, world
root@localhost go_server # ./server
listen at:50001
server addr:127.0.0.1:50001
timestamp from metadata:
- Apr 1 20:25:34.227395377
三、实际使用举例
在项目开发中,我们的某个项目就利用这个metadata传入账户号,然后在envoy中配置了转发规则,来实现流量控制,达到灰度发布的效果。例如下面的配置
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
creationTimestamp: null
name: hello
namespace: test
esourceVersion: "0x000000000001158F"
spec:
hosts:
- rtsub.uxr
http:
- match:
- headers:
key_name://matedata中的key值
regex: account=5022222222;.* //exact: account=50222222;
四、参考文件
1、 https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md
GRPC的metadata使用的更多相关文章
- grpc 入门(一)--hello world
一,从rpc接口的定义说起,下面给一个最简单的grpc示例--hello world 在这个rpc横行的世界里,实现一个rpc很重要的一件事就是定义一个好接口,一个好的接口定义会让你省去很多麻烦.熟悉 ...
- gRPC学习
概述 gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法, ...
- Golang gRPC 使用
一.概念 1.gRPC默认使用protocol buffers,这是google开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如JSON),可以用proto files创建gRPC服务 ...
- gRPC官方文档(安全认证)
文章来自gRPC 官方文档中文版 认证 gRPC 被设计成可以利用插件的形式支持多种授权机制.本文档对多种支持的授权机制提供了一个概览,并且用例子来论述对应API,最后就其扩展性作了讨论. 马上将会推 ...
- GRPC 截止时间与元数据
截止时间 gRPC 允许客户端在调用一个远程方法前指定一个最后期限值.这个值指定了在客户端可以等待服务端多长时间来应答,超过这个时间值 RPC 将结束并返回DEADLINE_EXCEEDED错误.在服 ...
- btcWallet系列之一-grpc模块
btcwallet对外服务 btcwallet除了像btcd对外提供rpc服务以外,还提供了grpc服务,同时grpc采用的是protobuf来实现. 这方便与不同语言进行交互,降低客户端代码编写量. ...
- 从实践到原理,带你参透 gRPC
gRPC 在 Go 语言中大放异彩,越来越多的小伙伴在使用,最近也在公司安利了一波,希望这一篇文章能带你一览 gRPC 的巧妙之处,本文篇幅比较长,请做好阅读准备.本文目录如下: 简述 gRPC 是一 ...
- Go微服务 grpc/protobuf
了解grpc/protobuf gRPC是一个高性能.通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers ...
- 【Go】Golang实现gRPC的Proxy的原理
背景 gRPC是Google开始的一个RPC服务框架, 是英文全名为Google Remote Procedure Call的简称. 广泛的应用在有RPC场景的业务系统中,一些架构中将gRPC请求都经 ...
随机推荐
- Linux 常用命令 | top 详解
top 命令实时显示进程的状态.(自己也会占用资源,类似window的任务管理器),由以下几部分组成 默认状态显示的是cpu密集型的进程,并且每5秒钟更新一次. (1) 系统状态 当前时间.系统已运行 ...
- ATM功能实现项目
一.模拟实现一个ATM + 购物商城程序 1.额度 15000或自定义2.实现购物商城,买东西加入 购物车,调用信用卡接口结账3.可以提现,手续费5%4.支持多账户登录5.支持账户间转账6.记录每月日 ...
- Linux常用命令复习
1> 查看文件信息:ls ls是英文单词list的简写,其功能为列出目录的内容,是用户最常用的命令之一,它类似于DOS下的dir命令. Linux文件或者目录名称最长可以有265个字符,“.”代 ...
- My First Cloud Application's Design
Structure Diagram as following: Questions list: 1. Skydrive Integration > Based on the MSDN commu ...
- opencv 6 图像轮廓与图像分割修复 2 使用多边形将轮廓包围
使用多边形将轮廓包围 返回外部矩阵边界(boundingRect()函数) 寻找最小包围矩形(minAreaRect()函数) 寻找最小包围圆形(minEnclosingCircle函数) 用椭圆拟合 ...
- opencv 4 图像处理 (1 线性滤波,非线性滤波)
1 线性滤波:方框滤波.均值滤波.高斯滤波 1.1方框滤波(box Filter) 1.2均值滤波(blur函数) 缺陷: 1.3高斯滤波(GaussianBlur函数) 1.4线性滤波核心API函数 ...
- c# 发送邮箱,企业邮箱测试成功
今天在项目中需要实现一个发送邮箱的功能,来实现用户邮箱激活功能!!! 之前采用的是个人的邮箱进行测试,一切都是很顺利的,后来换成了公司的企业邮箱,遇到了一点小问题,问题如下: 发送邮件失败,原因:命令 ...
- 使用lib-flexible.js适配移动端UI设计750px设计图
最近在和设计沟通关于设计图尺寸大小和前端实际页面尺寸大小不一致的情况,我们的UI设计是使用的iPone6的,(iphone6: 375px*667px 实际像素:750px*1334px)如果 ...
- react -Route exact Redirect
exact是Route下的一个属性,react路由会匹配到所有能匹配到的路由组件,exact能够使得路由的匹配更严格一些(exact的值为bool型). <Route path='/' c ...
- Java数组使用以及foreach循环
Java数组使用以及foreach循环 二话不说,先甩一个简单的程序: final int NUM= 10; int[] arrays = new int[NUM]; System.out.print ...