当前位置: 首页 > article >正文

一个go http和grpc客户端库

大家好,我是peachesTao,今天是五一假期的第4天,首先祝大家劳动节快乐。今天给大家推荐一个统一http和grpc客户端调用的库,名为prpc,github地址:prpc,该库是我公司根据最佳实践总结开发出来的,它可以提升开发效率,让开发者聚焦于业务层代码。

下面我从三个方面来介绍

自动生成http客户端代码

1、编写http客户端代码痛点

首选我们来看一段调用http接口获取用户列表的代码

type GetUserListReq struct {
 Age  int32  `json:"age"`
}

type GetUserListReply struct {
 Code int32       `json:"code"`
 Msg  string      `json:"msg"`
 List []*UserInfo `json:"list"`
}

type UserInfo struct {
 Name string `json:"name"`
 Age  int32  `json:"age"`
}

func GetUserList(req *protocol.GetUserListReq) (*GetUserListReply, error) {
  user := config.GetServerConfig().User
  request, err := httplib.Post(user.URL+user.GetUserList).Debug(true).JSONBody(req)
  if err != nil {
    return nil, err
  }
  resp := new(protocol.GetUserListReply)
  err = request.ToJSON(resp)
  if err != nil {
    return nil, err
  }
  return resp, nil
}

分别定义了请求和响应数据结构体,从配置文件中获取http服务的url和用户列表接口的path,将请求结构体编码,然后通过http client库发起http请求,将返回的数据解码为响应结构体。

我们发现这样的代码有下面三个痛点

  1. 每次调用都要对req对象编码、res对象进行解码

  2. 需要在代码中硬编码读取配置服务端的url

  3. 如果服务端将Post改成Get方式,要改客户端的代码

这非常影响开发效率且容易出错,这些代码能不能自动生成?答案是可以的,凡是有规律的代码都可以自动生成。我们的实现方案是基于protobuf实现的。

2、基于protobuf的http客户端代码生成

我们使用protobuf定义服务调用方法、请求和响应结构体,再借助http Method Option自定义服务url和http method,最后用prpc内置的插件protoc-gen-go-prpc生成跟grpc相似的函数签名的客户端代码。

GetUserList protobuf文件定义:

syntax = "proto3";

option go_package = "/api/";
import "google/api/annotations.proto";

service User {
  //获取用户列表
  rpc GetUserList(GetUserListReq) returns (GetUserListReply) {
    option (google.api.http) = {
      get: "/user/list"
      body: "*"
      additional_bindings:[
        {custom:{kind:"Content-Type", path:"application/json"}}]
    };
  }
}

message GetUserListReq {
  int32 age = 1;
}

message GetUserListReply {
  int32 code = 1;
  string msg = 2 ;
  repeated UserInfo list = 3;
}

message UserInfo {
  string name = 1;
  int32 age = 2;
}

自动生成的调用入口函数如下(此处省略了其他部分代码,想看完整的代码可以前往prpc-examples):

func (c *userClient) GetUserList(ctx context.Context, in *GetUserListReq, opts ...http.CallOption) (*GetUserListReply, error) {
 out := new(GetUserListReply)
 header := map[string]string{
  "Content-Type": "application/json",
 }
 opts = http.CallOptions(opts).CombineHeader(header)
 err := c.cc.HttpInvoke(ctx, "GET", "/user/list", in, out, opts...)
 if err != nil {
  return nil, err
 }
 return out, nil
}

开发者侧代码:

 conn := prpc.NewClientConn()
 err := conn.NewHttpClientConn(context.Background(), "127.0.0.1:8000")
 if err != nil {
  log.Error(err)
  return
 }
 userClient := api.NewUserClient(conn)
 listReply, err := userClient.GetUserList(context.Background(), &api.GetUserListReq{Age: 18})
 if err != nil {
  log.Error(err)
  return
 }
 log.Info(listReply)

可以看出,开发者就像调用grpc方法一样简单的调用http接口,实现了对协议的无感,开发者只需要在protobuf中定义相关信息,其他的交给插件就行。

http和grpc调用随意切换

因为http和grpc客户端调用代码都是根据protobuf生成的,生成的是http还是grpc取决于rpc方法是否定义了http method option,如果定义了则生成http代码,否则生成grpc调用代码。

所以http切换成grpc protobuf只需要删除http method option 部分即可,同理,grpc切换成http则加上它就行。

上面GetUserList改成grpc调用的话protobuf rpc方法定义如下:

service User {
  //获取用户列表
  rpc GetUserList(GetUserListReq) returns (GetUserListReply) {}
}

服务发现和负载均衡

prpc还包含集群模式下的服务发现和负载均衡功能,一套服务发现和负载均衡机制同时兼容http和grpc,且都支持扩展。

开发者只需要实现resolver和balancer接口就可以自定义服务发现和负载均衡,目前prpc内置了基于consul的服务发现和轮训的负载均衡功能。

后续我们将增加基于zookeeper,etcd的服务发现和实现权重的负载均衡方式,也欢迎小伙伴积极参与进来,给我们贡献代码,共同完善prpc。

更多的细节请前往github prpc了解

相关链接

[prpc] https://github.com/classtorch/prpc
[prpc-examples] https://github.com/classtorch/prpc-examples


http://www.kler.cn/news/17474.html

相关文章:

  • Zigbee 无线串口通信模块( DL-22 )
  • 【Python入门篇】——Python基础语法(标识符与运算符)
  • 文献集锦 | 非因生物空间多组学技术在头颈部肿瘤中的研究策略
  • 7.3 有源滤波电路(1)
  • Springcloud--docker快速入门
  • k8s DCGM GPU采集指标项说明
  • 操作系统之死锁处理策略
  • 体验 nanoGPT
  • PWLCM分段线性混沌映射
  • 日语学习(一)
  • flink-on-yarn两种提交模式及其区别
  • 【Linux问题合集001】Linux中如何将用户添加到sudo组中的步骤
  • 武忠祥老师每日一题||不定积分基础训练(六)
  • Lattics ——一款简单易用、好看强大的知识管理工具
  • 【Spring Security第一篇】初始Spring Security、表单认证、认证与授权
  • Docker安全最佳实践
  • 算法的时间复杂度和空间复杂度(友友们专属限定版)
  • linux常用操作
  • Java ---比较器
  • 武忠祥老师每日一题||定积分基础训练(五)
  • java基础:接口的定义与实现
  • 今日事务java所感
  • 深入源码理解redis数据结构(一)
  • 从 Elasticsearch 到 Apache Doris,10 倍性价比的新一代日志存储分析平台
  • IronOCR 2023.4.13 Crack
  • 【移动端网页布局】流式布局案例 ⑥ ( 多排按钮导航栏 | 设置浮动及宽度 | 设置图片样式 | 设置文本 )
  • JDK17新特性之--新的Compact Strings(JEP 254)
  • 以两分钟了解Python之SQLAlchemy框架的使用
  • 腾讯云的cdn怎么配置|腾讯云CDN配置教程
  • ps磨皮插件专用智能磨皮插件 AI算法美颜 提高P图效率