zoukankan      html  css  js  c++  java
  • golang——net/rpc包学习

    1、rpc包

    rpc包提供了通过网络或其他I/O连接对一个对象的导出方法的访问。

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

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

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

    其中T、T1和T2都能被encoding/gob包序列化。

    方法的第一个参数代表调用者提供的参数;第二个参数代表返回给调用者的参数。

    方法的返回值,如果非nil,将被作为字符串回传,在客户端看来就和errors.New创建的一样。

    如果返回了错误,回复的参数将不会被发送给客户端。

    代码示例:

    package main
    
    import (
    	"errors"
    	"fmt"
    	"log"
    	"net"
    	"net/http"
    	"net/rpc"
    )
    
    // Args 参数
    type Args struct {
    	A, B int
    }
    
    // Quotient 商、余数
    type Quotient struct {
    	Quo, Rem int
    }
    
    // Arith 算术服务
    type Arith int
    
    // Multiply 乘法服务
    func (*Arith) Multiply(args *Args, reply *int) error {
    	*reply = args.A * args.B
    	return nil
    }
    
    // Divide 除法服务
    func (*Arith) Divide(args *Args, quo *Quotient) error {
    	if args.B == 0 {
    		return errors.New("除数不能为零")
    	}
    	quo.Quo = args.A / args.B
    	quo.Rem = args.A % args.B
    	return nil
    }
    
    // 错误检查
    func checkErr(err error) {
    	if err != nil {
    		log.Fatalln(err)
    	}
    }
    
    func main() {
    	//开启服务
    	arith := new(Arith)
    	//使用默认服务对象
    	err := rpc.Register(arith)
    	checkErr(err)
    	//默认路径
    	// const (
    	// 	DefaultRPCPath   = "/_goRPC_"
    	// 	DefaultDebugPath = "/debug/rpc"
    	// )
    	rpc.HandleHTTP()
    	//设置监听
    	lis, err := net.Listen("tcp", ":1234")
    	checkErr(err)
    	go http.Serve(lis, nil)
    
    	//客户端请求服务
    	client, err := rpc.DialHTTP("tcp", ":1234")
    	checkErr(err)
    	defer client.Close()
    	//乘法
    	args := &Args{A: 17, B: 3}
    	var reply int
    	err = client.Call("Arith.Multiply", args, &reply)
    	checkErr(err)
    	fmt.Printf("Arith.Multiply:%d * %d = %d
    ", args.A, args.B, reply)
    	//除法
    	quotient := new(Quotient)
    	call := client.Go("Arith.Divide", args, quotient, nil)
    	<-call.Done
    	fmt.Printf("Arith.Divide:%d / %d = %d .... %d
    ", args.A, args.B, quotient.Quo, quotient.Rem)
    }
    
    //输出
    //Arith.Multiply:17 * 3 = 51
    // Arith.Divide:17 / 3 = 5 .... 2
    

    2、客户端

    2.1、type Client struct{}

    Client类型代表RPC客户端。

    同一个客户端可能有多个未返回的调用,也可能被多个go程同时使用。

    2.2、常用方法

    (1)func NewClient(conn io.ReadWriteCloser) *Client

    NewClient返回一个新的Client,以管理对连接另一端的服务的请求。

    (2)func Dial(network, address string) (*Client, error)

    Dial在指定的网络和地址与RPC服务端连接。

    (3)func DialHTTP(network, address string) (*Client, error)

    DialHTTP在指定的网络和地址与在默认HTTP RPC路径监听的HTTP RPC服务端连接。

    (4)func DialHTTPPath(network, address, path string) (*Client, error)

    DialHTTPPath在指定的网络、地址和路径与HTTP RPC服务端连接。

    (5)func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error

    Call调用指定的方法,等待调用返回,将结果写入reply,然后返回执行的错误状态。

    (6)func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call

    Go异步的调用函数。本方法Call结构体类型指针的返回值代表该次远程调用。

    通道类型的参数done会在本次调用完成时发出信号(通过返回本次Go方法的返回值)。

    如果done为nil,Go会申请一个新的通道(写入返回值的Done字段);如果done非nil,done必须有缓冲,否则Go方法会故意崩溃。

    (7)func (client *Client) Close() error

    关闭客户端。

    3、服务端

    3.1、type Server struct{}

    rpc包提供默认的服务对象,可直接通过“rpc.”进行使用。

    3.2、常用方法

    (1)func NewServer() *Server

    创建并返回一个*Server。

    (2)func (server *Server) Register(rcvr interface{}) error

    注册服务。

    如果rcvr不是一个导出类型的值,或者该类型没有满足要求的方法,Register会返回错误。

    Register也会使用log包将错误写入日志。

    客户端可以使用格式为"Type.Method"的字符串访问这些方法,其中Type是rcvr的具体类型。

    (3)func (server *Server) RegisterName(name string, rcvr interface{}) error

    RegisterName类似Register,但使用提供的name代替rcvr的具体类型名作为服务名。

    (4)func (server *Server) Accept(lis net.Listener)

    Accept接收监听器l获取的连接,然后服务每一个连接。

    Accept会阻塞,调用者应另开线程。

    (5)func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)

    ServeHTTP实现了回应RPC请求的http.Handler接口。

    (6)func (server *Server) HandleHTTP(rpcPath, debugPath string)

    HandleHTTP注册server的RPC信息HTTP处理器对应到rpcPath,注册server的debug信息HTTP处理器对应到debugPath。

    HandleHTTP会注册到http.DefaultServeMux。之后,仍需要调用http.Serve(),一般会另开线程:"go http.Serve(l, nil)"

    笃志:“博学而笃志,切问而近思,仁在其中矣。”
    弘毅:“士不可以不弘毅,任重而道远。”
    止于至善:“大学之道,在明明德,在亲民,在止于至善。”
    关注:笃志弘毅,止于至善
  • 相关阅读:
    还需要做恰当的解读,此时你可能需要一些书:
    创业公司的架构演进史
    任务调度平台Cuckoo-Schedule
    ORACLE中死锁
    Action的模型绑定
    三次握手、四次握手、backlog
    Django框架
    扩展BootstrapTable的treegrid功能
    Identity Service
    Linux权限
  • 原文地址:https://www.cnblogs.com/dzhy/p/11086905.html
Copyright © 2011-2022 走看看