rpc 就是  远程过程调用    指的是调用远端服务器上的程序的方法整个过程。

rpc 理论

RPC技术在架构设计上有四部分组成,分别是:客户端、客户端存根、服务端、服务端存根。

客户端:服务调用发起方 又叫做  服务消费者

服务器: server上运行的可以被客户端调用的方法

客户端存根:存放server端的地址和端口消息 。  将客户端消息打包转换成网络消息 发送给服务端 。 接受服务端的数据包 该程序运行在客户端。

服务端存根:存放client 网络数据 解析数据 调用本地对应的方法运行,将产生的结果回给客户端  该程序运行在 服务端。

go语言自带的rpc 框架的使用

1 服务定义及暴露

在编程实现过程中,服务器端需要注册结构体对象,然后通过对象所属的方法暴露给调用者,从而提供服务,该方法称之为输出方法,此输出方法可以被远程调用。

当然,在定义输出方法时,能够被远程调用的方法需要遵循一定的规则。我们通过代码进行讲解:

func (t *T) MethodName(request T1,response *T2) error

上述代码是go语言官方给出的对外暴露的服务方法的定义标准,其中包含了主要的几条规则,分别是:

  • 1、对外暴露的方法有且只能有两个参数,这个两个参数只能是输出类型或内建类型,两种类型中的一种。
  • 2、方法的第二个参数必须是指针类型。
  • 3、方法的返回类型为error。
  • 4、方法的类型是可输出的。
  • 5、方法本身也是可输出的。

我们举例说明:假设目前我们有一个需求,给出一个float类型变量,作为圆形的半径,要求通过RPC调用,返回对应的圆形面积。具体的编程实现思路如下:

type MathUtil struct{
}
//该方法向外暴露:提供计算圆形面积的服务
func (mu *MathUtil) CalculateCircleArea(req float32, resp *float32) error {
*resp = math.Pi * req * req //圆形的面积 s = π * r * r
return nil //返回类型
}

在上述的案例中,我们可以看到:

  • 1、Calculate方法是服务对象MathUtil向外提供的服务方法,该方法用于接收传入的圆形半径数据,计算圆形面积并返回。
  • 2、第一个参数req代表的是调用者(client)传递提供的参数。
  • 3、第二个参数resp代表要返回给调用者的计算结果,必须是指针类型。
  • 4、正常情况下,方法的返回值为是error,为nil。如果遇到异常或特殊情况,则error将作为一个字符串返回给调用者,此时,resp参数就不会再返回给调用者。

至此为止,已经实现了服务端的功能定义,接下来就是让服务代码生效,需要将服务进行注册,并启动请求处理。

2 注册服务及监听请求

net/rpc包为我们提供了注册服务和处理请求的一系列方法,结合本案例实现注册及处理逻辑,如下所示:

//1、初始化指针数据类型
mathUtil := new(MathUtil) //初始化指针数据类型 //2、调用net/rpc包的功能将服务对象进行注册
err := rpc.Register(mathUtil)
if err != nil {
panic(err.Error())
} //3、通过该函数把mathUtil中提供的服务注册到HTTP协议上,方便调用者可以利用http的方式进行数据传递
rpc.HandleHTTP() //4、在特定的端口进行监听
listen, err := net.Listen("tcp", ":8081")
if err != nil {
panic(err.Error())
}
go http.Serve(listen, nil)

经过服务注册和监听处理,RPC调用过程中的服务端实现就已经完成了。接下来需要实现的是客户端请求代码的实现。

3 客户端调用

在服务端是通过Http的端口监听方式等待连接的,因此在客户端就需要通过http连接,首先与服务端实现连接。

  • 客户端连接服务端

    client, err := rpc.DialHTTP("tcp", "localhost:8081")
    if err != nil {
    panic(err.Error())
    }
  • 远端方法调用 客户端成功连接服务端以后,就可以通过方法调用调用服务端的方法,具体调用方法如下:

    var req float32 //请求值
    req = 3 var resp *float32 //返回值
    err = client.Call("MathUtil.CalculateCircleArea", req, &resp)
    if err != nil {
    panic(err.Error())
    }
    fmt.Println(*resp)

    上述的调用方法核心在于client.Call方法的调用,该方法有三个参数,

  • 第一个参数表示要调用的远端服务的方法名,第二个参数是调用时要传入的参数,第三个参数是调用要接收的返回值。 上述的Call方法调用实现的方式是同步的调用,除此之外,还有一种异步的方式可以实现调用。异步调用代码实现如下:

  • var respSync *float32
    //异步的调用方式
    syncCall := client.Go("MathUtil.CalculateCircleArea", req, &respSync, nil)
    replayDone := <-syncCall.Done
    fmt.Println(replayDone)
    fmt.Println(*respSync)

4 多参数的请求调用参数传递

上述内容演示了单个参数下的RPC调用,对于多参数下的请求该如何实现。我们通过另外一个案例进行演示。

假设现在需要实现另外一个需求:通过RPC调用实现计算两个数字相加功能并返回计算结果。此时,就需要传递两个参数,具体实现如下:

将参数定义在一个新的结构体中,存放在param包中:

type AddParma struct {
Args1 float32 //第一个参数
Args2 float32 //第二个参数
}

在server.go文件中,实现两数相加的功能,并实现服务注册的逻辑:

