Go语言中的RPC调用

Go语言中的RPC调用

首先,说一下目录结构:

一、HttpRPC

1、建立服务文件

/*Go RPC的函数只有符合下面的条件才能被远程访问,不然会被忽略,详细的要求如下:
函数必须是导出的(首字母大写)
必须有两个导出类型的参数,
第一个参数是接收的参数,第二个参数是返回给客户端的参数,第二个参数必须是指针类型的
函数还要有一个返回值error
举个例子,正确的RPC函数格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error
*/
package common

import (
    "errors"
)

type Args struct {
    A, B float32
}
type Result struct {
    Value float32
}
type MathService struct {
}

func (s *MathService) Add(args *Args, result *Result) error {
    result.Value = args.A + args.B
    return nil
}

func (s *MathService) Divide(args *Args, result *Result) error {
    if args.B == 0 {
        return errors.New("除数不能为零!")
    }
    result.Value = args.A / args.B
    return nil
}

2、服务端代码:

package main

import (
    "fmt"
    "net/http"
    "net/rpc"

    "../common"
)

func main() {
    var ms = new(common.MathService)
    rpc.Register(ms)
    rpc.HandleHTTP() //将Rpc绑定到HTTP协议上。
    fmt.Println("启动服务...")
    err := http.ListenAndServe(":1234", nil)
    if err != nil {
        fmt.Println(err.Error())
    }
    fmt.Println("服务已停止!")
}

3、客户端调用代码:

package main

import (
    "fmt"
    "net/rpc"

    "../common"
)

func main() {
    var args = common.Args{17, 8}
    var result = common.Result{}

    var client, err = rpc.DialHTTP("tcp", "127.0.0.1:1234")
    if err != nil {
        fmt.Println("连接RPC服务失败:", err)
    }
    err = client.Call("MathService.Divide", args, &result)
    if err != nil {
        fmt.Println("调用失败:", err)
    }
    fmt.Println("调用结果:", result.Value)
}

4、测试:

二、HttpRPC

1、建立服务文件

/*Go RPC的函数只有符合下面的条件才能被远程访问,不然会被忽略,详细的要求如下:
函数必须是导出的(首字母大写)
必须有两个导出类型的参数,
第一个参数是接收的参数,第二个参数是返回给客户端的参数,第二个参数必须是指针类型的
函数还要有一个返回值error
举个例子,正确的RPC函数格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error
*/
package common

import (
    "errors"
)

type Args struct {
    A, B float32
}
type Result struct {
    Value float32
}
type MathService struct {
}

func (s *MathService) Add(args *Args, result *Result) error {
    result.Value = args.A + args.B
    return nil
}

func (s *MathService) Divide(args *Args, result *Result) error {
    if args.B == 0 {
        return errors.New("除数不能为零!")
    }
    result.Value = args.A / args.B
    return nil
}

2、服务端文件

package main

import (
    "fmt"
    "net"
    "net/rpc"

    "../common"
)

func main() {
    var ms = new(common.MathService) //实例化服务对像
    rpc.Register(ms)                 //注册这个服务
    fmt.Println("启动服务...")
    var address, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:1234") //定义TCP的服务承载地址
    listener, err := net.ListenTCP("tcp", address)               //监听TCP连接
    if err != nil {
        fmt.Println("启动失败!", err)
    }
    for {
        conn, err := listener.Accept() //如果接受到连接
        if err != nil {
            continue
        }
        fmt.Println("接收到一个调用请求...")
        rpc.ServeConn(conn) //让此rpc绑定到该Tcp连接上。
    }
    //fmt.Println("服务已停止!")
}

3、客户端代码:

// main.go
package main

import (
    "fmt"
    "net/rpc"

    "../common"
)

func main() {
    var client, err = rpc.Dial("tcp", "127.0.0.1:1234")
    if err != nil {
        fmt.Println("连接不到服务器:", err)
    }
    var args = common.Args{40, 3}
    var result = common.Result{}
    fmt.Println("开始调用!")
    err = client.Call("MathService.Add", args, &result)
    if err != nil {
        fmt.Println("调用失败!", err)
    }
    fmt.Println("调用成功!结果:", result.Value)
}

4、效果:


Go语言中的RPC调用
https://www.dearcloud.cn/2016/03/09/20200310-cnblogs-old-posts/20160309-Go语言中的RPC调用/
作者
宋兴柱
发布于
2016年3月9日
许可协议