RPC(Remote Procedure Call,远程过程调用)是一种通过网络请求从远程服务器调用服务,而不需要了解底层网络细节的应用程序通信协议。RPC 协议基于传输层的 TCP 或 UDP 协议,或者是应用层的 HTTP 协议构建,允许开发者直接调用另一台计算机上的程序,而开发者无需额外地为这个调用过程编写网络通信相关代码,从而使得开发网络分布式应用程序更加容易,比如现在比较流行的微服务通常就是基于 RPC 协议。
案例代码目录结构
|---golang
|---src
|---demo
|---rpc
|---client.go
|---server.go
|---utils
|---common.go
common.go
package utils
type Args struct {
A, B int
}
RPC 服务端 – rpc/server.go
package main
import (
"demo/rpc/utils"
"errors"
"log"
"net"
"net/http"
"net/rpc"
)
type MathService struct {
}
func (m *MathService) Multiply(args *utils.Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (m *MathService) Divide(args *utils.Args, reply *int) error {
if args.B == 0 {
return errors.New("除数不能为0")
}
*reply = args.A / args.B
return nil
}
func main() {
// 启动 RPC 服务端
math := new(MathService)
rpc.Register(math)
rpc.HandleHTTP()
listener, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal("启动服务监听失败:", err)
}
err = http.Serve(listener, nil)
if err != nil {
log.Fatal("启动 HTTP 服务失败:", err)
}
}
RPC 客户端 – rpc/client.go
package main
import (
"demo/rpc/utils"
"fmt"
"log"
"net/rpc"
)
func main() {
var serverAddress = "localhost"
client, err := rpc.DialHTTP("tcp", serverAddress + ":8080")
if err != nil {
log.Fatal("建立与服务端连接失败:", err)
}
// 建立起连接后就可以调用远程服务器端的方法了
/* 1. 先看同步调用的方式 */
args := &utils.Args{10,10}
var reply int
err = client.Call("MathService.Multiply", args, &reply)
if err != nil {
log.Fatal("调用远程方法 MathService.Multiply 失败:", err)
}
fmt.Printf("%d*%d=%d\n", args.A, args.B, reply)
/* 2. 异步方式的rpc调用方式 */
divideCall := client.Go("MathService.Divide", args, &reply, nil)
for {
select {
case <-divideCall.Done:
fmt.Printf("%d/%d=%d\n", args.A, args.B, reply)
return
}
}
}
About the author