一般的 RPC 服务都是对内使用的,基本不会公开在外网,即使是多机房,也一般是通过网络网关层做出限制,只允许受信的几个 IP 可以访问。
这是常识,也是一般的 RPC 的部署要求之一。
如果人员不够,或者不想再包装一层接口给其它人用,那么鉴权就显得尤为重要了,尤其是通过 token 的鉴权。
另外,我们在请求 RPC 接口时可能要传递一些额外的数据,比如请求的时间戳、请求的序列号等等。
或者说,如果传递 RPC 接口参数以外的数据,也是 RPC 开发中的重要一环。
这些数据,在 gRPC 框架中被称之为 元数据 (metadata
)。 gRPC-go 提供了 google.golang.org/grpc/metadata
模块来生成、发送和接收、获取这些数据。
google.golang.org/grpc/metadata
简介
meta
包提供了以下几个结构体
结构体 | 说明 |
---|---|
MD |
MD 是一个哈希表,以健值对的形式存储数据 |
MD
结构体的定义如下
type MD map[string][]string
从定义可以看出,MD
的值时一个 slice
,这个认知非常重要,关系着后面成员方法的使用。
MD
结构体的键只允许 数字、小写字母和 -_.
三个特殊字符。任何大些字母在成员方法中都会被转换为小写字母。
建议: 尽量使用 MD 提供的方法来操作 MD 对象,不然大小写这个约定可能会造成很多 bug 。
MD
结构体除了可以使用 哈希表 map 常用的下标法访问和添加数据外,还定义了几个方法辅助我们获取和设置见键值对
方法 | 说明 |
---|---|
func (md MD) Set(k string, vals ...string) |
为键 key 设置一个新值 vals |
func (md MD) Len() int |
获取键的数量 |
func (md MD) Get(k string) []string |
根据键 key 获取值,返回的是字符串 slice |
func (md MD) Copy() MD |
创建 md 的一个新的副本 |
func (md MD) Append(k string, vals ...string) |
在键 key 对应值的后面追加新值 vals |
注意
Set()
方法如何键key
不存在则为新增,如果存在就是替换。Append()
方法的功能是追加,即使值一模一样也是追加,也就是可能会有重复的值。相当于slice
的 append 操作
metadata
的成员方法方便了我们生成和获取元数据,同时,为了更好的生成 md
对象,metadata
还提供了了一下便捷函数
函数 | 说明 |
---|---|
func Pairs(kv ...string) MD |
根据键值对数据生成一个 md 对象 |
func New(m map[string]string) MD |
根据哈希表生成一个 md 对象 |
func Join(mds ...MD) MD |
将对个 md 对象拼接成一个新的 md 对象 |
func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) |
根据上下文构造一个请求 md 对象,不建议使用 |
func FromOutgoingContext(ctx context.Context) (MD, bool) |
从发送上下文中获取 md 对象,一般用在 gRPC 客户端中 |
func FromIncomingContext(ctx context.Context) (MD, bool) |
从请求上下文中获取 md 对象,一般用在 gRPC 服务端中 |
func Pairs(kv ...string) MD
的使用范例如下
md := metadata.Pairs("key1","val1","key1","val1-2", "key2","val2")
也就是把多个键值对依次以 键,值
的方式传递给 Pairs()
方法
func New(m map[string]string) MD
的使用范例如下
md := metadata.New(map[string]string{"key1": "val1","key1": "val1-2", "key2": "val2"})
func FromOutgoingContext(ctx context.Context) (MD, bool)
的使用范例
未完待续...没空了,晚上补上