net/rpc初识
RPC:远程调用过程协议,相关理论可以说是分布式和微服务的基础了,有需要的可以自行深入学习,简单来说RPC就是为了本机可以调用远程机器的子服务而产生的这么一种通信协议,基本上在后端开发中,RPC接口和HTTP接口的出现次数是最多的。
RPC通常和protobuf联系在一起,这么说其实不太准确,其实是grpc和protobuf联系在一起,因为protobuf序列化和反序列化的速度比json快,而且protobuf更加轻量级,更适合进行轻量的rpc通信(restful风格接口)
不管是轻量的GRPC框架,还是基于GRPC框架的微服务框架Go-Micro、Go-Kit等,它们在RPC这一块的实现肯定都是基于Go语言内建库:net/rpc上的,很多人上来就直接去撸框架,我其实并不认同这种学习方法,从语言的底层开始学起显然是一种更优的方法。
来看看Go内置的rpc包
服务1:求圆形面积
server
//结构体 作为服务的接收者
type MathUtil struct{
}
//向外暴露的服务 对应着Go的方法 方法:有接收者的函数
//net/rpc规定 服务的参数只能有两个 第二个参数必须为指针 返回类型必须为error
func (mu *MathUtil) CalculateCircleArea(req float32,resp *float32) error {
*resp=math.Pi * req * req
return nil
}
func main() {
//初始化指针类型数据
mathUtil:=new(MathUtil)
//调用 rpc注册服务
`err:=rpc.Register(mathutil)`
if err!=nil {
panic(err.Error())
return
}
//将服务注册到http协议上,调用者可以通过http的方式进行调用
rpc.HandleHTTP()
//进行特定端口的监听
listen,err:=net.Listen("tcp",":8087")
if err!=nil {
panic(err.Error())
}
http.Serve(listen,nil)
}
client
func main() {
//拨通HTTP
client, err := rpc.DialHTTP("tcp", "localhost:8087")
if err != nil {
panic(err.Error())
}
var req float32
req = 2
var resp *float32
//同步调用 Call的参数分别为服务名 注意这里的字符串是定死的 必须为 结构体.服务 和参数
err = client.Call("MathUtil.CalculateCircleArea", req, &resp)
if err != nil {
panic(err.Error())
}
fmt.Println(resp)
//异步调用
//syncCall := client.Go("MathUtil.CalculateCircleArea", req, &resp, nil)
//replayDone := <-syncCall.Done
//fmt.Println(replayDone)
//fmt.Println(*resp)
}