Go语言RPC(模拟远程过程调用)

作者: adm 分类: go 发布时间: 2023-05-11

什么是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)
    }
}
 

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!