答案:Go的net/rpc包通过gob序列化实现Go语言间简单高效的RPC通信,适用于内部服务交互。它使用标准库即可完成服务注册、TCP监听与调用,但仅限Go环境、缺乏跨语言支持与高级特性。

在Go语言的世界里,实现RPC(远程过程调用)服务其实远没有想象中那么复杂,尤其是当你选择使用其内置的
net/rpc
net/rpc
要实现一个基于
net/rpc
服务端实现:
定义服务结构体和方法: 创建一个普通的Go结构体,并为其定义方法。这些方法必须遵循
func (t *T) MethodName(args *ArgsType, reply *ReplyType) error
ArgsType
ReplyType
gob
net/rpc
gob
package main
import (
"log"
"net"
"net/rpc"
"time"
)
// Arith 是一个算术服务
type Arith struct{}
// Args 是算术方法的参数
type Args struct {
A, B int
}
// Multiply 方法用于计算乘积
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
log.Printf("Server received Multiply(%d, %d), returning %d", args.A, args.B, *reply)
return nil
}
// Divide 方法用于计算除法
func (t *Arith) Divide(args *Args, reply *float64) error {
if args.B == 0 {
return rpc.ErrShutdown // 模拟一个错误
}
*reply = float64(args.A) / float64(args.B)
log.Printf("Server received Divide(%d, %d), returning %.2f", args.A, args.B, *reply)
return nil
}
func main() {
arith := new(Arith)
rpc.Register(arith) // 注册服务实例,服务名为 "Arith"
// 也可以使用 rpc.RegisterName("MyArithService", arith) 来指定服务名
listener, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatalf("Listen error: %v", err)
}
log.Println("RPC server listening on :1234")
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("Accept error: %v", err)
// 实际应用中可能需要更复杂的错误处理,比如重试或退出
time.Sleep(time.Second) // 避免CPU空转
continue
}
go rpc.ServeConn(conn) // 为每个连接启动一个 goroutine 处理RPC请求
}
}客户端实现:
立即学习“go语言免费学习笔记(深入)”;
连接RPC服务: 使用
rpc.Dial
rpc.DialHTTP
调用远程方法: 通过
client.Call("ServiceName.MethodName", args, &reply)package main
import (
"fmt"
"log"
"net/rpc"
"time"
)
// Args 结构体需要和服务端定义的一致
type Args struct {
A, B int
}
func main() {
// 尝试连接RPC服务,如果连接不上,会重试几次
var client *rpc.Client
var err error
for i := 0; i < 5; i++ {
client, err = rpc.Dial("tcp", "localhost:1234")
if err == nil {
log.Println("Successfully connected to RPC server.")
break
}
log.Printf("Failed to connect to RPC server, retrying in 2 seconds... (%v)", err)
time.Sleep(2 * time.Second)
}
if err != nil {
log.Fatalf("Could not connect to RPC server after multiple retries: %v", err)
}
defer client.Close()
// 调用 Multiply 方法
argsMultiply := Args{7, 8}
var replyMultiply int
err = client.Call("Arith.Multiply", argsMultiply, &replyMultiply)
if err != nil {
log.Fatalf("Arith.Multiply error: %v", err)
}
fmt.Printf("Arith: %d * %d = %d\n", argsMultiply.A, argsMultiply.B, replyMultiply)
// 调用 Divide 方法
argsDivide := Args{10, 3}
var replyDivide float64
err = client.Call("Arith.Divide", argsDivide, &replyDivide)
if err != nil {
log.Fatalf("Arith.Divide error: %v", err)
}
fmt.Printf("Arith: %d / %d = %.2f\n", argsDivide.A, argsDivide.B, replyDivide)
// 尝试一个会出错的调用
argsDivideByZero := Args{10, 0}
var replyDivideByZero float64
err = client.Call("Arith.Divide", argsDivideByZero, &replyDivideByZero)
if err != nil {
fmt.Printf("Arith.Divide (by zero) error: %v\n", err) // 预期会报错
} else {
fmt.Printf("Arith: %d / %d = %.2f (unexpected success)\n", argsDivideByZero.A, argsDivideByZero.B, replyDivideByZero)
}
}net/rpc
在我看来,
net/rpc
net/rpc
gob
net/rpc
net/rpc
net/rpc
context.WithTimeout
net/rpc
那么,为什么
net/rpc
net/rpc
net/rpc
net/rpc
要深入理解
net/rpc
服务端核心细节:
服务注册: 这是服务端最关键的一步。通过
rpc.Register(receiver interface{})rpc.RegisterName(name string, receiver interface{})rpc.Register(arith)
Arith
rpc.RegisterName("MyCalculator", arith)error
func (t *T) Method(args *ArgsType, reply *ReplyType) error
args
reply
error
网络监听:
net.Listen("tcp", ":port")连接处理:
listener.Accept()
rpc.ServeConn(conn)
net/rpc
ServeConn
ServeConn
net/rpc
rpc.HandleHTTP()
http.ListenAndServe
rpc.DialHTTP
gob
客户端核心细节:
建立连接:
rpc.Dial("tcp", "host:port")*rpc.Client
rpc.DialHTTP("tcp", "host:port")rpc.Dial
rpc.DialHTTP
方法调用:
client.Call("ServiceName.MethodName", args, &reply)"ServiceName.MethodName"
RegisterName
args
gob
&reply
gob
Call
client.Go("ServiceName.MethodName", args, &reply, ch)*rpc.Call
Call.Done
错误处理:
Call
error
error
理解这些细节,特别是方法签名和
gob
net/rpc
net/rpc
尽管
net/rpc
跨语言兼容性差: 这是最大的限制。由于默认使用
gob
net/rpc
net/rpc
缺乏高级特性:
net/rpc
ServeConn
net/rpc
error
协议限制: 默认使用TCP或HTTP/1.1。它不直接支持HTTP/2,这意味着你无法利用HTTP/2的多路复用、头部压缩等特性,这在高性能和低延迟场景下可能是一个劣势。
接口定义和版本管理:
net/rpc
安全性:
net/rpc
总的来说,
net/rpc
以上就是GolangRPC服务实现 net/rpc包案例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号