最近阅读了RPC框架kitc的部分源码,kitc是kite框架的客户端实现,kite框架是公司内部基于开源的thrift封装二次开发的,与开源的kite框架并不一样。kitc 的执行过程也是中间件调用链的执行过程。
对目标接口方法进行封装
// client端调用目标接口的方法,由工具根据接口定义自动生成
func (p *ExampleServiceClient) Method1(req *ExampleRequest) (r *ExampleResponse, err error) {
if err = p.sendMethod1(req); err != nil { return }
return p.recvMethod1()
}
// EndPoint represent one method for calling from remote.
// EndPoint 代表一个远端方法的调用过程
type EndPoint func(ctx context.Context, req interface{}) (resp interface{}, err error)
// 对目标接口方法进行封装,封装为endpoint.EndPoint类型
func mkMethod1(client *example.ExampleServiceClient) endpoint.EndPoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
transport := client.Transport.(kitc.Transport)
err := transport.OpenWithContext(ctx)
if err != nil {...}
defer transport.Close()
// Method1为proto文件中定义的服务接口
resp, err := client.Method1(request.(endpoint.KitcCallRequest).RealRequest().(*example.ExampleRequest))
addr := transport.RemoteAddr()
return &KitcExampleResponse{resp, addr}, err
}
}
kitc中间件的定义
// Middleware deal with input EndPoint and output EndPoint
// 输入为EndPoint类型,输出为EndPoint类型
type Middleware func(EndPoint) EndPoint
// client端执行目标接口方法调用
func (c *Client) Method1(ctx context.Context, r *example.ExampleRequest) (*KitcExampleResponse, error) {
kc := c.client
if kc == nil {...}
// 中间件的初始化
**ctx, err := kc.MethodInit("Method1", ctx, r)** @1
if err != nil {...}
client := GetExampleServiceClient(kc)
**next := mkMethod1(client)**
request := &KiteExampleRequest{r}
**resp, err := kc.MethodCall(next, ctx, request)** @2
kitcResp, ok := resp.(*KitcExampleResponse)
if !ok {...}
return kitcResp, err
}
// @1 处的代码
func (kc *KitcClient) MethodInit(method string, ctx context.Context, request interface{}) (context.Context, error) {
metricsClient.EmitCounter("kite.request.throughput", 1)
// 初始化中间件调用链,包含服务发现中间件,负载均衡中间件, 连接池中间件等等
kc.once.Do(kc.initMWChain)
// 因为request会被生成代码包裹,
// 如果用户使用了自定义的LB, 需要保证直接把最原始的req传递给用户
ctx = context.WithValue(ctx, KITC_RAW_REQUEST_KEY, request)
return kc.initRPCInfo(method, ctx)
}
// @2 处的代码
func (kc *KitcClient) MethodCall(next endpoint.EndPoint, ctx context.Context, request interface{}) (endpoint.KitcCallResponse, error) {
......
// kc.chain(next)执行中间件调用链,生成一个EndPoint类型,然后执行EndPoint方法
// 如此就完成了目标接口方法的调用
resp, err := kc.chain(next)(ctx, request)
if _, ok := resp.(endpoint.KitcCallResponse); !ok {...}
return resp.(endpoint.KitcCallResponse), err
}