Go 语言实现 RPC 调用
时间:2022-07-22
本文章向大家介绍Go 语言实现 RPC 调用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
友情提示:此篇文章大约需要阅读 6分钟37秒,不足之处请多指教,感谢你的阅读。
RPC
在分布式计算,远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。RPC 是一种服务器-客户端( Client/Server )模式,经典实现是一个通过 发送请求-接受回应 进行信息交互的系统。 wiki 维基百科
在这里引用一下维基百科对于 RPC 的解释, 可以针对与 HTTP 协议来比较分析,RPC 更适合于公司中大、中型项目分布式调用场景。
调用流程
- 客户端调用客户端stub(client stub)。这个调用是在本地,并将调用参数push到栈(stack)中。
- 客户端stub(client stub)将这些参数包装,并通过系统调用发送到服务端机器。打包的过程叫 marshalling。(常见方式:XML、JSON、二进制编码)
- 客户端本地操作系统发送信息至服务器。(可通过自定义TCP协议或HTTP传输)
- 服务器系统将信息传送至服务端stub(server stub)。
- 服务端stub(server stub)解析信息。该过程叫 unmarshalling。
- 服务端stub(server stub)调用程序,并通过类似的方式返回给客户端。
C/S 架构调用
RPC 与 HTTP 区别
RPC 调用实现的方式是和 HTTP 有异曲同工之处的,但是对于 RPC 与 HTTP 在 请求 / 响应中还是存在着差别的:
- HTTP 与 RPC 协议在实现上是不同的,大家都了解到 HTTP 原理就是 客户端请求服务端,服务端去响应并返回结果,但是 RPC 协议设计的时候采用的方式就是服务端给客户端提供 TCP 长连接服务,Client 端去调用 Server 提供的接口,实现特定的功能;
- RPC 可以同时提供同步调用及异步调用,而 HTTP 提供的方式就是同步调用,客户端会等待并接受服务端的请求处理的结果;
- RPC 服务设计可以提高代码编写过程中的解耦操作,提高代码的可移植性,每一个 服务可以设计成提供特定功能的小服务,客户端去调取远程的服务,而不用去关心远程是怎么实现的。
RPC 应用领域
- 大型网站的内部子系统设计;
- 为系统提供降级功能;
- 并发设计场景;
当然 RPC 也有缺点,每一个 RPC 服务都需要单独搭建,一旦服务出错或者更为严重的不提供支持,作为客户端的就会出现服务不可用,这对系统稳定性及可持续提供支持要求比较高,当然在设计过程中,这样也加大了对系统调试的难度,也就是说这种设计要求 RPC 服务的稳定性及正确性要求是比较大的。
实现代码
客户端实现
package main
import (
"demo/common"
"fmt"
"net/rpc"
)
func main() {
var args = common.Args{A: 32, B: 14}
var result = common.Result{}
var client, err = rpc.DialHTTP("tcp", "127.0.0.1:9090")
if err != nil {
fmt.Printf("connect rpc server failed, err:%v", err)
}
err = client.Call("MathService.Divide", args, &result)
if err != nil {
fmt.Printf("call math service failed, err:%v", err)
}
fmt.Printf("call RPC server success, result:%f", result.Value)
}
服务端实现
package main
import (
"demo/common"
"fmt"
"net/http"
"net/rpc"
)
func main() {
var ms = new(common.MathService)
// 注册 RPC 服务
err := rpc.Register(ms)
if err != nil {
fmt.Printf("rpc server register faild, err:%s", err)
}
// 将 RPC 服务绑定到 HTTP 服务中去
rpc.HandleHTTP()
fmt.Printf("server start ....")
err = http.ListenAndServe(":9090", nil)
if err != nil {
fmt.Printf("listen and server is failed, err:%vn", err)
}
fmt.Printf("server stop ....")
}
功能实现
package common
import "errors"
type Args struct {
A, B float32
}
type Result struct {
Value float32
}
type MathService struct {}
func (s *MathService) Add (args *Args, result *Result) error{
result.Value = args.A + args.B
return nil
}
func (s *MathService) Divide(args *Args, result *Result) error{
if args.B == 0 {
return errors.New("arge.B is 0")
}
result.Value = args.A / args.B
return nil
}
参考文章
- 贝叶斯过滤算法
- 強大的jQuery Chart组件-Highcharts
- vue2.0 配置 选项 属性 方法 事件 ——速查
- 亲密接触IIS 8和Web Deploy 3.0
- vue2.0 组件通信
- 在MongoDB中实现聚合函数
- 原生JS编写的照片墙效果实例演示特效
- 使用SuperWebSocket 构建实时 Web 应用
- Vue2.0的变化 ,组件模板,生命周期,循环,自定义键盘指令,过滤器
- 原生js编写的安全色拾色器
- 原生js写的贪吃蛇网页版游戏特效
- JS双月份显示联动效果,点击日期浮出消息提示
- JS兼容所有浏览器的一段加入收藏代码,设置为首页
- CentOS 6上的redis搭建实战记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php实现单笔转账到支付宝功能
- PHP发送邮件确认验证注册功能示例【修改别人邮件类】
- PHP实现微信退款功能
- 从零开始玩转PerfDogService---------初探篇
- php+laravel依赖注入知识点总结
- PHP获取当前系统时间的办法小结
- Laravel 中使用简单的方法跟踪用户是否在线(推荐)
- 浅析php怎么实现爬取数据原理
- 在 Laravel 中动态隐藏 API 字段的方法
- php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式
- Thinkphp 5.0实现微信企业付款到零钱
- 实现php删除链表中重复的结点
- YII分模块加载路由的实现办法
- ThinkPHP5.0框架实现切换数据库的方法分析
- php微信公众号开发之微信企业付款给个人