GO 语言实现最简单的 RPC

本节我们以GO 语言为例,实现一个最简单的 RPC 通信示例。

1. 创建 服务端 项目

项目目录 : /rpcdDemo/server

初始化 go mod

go mod init rpcserver

创建 main.go,编写如下代码:

package main

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

// 服务 : 提供一个矩形面积、周长计算服务

// 定义一个矩形结构体
type Rectangle struct {
}

// 定义参数结构
type Params struct {
	Width  float64 `json:"width"`
	Height float64 `json:"height"`
}

// 计算矩形面积
func (rect *Rectangle) Area(p Params, result *float64) error {
	*result = p.Width * p.Height
	return nil
}

// 计算矩形周长
func (rect *Rectangle) Perimeter(p Params, result *float64) error {
	*result = (p.Width + p.Height) * 2
	return nil
}

// 开启服务等待调用
func main() {
	// 注册服务
	rect := Rectangle{}
	rpc.Register(&rect)
	// 把服务绑定到 http 协议上
	rpc.HandleHTTP()
	// 监听服务,等待客户端调用
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Printf("err: %v\n", err)
	}
}

运行服务端

go run main.go

2. 创建客户端调用服务端函数

项目目录 : /rpcdDemo/client

初始化 go mod

go mod init rpcclient

创建 main.go,编写如下代码:

package main

import (
	"fmt"
	"net/rpc"
)

// 定义参数结构
type Params struct {
	Width  float64 `json:"width"`
	Height float64 `json:"height"`
}

func main() {
	// 调用服务
	// 链接 rpc 服务
	client, err := rpc.DialHTTP("tcp", "127.0.0.1:8080")
	if err != nil {
		panic(err)
	}
	//
	var result float64
	client.Call("Rectangle.Area", Params{10, 20}, &result)
	fmt.Printf("面积: %v\n", result)
	client.Call("Rectangle.Perimeter", Params{10, 20}, &result)
	fmt.Printf("周长: %v\n", result)
}

运行项目

go run main.go 

执行结果 :

...client> go run main.go
面积: 200
周长: 60

说明

通过上面的操作,我们已经实现了基于 go 语言的 rpc 通信,客户端成功调用了服务端的矩形面积、周长计算函数,传递参数并获得对应的结果。

这种方式近适用于 go 语言项目间的通信,如果一个项目的微服务使用多种语言开发就无法完成服务之间的通信了。

请继续阅读下一节,学习 gRPC 知识,来实现跨语言的 RPC 通信。