Skip to content

zh_userguide

Ray edited this page Nov 7, 2017 · 16 revisions

基本介绍

Motan是高性能的RPC服务化框架,Motan提供了强大服务治理功能以及优秀的扩展能力。Motan-go是Motan的golang版本实现,除了提供了client与server与其他语言版本进行交互外,Motan-go还提供了agent为不同语言使用Motan框架进行跨语言服务治理提供了支持。

架构概述

Motan-go的基本交互方式请参考Motan架构概述

模块概述

Motan-go的各模块的作用与Motan java版本的基本一致, 但是实现方式与java版本略有不同,其中transport部分在client端与server端分别由endpointserver两个模块实现。 Motan-go的代码结构按package进行主要功能模块进行划分,各package功能可以参考GoDoc文档

自定义扩展实现

强大的扩展能力是Motan框架的特点之一,Motan-go通过扩展注册机制来支持自定义扩展,通过自定义扩展可以方便适配不同的系统或增加定制化功能。 Motan-go的各类扩展实现是通过ExtentionFactory来管理,Motan-go给出了默认实现类DefaultExtentionFactory,DefaultExtentionFactory提供了各类扩展实现类的注册与获取机制,并会提前注册所有的扩展实现。在实际使用client、server、agent时会默认使用DefaultExtentionFactory,用户只需要注册自定义实现即可,这是推荐的扩展方式。

也可以使用自定义的ExtentionFactory实现来替换默认的DefaultExtentionFactory,但需要对所有扩展的使用方式比较了解,不建议一般用户通过此种方式进行扩展。

主要扩展点

Motan-go对各主要功能都提供了可扩展能力,并提供了多种默认实现可供选择。主要扩展点如下:

  • Registry: 不同注册中心扩展。目前支持zookeeper和direct,后续会支持其他注册中心,例如consul等
  • Filter: filter是在请求处理中对reques和response进行处理的机制,提供endpointFilter和clusterFilter两个插入点。使用filter进行功能扩展是推荐的扩展方式。默认提供accesslog、metric等filter。
  • HaStrategy: 高可用策略扩展点,默认提供failover。后续将提供backup request等策略
  • LoadBalance: 负载均衡策略扩展点。默认实现random、roundrobin。同时给出了支持跨group权重处理的warper实现类,方便不同LB策略支持按权重跨group负载均衡
  • EndPoint: endpoint为调用远程server的扩展点,可以理解为点对点直连场景下的client。默认提供motan协议实现与grpc实现。
  • Provider: 具体rpc服务的实现类扩展,可以是调用本地代码实现,也可以是跨进程实现。默认提供本地服务实现调用与CGI跨进程调用。
  • Server: 不同类型的server实现,一般与协议绑定。默认提供MotanServer实现。
  • MessageHandler: 针对默认Server实现MotanServer的不同类型消息处理扩展。
  • Serialization: 可以进行不同类型序列化实现扩展。默认支持simple序列化。

自定义扩展注册

实现一个扩展

实现一个自定义扩展需要实现上述扩展点接口的全部方法,以实现一个endpointFilter为例,需要先实现 endpointFilter接口中声明的方法。如下:

type MyEndPointFilter struct {
	url  *motancore.URL
	next motancore.EndPointFilter
}

// 获取此filter的index。index用来决定不同filter的执行顺序,index越小会越先执行。
func (m *MyEndPointFilter) GetIndex() int {
	return 20
}

func (m *MyEndPointFilter) GetName() string {
	return "myfilter"
}

// filter必须为多例模式,NewFilter用来创建一个新的filter实例。
func (m *MyEndPointFilter) NewFilter(url *motancore.URL) motancore.Filter {
	return &MyEndPointFilter{url: url}
}

//filter调用是嵌套模式,filter的最内层会调用实际endpoint进行远程请求。
func (m *MyEndPointFilter) Filter(caller motancore.Caller, request motancore.Request) motancore.Response {
	fmt.Printf("before call. request:%+v\n", request)
	// must call next filter in Filter implement
	response := m.GetNext().Filter(caller, request)
	fmt.Printf("after call. response:%+v\n", response)
	return response
}

func (m *MyEndPointFilter) HasNext() bool {
	return m.next != nil
}

// 设置filter链中的下一个filter
func (m *MyEndPointFilter) SetNext(nextFilter motancore.EndPointFilter) {
	m.next = nextFilter
}

// 获取filter链中的下一个filter
func (m *MyEndPointFilter) GetNext() motancore.EndPointFilter {
	return m.next
}

// filter 类型。filter分为endpointFilter 与clusterFilter,分别在调用的不同位置执行filter过滤行为
func (m *MyEndPointFilter) GetType() int32 {
	return motancore.EndPointFilterType
}

注册实现扩展类

实现了扩展类之后,需要把扩展类注册到ExtentionFactory,注册时需要一个扩展类的唯一标识,以及一个创建新扩展类的方法。用上面的MyEndPointFilter为例,注册到默认工厂类的方式如下:

