Skip to main content

rpc

rpc简介

rpc入门

从字面上可以看出,remote远程那么就一定离不开网络

应用:比如北京的客户端去调用上海服务器的方法

在开始rpc之前,先回顾一下网络socket通信

server端:
net.Listen() ===>listener 创建监听器
listener.Accept() ===> conn 启动监听 建立连接
conn.Read()
conn.Write()
defer conn.Close() / listener.Close()

client端:
net.Dial() ===>conn
conn.Write()
conn.Read()
defer conn.Close()

rpc的使用步骤:

  • 服务端:
    1. 注册rpc服务对象:给对象绑定方法(1,定义类 2,绑定类方法)
    rpc.RegisterName("服务名",回调对象) //下面的HelloWorld就是回调函数
    1. 创建监听器
    listener,err := net.Listen()
    1. 建立连接
    conn, err := listener.Accept()
    1. 将连接绑定rpc服务
    rpc.ServeConn(conn)
  • 客户端:
    1. 用rpc去连接服务器
    conn, err := rpc.Dial()
    1. 像调用本地函数一样去调用远程函数
    conn.Call("服务名.方法名", 传入参数, 传出参数)

rpc相关函数:

  1. 注册rpc服务
  • func RegisterName(name string, rcvr interface{}) error
1. 参数1-name 服务名,string. 
2. 参数2-rcvr 对应的rpc对象 空接口类型/指针 该对象绑定的方法需满足:
a,必须是导出的(包外可见,首字母大写)
b,方法必须有2个参数,第一个参数是传入参数
第二个是传出参数都是导出类型或内置类型
c,方法的第二个参数必须是指针(传出参数)
d,方法只有一个error接口类型的返回值

请看下面的示例:

type World struct{}

//方法只有一个error接口类型的返回值,eg
func (this *World) HelloWorld(name string, resp *string) error{

}

rpc.RegisterName("服务名",new(World))

  1. 绑定rpc服务
  • func ServeConn(conn io.ReadWriteCloser)
conn: 就是成功建立连接的socket --- conn
  1. 调用远程函数
  • func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
serviceMethod: "服务名.方法名"
args: 传入参数,方法所需要的数据
reply:传出参数,定义var 变量, &变量名 完成传参

rpc-server

package main

import (
"log"
"net"
"net/rpc"
)

//定义类对象
type World struct {
}

//绑定类方法
func (this *World) HelloWorld(name string, resp *string) error { //HelloWorld首字母要大写
*resp = name + "你好!"
return nil
}

func main() {
//1,注册rpc服务 绑定对象方法
err := rpc.RegisterName("hello", new(World))
if err != nil {
log.Println("注册rpc服务失败:", err)
return
}
//2,设置监听
listener, err := net.Listen("tcp", "127.0.0.1:8800")
if err != nil {
log.Println("net.Listen() error:", err)
return
}
defer listener.Close()
log.Printf("开始监听")
//3,建立连接
conn, err := listener.Accept()
if err != nil {
log.Println("listener.Accept() error:", err)
return
}
log.Printf("连接成功")
//4,绑定服务
rpc.ServeConn(conn)
}

rpc-client

package main

import (
"fmt"
"log"
"net/rpc"
)

func main() {
//1. 用rpc去连接服务器
conn, err := rpc.Dial("tcp", "127.0.0.1:8800")
if err != nil {
log.Println("rpc.Dial() error:", err)
return
}
defer conn.Close()
//2,调用远程服务
var reply string //接收返回值(传出参数)
err = conn.Call("hello.HelloWorld", "Scott", &reply)
if err != nil {
log.Println("conn.Call() error:", err)
return
}
fmt.Println(reply)
}

run: