一般的 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) 的使用范例
未完待续...没空了,晚上补上