1、golang中如何实现RPC
实现方式:
golang官方的net/rpc库使用encoding/gob进行编解码,支持tcp和http数据传输方式,由于其他语言不支持gob编解码方式,所以golang的RPC只支持golang开发的服务器与客户端之间的交互
官方还提供了net/rpc/jsonrpc库实现RPC方法,jsonrpc采用JSON进行数据编解码,因而支持跨语言调用,目前jsonrpc库是基于tcp协议实现的,暂不支持http传输方式
1.1 例题:golang实现RPC程序,实现求矩形面积和周长
服务端:
package main
import (
"log"
"net/http"
"net/rpc"
)
// 服务端
type Params struct {
Width, Height int
}
type Rect struct {
}
func (r *Rect) Area(p Params, ret *int) error {
*ret = p.Height * p.Width
return nil
}
func (r *Rect) Perimeter(p Params, ret *int) error {
*ret = 2 * (p.Height + p.Width)
return nil
}
func main(){
rect := new(Rect)
// 1.注册一个rect的服务
rpc.Register(rect)
// 2.服务处理绑定到http协议上
rpc.HandleHTTP()
// 3.监听服务
err := http.ListenAndServe(":8100", nil)
if err != nil {
log.Panicln(err)
}
}
客户端:
package main
import (
"fmt"
"log"
"net/rpc"
"time"
)
// golang实现RPC程序,实现求矩形面积和周长
// 客户端
type Params struct {
Width, Height int
}
func main(){
// 1、连接服务端
conn, err := rpc.DialHTTP("tcp", ":8100")
if err != nil {
log.Fatal(err)
}
// 2.调用方法
// 面积
ret := 0
t1 := time.Now()
err2 := conn.Call("Rect.Area", Params{50, 100}, &ret)
if err2 != nil {
log.Fatal(err2)
}
fmt.Println("面积:", ret)
t2 := time.Now()
fmt.Println(t2.Sub(t1))
// 周长
err3 := conn.Call("Rect.Perimeter", Params{50, 100}, &ret)
if err3 != nil {
log.Fatal(err3)
}
fmt.Println("周长:", ret)
fmt.Println(time.Now().Sub(t2))
}
1.2 golang写RPC程序,必备的4个基本条件
不然RPC用不了
结构体字段首字母要大写,可以别人调用
函数名必须首字母大写
函数第一参数是接收参数,第二个参数是返回给客户端的参数,必须是指针类型
函数还必须有一个返回值error
1.3 练习
模仿前面演示,实现RPC程序,服务端接收2个参数,可以做乘法运算,也可以做商和余数的运算,客户端进行传参和访问。
自定义客户端接收参数。
服务端:
package main
import (
"errors"
"log"
"net/http"
"net/rpc"
)
// 结构体,用于注册的
type Arith struct{}
// 声明参数结构体
type ArithRequest struct {
A, B int
}
// 返回给客户端的结果
type ArithResponse struct {
// 乘积
Pro int
// 商
Quo int
// 余数
Rem int
}
// 乘法
func (a *Arith) Multiply(req ArithRequest, res *ArithResponse) error {
res.Pro = req.A * req.B
return nil
}
// 商和余数
func (a *Arith) Divide(req ArithRequest, res *ArithResponse) error {
if req.B == 0 {
return errors.New("除数不能为0")
}
// 除
res.Quo = req.A / req.B
// 取模
res.Rem = req.A % req.B
return nil
}
// 主函数
func main() {
// 1.注册服务
rect := new(Arith)
// 注册一个rect的服务
rpc.Register(rect)
// 2.服务处理绑定到http协议上
rpc.HandleHTTP()
// 3.监听服务
err := http.ListenAndServe(":8100", nil)
if err != nil {
log.Fatal(err)
}
}
客户端:
package main
import (
"fmt"
"log"
"net/rpc"
)
type ArithRequest struct {
A, B int
}
// 返回给客户端的结果
type ArithResponse struct {
// 乘积
Pro int
// 商
Quo int
// 余数
Rem int
}
func main() {
conn, err := rpc.DialHTTP("tcp", ":8100")
if err != nil {
log.Fatal(err)
}
req := ArithRequest{9, 2}
var res ArithResponse
err2 := conn.Call("Arith.Multiply", req, &res)
if err2 != nil {
log.Fatal(err2)
}
fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)
err3 := conn.Call("Arith.Divide", req, &res)
if err3 != nil {
log.Fatal(err3)
}
fmt.Printf("%d / %d 商 %d,余数 = %d\n", req.A, req.B, res.Quo, res.Rem)
}
2、net/rpc/jsonrpc库 实现示例
net/rpc/jsonrpc库通过json格式编解码,支持跨语言调用
服务端代码:
package main
import (
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type Params struct {
Width, Height int
}
type Rect struct {
}
func (r *Rect) Area(p Params, ret *int) error {
*ret = p.Width * p.Height
return nil
}
func (r *Rect) Perimeter(p Params, ret *int) error {
*ret = (p.Height + p.Width) * 2
return nil
}
func main() {
rpc.Register(new(Rect))
// 开启 tcp 监听
lis, err := net.Listen("tcp", ":8100")
if err != nil {
log.Panicln(err)
}
for {
conn, err := lis.Accept()
if err != nil {
continue
}
go func(conn net.Conn) {
fmt.Println("new client")
jsonrpc.ServeConn(conn)
}(conn)
}
}
客户端代码:
package main
import (
"fmt"
"log"
"net/rpc/jsonrpc"
)
type Params struct {
Width, Height int
}
func main() {
conn, err := jsonrpc.Dial("tcp", ":8100")
if err != nil {
log.Panicln(err)
}
ret := 0
err2 := conn.Call("Rect.Area", Params{50, 100}, &ret)
if err2 != nil {
log.Panicln(err2)
}
fmt.Println("面积:", ret)
err3 := conn.Call("Rect.Perimeter", Params{50, 100}, &ret)
if err3 != nil {
log.Panicln(err3)
}
fmt.Println("周长:", ret)
}
3、自定义rpc使用过程中的网络传输数据格式
作者:joker.liu 创建时间:2023-05-18 11:54
最后编辑:joker.liu 更新时间:2023-05-18 14:40
最后编辑:joker.liu 更新时间:2023-05-18 14:40