Go语言RPC(模拟远程过程调用)
什么是RPC框架?
RPC是指Remote Procedure Call远程过程调用
作用:
简化进程间通信的过程
RPC的作用
装通信过程,让远程的数据收发通信过程看起来就像本地的函数调用一样。
Go之RPC示例
特点:
使用channel代替Socket实现RPC过程
客户端和服务器再一个进程当中的两个goroutine中运行
实现方式:
定义客服端发送消息和封装消息的函数–>接收消息、放入消息通道、超时处理
定义服务端接收消息后的处理以及答复
示例代码:
package main import ( "errors" "fmt" "time" ) /* 实现客服端和服务器再一个进程 使用channel+两个goroutine实现 */ /* 模拟RPC客户端的请求和接收消息并封装 */ func RPCClient(ch chan string, req string) (string, error) { // 向服务器通道发送消息--->将接收到的信息发送到ch通道 ch <- req // 使用select选择器接收服务器的消息 select { case ack := <-ch: // 接收服务器返回的数据 return ack, nil case <-time.After(time.Second): // 超时返回空值并抛出异常信息 return "", errors.New("连接超时!") } } /* 模拟PRC服务器端接收客户端请求和回应 */ func RPCServer(ch chan string) { // 持续接收 for { // 接收客户端消息 data := <-ch // 打印收到的信息 fmt.Println("接收到的信息是:", data) // 将结果返回给客户端--->数据放回通道 ch <- "已收到消息!" } } /* main函数调用 */ func main() { // 创建通道--->客服端与服务器沟通通道 ch := make(chan string) // 并发执行服务器逻辑 go RPCServer(ch) // 模拟客户端请求数据 recv, err := RPCClient(ch, "HelloWorld!") if err != nil { // 打印错误信息 fmt.Println(err) }else { // 正常接收 fmt.Println("接收到的信息是", recv) } }
客户端请求和接收封装
/* 模拟RPC客户端的请求和接收消息并封装 */ func RPCClient(ch chan string, req string) (string, error) { // 向服务器通道发送消息--->将接收到的信息发送到ch通道 ch <- req // 使用select选择器接收服务器的消息 select { case ack := <-ch: // 接收服务器返回的数据 return ack, nil case <-time.After(3 * time.Second): // 超时返回空值并抛出异常信息 return "", errors.New("连接超时!") } }
注意:
方法入口模拟socket向服务器发送一个字符串信息。服务器接收后,结束阻塞执行下一行。
使用select开始做多路复用--->select语句中的case的通道操作是同时开启的。哪个case先返回则先执行哪个case里的语句
time.After使用了time包提供的函数After(),参数是 time包的一个常量,time.After返回一个通道,这个通道在指定时间后,通过通道返回当前时间。
主流程
创建一个无缓冲的字符串格式通道。将通道传给服务器的 RPCServer()函数,这个函数并发执行。使用RPCClient()函数通过ch对服务器发出RPC请求,同时接收服务器反馈数据或者等待超时
/* main函数调用 */ func main() { // 创建通道--->客服端与服务器沟通通道 ch := make(chan string) // 并发执行服务器逻辑 go RPCServer(ch) // 模拟客户端请求数据 recv, err := RPCClient(ch, "HelloWorld!") if err != nil { // 打印错误信息 fmt.Println(err) }else { // 正常接收 fmt.Println("接收到的信息是", recv) } }