weiboExtFactory := motan.GetDefaultExtFactory() //获取默认注册工厂类。
weiboExtFactory.RegistExtFilter("myfilter", func() motancore.Filter {
	return &MyEndPointFilter{}
}) //注册的唯一标识,即name为`myfilter`,注册的是创建一个新的`myfilter`类的匿名方法。

自定义扩展使用

在完成了自定义扩展的注册后,可以通过配置使用自定义扩展类。一般是通过在refer、service的对应配置项中使用注册时的name即可。例如上例中的myfilter,使用方法如下:

motan-refer:
  mytest-motan2:
    path: com.weibo.motan2.test.Motan2TestService
    registry: direct-registry
    serialization: simple
    basicRefer: mybasicRefer
    filter: "accessLog, myfilter" #此处配置了两个filter,一个`accessLog`为系统自带的访问日志记录filter,另一个是自定义的`myfilter`。

配置后,myfilter会在调用中生效。上述自定义扩展的例子可以参考main/agentdemo.go

Motan2协议

Motan2协议相比Motan协议,更方便代理与跨语言解析。Motan2协议把请求中的meta信息与请求参数信息进行了分离,更适合对motan消息进行代理与路由;使用utf-8字符进行编码更适合不同语言进行解析处理。

Motan2协议分为Header、Metadata、Body三个部分。

Header

Header部分主要包括魔数、版本、消息类型、序列化方式、状态、消息id等内容,总共104bit(13byte)

Header字段名称 字段说明 长度(bit) 取值及意义
megicNum 魔数 16 固定为0xF1F1
messageType 保留 3 保留,后续扩展使用
是否心跳请求 1 1为心跳请求,0为非心跳请求
是否gzip压缩 1 1为gzip压缩,0为非压缩
是否单向请求 1 1为单向请求(不需要回包),0为非单向请求
是否代理请求 1 1为代理请求,0为直接请求
消息类型 1 0为request,1为response
version 协议版本号 5 原motan协议版本号为0,motan2协议版本号为1。
status 消息状态 3 0 正常消息,1 请求处理异常。共支持2^3即8种状态。request和response可以分别表示不同状态,其他状态待扩展
serialize 序列化协议 5 0 hessian,1 grpc-pb,2 json,3 msgpack,4 hprose,5 pb,6 simple,7 grpc-pb-json,其他待扩展
reserve 保留 3 保留
requestId 消息id 64 long型requestId。requestid需要保证对同一节点请求唯一。重复请求时可以使用相同requestId

Metadata

Metadata中包括请求的service名、方法、group以及携带的附加信息。Metadata只支持字符类型的k-v键值对,这些k、v使用utf-8进行编码,每个字符串之间通过\n进行分隔,因此,Metadata信息中不允许使用\n字符 Metadata部分的格式为:

字段名称 字段说明 长度(bit) 取值及意义
metasize metadata的长度 32 int32类型,metadata数据字节长度,为0时没有metadata。
metadata metadata的内容 由metasize指定 metadata信息。utf8类型string,由\n分隔的多个string组成kv对。

Metadata中,Motan框架使用的信息都是以M_开头的key,因此,通过Metadata携带自定义业务参数时,不允许使用M_作为自定义key的前缀

消息类型 参数名 含义 是否必填
request M_p 请求path。即请求的service名 T
M_m 请求方法名。 T
M_g 调用group F
M_md 请求方法参数描述 F
M_a auth认证信息 F
M_s 调用方信息 F
M_v 接口版本号 F
M_mdu module服务模块。 F
M_pp agent转发协议 F
M_is meta固定信息签名 F
response M_e 请求错误信息 F
M_pt 处理耗时 F

Body

Body部分用来存放请求的参数或响应的具体内容,body部分为header中指定序列化方式序列化后的byte数组。如果header中为gzip压缩状态,则Body部分是先进行序列化,然后进行gzip压缩后的byte数组。

Body部分格式为:

字段名称 字段说明 长度(bit) 取值及意义
bodysize Body部分的长度 32 int32类型,Body数据字节长度,为0时没有Body内容。
body Body的内容 由bodysize指定 body内容。例如request时的params,和response的value。

Simple序列化

simple序列化时为跨语言调用时使用的一种简单序列化协议,simple协议目前仅支持空、utf-8 string、string组成的map、以及byte字节流。simple协议比较适用于不包括复杂数据结构的跨语言交互,比较适合类似Rest风格的服务进行motan服务化转化。simple序列化在motan协议中的序列化编号为6.

simple序列化的格式为 type(1byte) + size(4byte) + content 其中type表示序列化对象的类型,size是序列化数据的字节长度,content是序列化后的内容,长度由size指定。

目前支持的类型如下:

type 说明
0 空对象
1 utf-8 string
2 map,k、v都是utf-8 string。格式为size + keystring + size + valuestring ...
3 byte array. 格式为 size + byte array
Clone this wiki locally