func (mu *MathUtil) Add(param param.AddParma, resp *float32) error {
*resp = param.Args1 + param.Args2 //实现两数相加的功能
return nil
}
mathUtil := new(MathUtil) err := rpc.RegisterName("MathUtil", mathUtil)//多参数的调用 设置方法就在这里调整的 对比下上面的 单个参数的注册区别
if err != nil {
panic(err.Error())
} rpc.HandleHTTP() listen, err := net.Listen("tcp", ":8082")
http.Serve(listen, nil)

在本案例中,我们通过新的注册方法rpc.RegisterName 实现了服务的注册和调用。

至此,我们已经完成了net/rpc包的最基础的使用。

https://github.com/rubyhan1314/Golang-100-Days/tree/master/Day80(RPC%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E6%9C%BA%E5%88%B6)/code

上面的连接对应三个例子 代码对应三个  一个是单个 参数  一个是多个参数  一个就是prob 封装的参数 环境安装啃爹 prob  go语言到环境到 protobuf构建有点麻烦



go语言rpc学习的更多相关文章

  1. C语言课程学习的总结

    C语言课程学习的总结 学习C程序这门课一年了,这是我们学的第一门专业课.在大学里,C语言不但是计算机专业的必修课程而且也是非计算机专业学习计算机基础的一门必修课程.所以作为我这个计算机专业的学生来说当 ...

  2. RPC学习--C#使用Thrift简介,C#客户端和Java服务端相互交互

    本文主要介绍两部分内容: C#中使用Thrift简介 用Java创建一个服务端,用C#创建一个客户端通过thrift与其交互. 用纯C#实现Client和Server C#服务端,Java客户端 其中 ...

  3. [转]C语言指针学习经验总结浅谈

    指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...

  4. C语言(函数)学习之strstr strcasestr

    C语言(函数)学习之[strstr]&[strcasestr]一.strstr函数使用[1]函数原型char*strstr(constchar*haystack,constchar*needl ...

  5. 【Go语言】学习资料

    这段时间一直在看Go语言,6月3日Apple发布了swift发现里面竟然也有许多Go语言的影子,截至现在每天都在感觉到Go语言的强大.确实值得一学 今天在这里给园友们推荐一些Go语言的学习资料 网站 ...

  6. 远离go path,弃用go get,使用go mod 进行go语言的学习

    标题说的是go语言的学习,因为我也没做过开发 文章要解决的仅仅是一个问题 当你使用go get 无论如何get不到所需的包的问题 第一步就是下载goland 新手极其推荐goland,因为直接使用gl ...

  7. Dart语言快速学习上手(新手上路)

    Dart语言快速学习上手(新手上路) // 声明返回值 int add(int a, int b) { return a + b; } // 不声明返回值 add2(int a, int b) { r ...

  8. D02-R语言基础学习

    R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...

  9. D01-R语言基础学习

    R语言基础学习——D01 20190410内容纲要: 1.R的下载与安装 2.R包的安装与使用方法 (1)查看已安装的包 (2)查看是否安装过包 (3)安装包 (4)更新包 3.结果的重用 4.R处理 ...

随机推荐

  1. 关于git中的merge和rebase

    变基-git官网说明 变基 改变提交的基于分支 和merge不同 合并显示合并记录 变基合并更新后一起提交 不显示合并记录 变基 合并的结果是一致的

  2. Liunx运维(六)-文件备份与压缩命令

    文档目录: 一.tar:打包备份 二.gzip:压缩或解压文件 三.zip:打包和压缩文件 四.unzip:解压zip文件 五.scp:远程文件复制 六.rsync:文件同步工具 ---------- ...

  3. CentOS 8 安装Nginx

    安装命令: dnf install nginx -y 这就安装完成了 ,对你没看错一个命令就已经把nginx安装好了,不信你通过 nginx -V 命令查看. 常用操作: 1.nginx配置文件目录 ...

  4. 为了搞清楚类加载,竟然手撸JVM!

    作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...

  5. ESXi 中重新启动管理代理

    使用直接控制台用户界面 (DCUI)重启管理代理: 连接到您的 ESXi 主机的控制台. 按 F2 自定义系统. 以 root 身份登录. 使用上下箭头导航至故障排除选项>重新启动管理代理. 按 ...

  6. vue-element Form表单验证(表单验证没错却一直提示错误)

    在使用element-UI 的表单时,发生一个验证错误,例如已输入值但求验证纠错:       代码如下所示: <el-form :model="correction" :i ...

  7. java数组之binarySearch查找

    /** * 1.如果找到目标对象则返回<code>[公式:-插入点-1]</code> * 插入点:第一个大与查找对象的元素在数组中的位置,如果数组中的所有元素都小于要查找的对 ...

  8. 大数据量查询容易OOM?试试MySQL流式查询

    一.前言 程序访问 MySQL 数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM). 其实在 MySQL 数据库中提供了流式查询,允许把符 ...

  9. Maven的安装跟配置(最全)

    一.去官网下载maven 官网地址: https://maven.apache.org/ 点击下载apache-maven-3.6.3-bin.zip 下载完成后解压即可. 二.配置环境变量 在我们的 ...

  10. Liunx运维(十二)-Liunx系统常用内置命令

    文档目录: 一.Liunx内置命令概述 二.LIunx常用内置命令实例 1.help查看内置命令帮助2.查看内置命令使用方法3.":" 占位符4. "." 与s ...