golang rpc

rpc是什么

RPC(Remote Procedure Call)是远程过程调用,通俗的说就是调用远处的一个函数。

入门

一. RPC版 HelloWorld

服务端代码

type HelloWorldService struct {
}

func (hello *HelloWorldService) Hello(request string, reply *string) error {
    *reply = "recieved msg :" + request + "\n"
    return nil
}
func Run() {
    rpc.RegisterName("HelloService", new(HelloWorldService))
    listen, err := net.Listen("tcp", "127.0.0.1:9090")
    if err != nil {
        log.Fatalln(err)
    }
    conn, err := listen.Accept()
    if err != nil {
        log.Fatalln(err)
    }
    rpc.ServeConn(conn)
}

说明:rpc.RegisterName会将HelloWorldService对象中所有满足rpc规则的方法注册为rpc函数,并放在HelloService服务空间之下。其中Hello方法必须满足以下规则:

  1. 访问限制必须公开
  2. 只能有2个序列化参数,第二个参数必须是指针类型
  3. 返回error类型

客户端代码:

func main()  {
    client, err := rpc.Dial("tcp", "127.0.0.1:9090")
    if err !=nil {
        log.Fatalln(err)
    }
    var reply string
    err = client.Call("HelloService.Hello", "Hello World", &reply)
    if err !=nil {
        log.Fatalln(err)
    }
    fmt.Println(reply)
}

首先通过rpc.Dial拨号rpc服务,cient.Call()可理解为呼叫,其第一个参数是rpc的服务服务名和方法名,第二和第三个参数是该方法的2个参数。

二. 更安全的RPC接口

在设计RPC的应用中,作为开发人员至少有3中角色:

  1. 服务器端实现RPC方法的开发人员
  2. 客户端调用RPC方法的开发人员
  3. 制定服务端和客户端RPC接口规范的设计人员

上面HelloWorld的例子虽然看似简单,但是不利于后期的维护和工作的切割,其中存在一个较大的问题是:
客户端中,Call()方法的参数无法得到编译器安全检查,只有运行时才能发现错误。

服务端代码:

  • 接口定义
const HelloServiceName = "study.rpc.HelloService"

type HelloServiceInterface  interface {
    Hello(request string,reply *string) error
}

func RegisterHelloService(srv HelloServiceInterface) error {
    return rpc.RegisterName(HelloServiceName,srv)
}
  • 服务端代码
type HelloWorldService struct {
}

func (hello *HelloWorldService) Hello(request string, reply *string) error {
    *reply = "recieved msg :" + request + "\n"
    return nil
}

func main()  {
    RegisterHelloService(new(HelloWorldService))
    listen, err := net.Listen("tcp", "127.0.0.1:9090")
    if err != nil {
        log.Fatalln(err)
    }
    for  {
        conn, err := listen.Accept()
        if err != nil {
            log.Fatalln(err)
        }
        go rpc.ServeConn(conn)
    }
}
  • 客户端代码

type HelloServiceClient struct {
    *rpc.Client
}

//检测HelloServiceClient 是否实现了 HelloServiceInterface 
var _ HelloServiceInterface = (*HelloServiceClient)(nil)

func (client *HelloServiceClient) Hello(request string, reply *string) error {
    return client.Call(HelloServiceName+".Hello",request,reply)
}

func DialHelloService(network string,addr string) (*HelloServiceClient,error) {
    client, err := rpc.Dial(network, addr)
    if err !=nil {
        return nil,err
    }
    return &HelloServiceClient{client},nil
}

func main()  {
    service, err := DialHelloService("tcp", "127.0.0.1:9090")
    if err !=nil {
        log.Fatalln(err)
    }
    var reply string
    err = service.Hello("Hello world", &reply)
    if err !=nil {
        log.Fatalln(err)
    }
    fmt.Println(reply)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,...
    ebayboy阅读 539评论 0 1
  • 今天看到不少公司都是用rpc 挺好奇的 不知道为何要用rpc?搜了一圈看一些说法是http可能性能低,而tcp要处...
    jiqiren007阅读 9,394评论 2 2
  • gRPC 简介: gRPC 是一款高性能、开源的 RPC 框架,产自 Google,基于 ProtoBuf 序列化...
    谢烟客阅读 10,578评论 6 36
  • 本文将从大的框架层面来聊聊RPC原理和实现,既然叫跨语言RPC,也将以thrift为例讲讲跨语言RPC如何实现。在...
    彦帧阅读 15,087评论 0 19
  • 转自:http://blog.csdn.net/kesonyk/article/details/50924489 ...
    晴天哥_王志阅读 25,008评论 2 38