RPC(Remote Procedure Call)笔记

RPC设计的目的:
隐藏客户端服务器通信细节
客户端调用更加像传统的过程调用
服务器处理更加像传统的过程调用

RPC理想是把网络通信做的跟函数调用一样。

  • Client

      z = fn(x, y)
    
  • Server

      fn(x, y) {
          compute
          return z
      }
    

*** RPC设计的目标是这种程度的透明度。 ***

服务器端

import "net/rpc"

创建远程调用对象

服务端(Register)注册一个对象,使它作为一个服务被暴露,服务的名字是该对象的类型名。注册之后,对象的导出方法就可以被远程访问。服务端可以注册多个不同类型的对象(服务),但注册具有相同类型的多个对象是错误的。

只有满足如下标准的方法才能用于远程访问,其余方法会被忽略:

  • 方法是导出的
  • 方法有两个参数,都是导出类型或内建类型
  • 方法的第二个参数是指针
  • 方法只有一个error接口类型的返回值

事实上,方法必须看起来像这样:

func (t *T) MethodName(argType T1, replyType *T2) error

比如:

type Args struct {
    A, B int
}

type Arith int

func (t *Arith) Multiply(args *Args, reply *int) error {
    *reply = args.A * args.B
    return nil
}
注册对象
arith := new(Arith)
rpc.Register(arith)
创建监听,接收并处理请求
rpc.HandleHTTP()

// 监听端口 1234
l, e := net.Listen("tcp", ":1234")
if e != nil {
    log.Fatal("listen error: ", e)
}
http.Serve(l, nil)
客户端
和服务器端建立连接
client, err := rpc.DialHTTP("tcp", "127.0.0.1:1234")
if err != nil {
    log.Fatal("dialing: ", err)
}
执行远程调用

执行远程调用,有两种方式:同步和异步。

// 同步调用,Call会等待远端调用完成
args := &Args{7, 8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)

fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
// 异步调用,Go方法异步地发送调用请求,并使用返回的Call结构体类型的Done通道字段传递完成信号
quotient := new(Quotient)
divCall := client.Go("Arith.Divide", args, quotient, nil)
<-divCall.Done

fmt.Printf("Arith: %d/%d=%d...%d\n", args.A, args.B, quotient.Quo, quotient.Rem)

--End
Mason

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容