kitc执行流程分析

最近阅读了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
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值