golang rpc usage

antonlin · 2020-04-22 18:21:32 · 720 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2020-04-22 18:21:32 的文章,其中的信息可能已经有所发展或是发生改变。

golang rpc usage

引言

这个文章不对RPC的底层实现做深入剖析,也不讲解RPC是什么~~

sample

RPC三步走,方法模型、服务端搭建、客户端设计

model

我们以设计一个做加法运算的方法为例子

type Math int //Math类
type Args struct {
    Ops1 int
    Ops2 int
}

func (m *Math) Add(args Args, reply *int) error {
    log.Print("server call Add")
    *reply = args.Ops1 + args.Ops1
    return nil
}

server

func main() {
    //创建对象
    math := new(Math)
    //rpc服务注册了一个Math对象 公开方法供客户端调用
    _ = rpc.Register(math)
    //指定rpc的传输协议 这里采用http协议作为rpc调用的载体 也可以用rpc.ServeConn处理单个连接请求
    rpc.HandleHTTP()
    l, e := net.Listen("tcp", ":8080")
    if e != nil {
        log.Fatal("listen error", e)
    }
    go http.Serve(l, nil)
    _, _ = os.Stdin.Read(make([]byte, 1))//blocked
}

以上就是server的设计。

client

//为了更规范编码,采用OOP思想进行封装
type MathCaller struct {
    client *rpc.Client
    Math//for overridge
}
//内置客户端
func NewHttpMathCaller(addr string) *MathCaller {
    //调用rpc服务端提供的方法之前,先与rpc服务端建立连接
    client, err := rpc.DialHTTP("tcp", addr)
    if err != nil {
        log.Fatal("dialHttp error", err)
        return nil
    }
    mc := new(MathCaller)
    mc.client = client
    return mc
}

//同步调用
func (mc *MathCaller) Add(args Args, reply *int) error {
    return mc.client.Call("Math.Add", args, reply)//通过这种方式,调用的时候,就类似于本地
}

client main

func main(){
    //调用rpc服务端提供的方法之前,先与rpc服务端建立连接
    mc := rpcs.NewHttpMathCaller("127.0.0.1:8080")
    //同步调用服务端提供的方法
    args := &rpcs.Args{Ops1: 7, Ops2: 9}
    var reply int
    _ = mc.Add(*args, &reply)//调用封装后的RPC,看起来更像是调用本地的mathcaller的Add方法。
}

总结

以上的RPC sample只适用于golang的C/S之间的调用,因为底层使用了gob编码,并非是一种通用化编码,因此,如果要在golang与其它语言一块使用rpc,那么,可以使用gRPC+protubuf。或者是使用sonrpc这种基于json协议的RPC调用。

Jsonrpc

基于jsonrpc,补充一个简单的demo.

func JsonRpcServer() error {
    lis, err := net.Listen("tcp", ":1234")
    if err != nil {
        return err
    }
    defer lis.Close()
    srv := rpc.NewServer()
      //注册rpc对象
    if err := srv.RegisterName("Math", new(Math)); err != nil {
        return err
    }
    for {
        conn, err := lis.Accept()
        if err != nil {
            log.Fatalf("lis.Accept(): %v\n", err)
        }
        go srv.ServeCodec(jsonrpc.NewServerCodec(conn))
    }
}
func JsonClientRpc() {
    client, err := jsonrpc.Dial("tcp", "127.0.0.1:1234") //tcp
    if err != nil {
        log.Fatal("dialing:", err)
    }
    args := &Args{Ops1: 7, Ops2: 9}
    var reply int
    err = client.Call("Math.Add", args, &reply)
    if err != nil {
        log.Fatal("rpc Math.xx err:", err)
    }
    fmt.Println("remote return:", reply)
}

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

720 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传