当前位置: 首页 > news >正文

Go RPC

目录

文章目录

    • Go RPC
      • HTTP RPC
      • TCP RPC
      • JSON RPC

Go RPC

Go 标准包中已经提供了对 RPC 的支持,而且支持三个级别的 RPC:TCP、HTTP、JSONRPC。但 Go 的 RPC 包是独一无二的 RPC,它和传统的 RPC 系统不同,它只支持 Go 开发的服务器与客户端之间的交互,因为在内部,它们采用了 Gob 来编码。

Go RPC 的函数只有符合下面的条件才能被远程访问,不然会被忽略,详细的要求如下:

  • 函数必须是导出的 (首字母大写)
  • 必须有两个导出类型的参数,
  • 第一个参数是接收的参数,第二个参数是返回给客户端的参数,第二个参数必须是指针类型的
  • 函数还要有一个返回值 error

举个例子,正确的 RPC 函数格式如下:

func (t *T) MethodName(argType T1, replyType *T2) error

T、T1 和 T2 类型必须能被 encoding/gob 包编解码。

任何的 RPC 都需要通过网络来传递数据,Go RPC 可以利用 HTTP 和 TCP 来传递数据,利用 HTTP 的好处是可以直接复用 net/http 里面的一些函数。详细的例子请看下面的实现

HTTP RPC

http 的服务端代码实现如下:


package mainimport ("errors""fmt""net/http""net/rpc"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}type Arith intfunc (t *Arith) Multiply(args *Args, reply *int) error {*reply = args.A * args.Breturn nil
}func (t *Arith) Divide(args *Args, quo *Quotient) error {if args.B == 0 {return errors.New("divide by zero")}quo.Quo = args.A / args.Bquo.Rem = args.A % args.Breturn nil
}func main() {arith := new(Arith)rpc.Register(arith)rpc.HandleHTTP()err := http.ListenAndServe(":1234", nil)if err != nil {fmt.Println(err.Error())}
}

通过上面的例子可以看到,我们注册了一个 Arith 的 RPC 服务,然后通过 rpc.HandleHTTP 函数把该服务注册到了 HTTP 协议上,然后我们就可以利用 http 的方式来传递数据了。

请看下面的客户端代码:


package mainimport ("fmt""log""net/rpc""os"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}func main() {if len(os.Args) != 2 {fmt.Println("Usage: ", os.Args[0], "server")os.Exit(1)}serverAddress := os.Args[1]client, err := rpc.DialHTTP("tcp", serverAddress+":1234")if err != nil {log.Fatal("dialing:", err)}// Synchronous callargs := Args{17, 8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)var quot Quotienterr = client.Call("Arith.Divide", args, &quot)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)}

我们把上面的服务端和客户端的代码分别编译,然后先把服务端开启,然后开启客户端,输入代码,就会输出如下信息:


$ ./http_c localhost
Arith: 17*8=136
Arith: 17/8=2 remainder 1

通过上面的调用可以看到参数和返回值是我们定义的 struct 类型,在服务端我们把它们当做调用函数的参数的类型,在客户端作为 client.Call 的第 2,3 两个参数的类型。客户端最重要的就是这个 Call 函数,它有 3 个参数,第 1 个要调用的函数的名字,第 2 个是要传递的参数,第 3 个要返回的参数 (注意是指针类型),通过上面的代码例子我们可以发现,使用 Go 的 RPC 实现相当的简单,方便。

TCP RPC

上面我们实现了基于 HTTP 协议的 RPC,接下来我们要实现基于 TCP 协议的 RPC,服务端的实现代码如下所示:


package mainimport ("errors""fmt""net""net/rpc""os"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}type Arith intfunc (t *Arith) Multiply(args *Args, reply *int) error {*reply = args.A * args.Breturn nil
}func (t *Arith) Divide(args *Args, quo *Quotient) error {if args.B == 0 {return errors.New("divide by zero")}quo.Quo = args.A / args.Bquo.Rem = args.A % args.Breturn nil
}func main() {arith := new(Arith)rpc.Register(arith)tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")checkError(err)listener, err := net.ListenTCP("tcp", tcpAddr)checkError(err)for {conn, err := listener.Accept()if err != nil {continue}rpc.ServeConn(conn)}}func checkError(err error) {if err != nil {fmt.Println("Fatal error ", err.Error())os.Exit(1)}
}

上面这个代码和 http 的服务器相比,不同在于:在此处我们采用了 TCP 协议,然后需要自己控制连接,当有客户端连接上来后,我们需要把这个连接交给 rpc 来处理。

如果你留心了,你会发现这它是一个阻塞型的单用户的程序,如果想要实现多并发,那么可以使用 goroutine 来实现,我们前面在 socket 小节的时候已经介绍过如何处理 goroutine。
下面展现了 TCP 实现的 RPC 客户端:


package mainimport ("fmt""log""net/rpc""os"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}func main() {if len(os.Args) != 2 {fmt.Println("Usage: ", os.Args[0], "server:port")os.Exit(1)}service := os.Args[1]client, err := rpc.Dial("tcp", service)if err != nil {log.Fatal("dialing:", err)}// Synchronous callargs := Args{17, 8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)var quot Quotienterr = client.Call("Arith.Divide", args, &quot)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)}

这个客户端代码和 http 的客户端代码对比,唯一的区别一个是 DialHTTP,一个是 Dial (tcp),其他处理一模一样。

JSON RPC

JSON RPC 是数据编码采用了 JSON,而不是 gob 编码,其他和上面介绍的 RPC 概念一模一样,下面我们来演示一下,如何使用 Go 提供的 json-rpc 标准包,请看服务端代码的实现:


package mainimport ("errors""fmt""net""net/rpc""net/rpc/jsonrpc""os"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}type Arith intfunc (t *Arith) Multiply(args *Args, reply *int) error {*reply = args.A * args.Breturn nil
}func (t *Arith) Divide(args *Args, quo *Quotient) error {if args.B == 0 {return errors.New("divide by zero")}quo.Quo = args.A / args.Bquo.Rem = args.A % args.Breturn nil
}func main() {arith := new(Arith)rpc.Register(arith)tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")checkError(err)listener, err := net.ListenTCP("tcp", tcpAddr)checkError(err)for {conn, err := listener.Accept()if err != nil {continue}jsonrpc.ServeConn(conn)}}func checkError(err error) {if err != nil {fmt.Println("Fatal error ", err.Error())os.Exit(1)}
}

通过示例我们可以看出 json-rpc 是基于 TCP 协议实现的,目前它还不支持 HTTP 方式。

请看客户端的实现代码:


package mainimport ("fmt""log""net/rpc/jsonrpc""os"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}func main() {if len(os.Args) != 2 {fmt.Println("Usage: ", os.Args[0], "server:port")log.Fatal(1)}service := os.Args[1]client, err := jsonrpc.Dial("tcp", service)if err != nil {log.Fatal("dialing:", err)}// Synchronous callargs := Args{17, 8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)var quot Quotienterr = client.Call("Arith.Divide", args, &quot)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)}

相关文章:

Go RPC

目录 文章目录 Go RPCHTTP RPCTCP RPCJSON RPC Go RPC Go 标准包中已经提供了对 RPC 的支持,而且支持三个级别的 RPC:TCP、HTTP、JSONRPC。但 Go 的 RPC 包是独一无二的 RPC,它和传统的 RPC 系统不同,它只支持 Go 开发的服务器与…...

真正的智能不仅仅是一个技术问题

智能并不是单一的技术问题,而是一个包括技术、人类智慧、社会制度和文化等多个方面的综合体,常常涉及技术变革、系统演变、运行方式创新、组织适应。智能是指人类的思考、判断、决策和创造等高级认知能力,可以通过技术手段来实现增强和扩展。…...

【数据结构】复杂度包装泛型

目录 1.时间和空间复杂度 1.1时间复杂度 1.2空间复杂度 2.包装类 2.1基本数据类型和对应的包装类 2.2装箱和拆箱 //阿里巴巴面试题 3.泛型 3.1擦除机制 3.2泛型的上界 1.时间和空间复杂度 1.1时间复杂度 定义:一个算法所花费的时间与其语句的执行次数成…...

Ae:绘画面板

Ae菜单:窗口/绘画 Paint 快捷键:Ctrl 8 绘画工具(画笔工具、仿制图章工具及橡皮擦工具)仅能工作在图层面板上。在使用绘画工具之前,建议先在绘画 Paint面板中查看或进行相关设置。 说明: 如果要在绘画描边…...

常见的锁和zookeeper

zookeeper 本文由 简悦 SimpRead 转码, 原文地址 zhuanlan.zhihu.com 前言 只有光头才能变强。 文本已收录至我的 GitHub 仓库,欢迎 Star:https://github.com/ZhongFuCheng3y/3y 上次写了一篇 什么是消息队列?以后,本来…...

经验总结:(Redis NoSQL数据库快速入门)

一、Nosql概述 为什么使用Nosql 1、单机Mysql时代 90年代,一个网站的访问量一般不会太大,单个数据库完全够用。随着用户增多,网站出现以下问题 数据量增加到一定程度,单机数据库就放不下了数据的索引(B Tree),一个机…...

form表单与模板引擎

文章目录 一、form表单的基本使用1、什么是表单2、表单的组成部分3、 <form>标签的属性4、表单的同步提交及缺点&#xff08;1&#xff09; 什么是表单的同步提交&#xff08;2&#xff09; 表单同步提交的缺点&#xff08;3&#xff09; 如何解决表单同步提交的缺点 二、…...

医院检验信息管理系统源码(云LIS系统源码)JQuery、EasyUI

云LIS系统是一种医疗实验室信息管理系统&#xff0c;提供全面的实验室信息管理解决方案。它的主要功能包括样本管理、检测流程管理、报告管理、质量控制、数据分析和仪器管理等。 云LIS源码技术说明&#xff1a; 技术架构&#xff1a;Asp.NET CORE 3.1 MVC SQLserver Redis等…...

React 组件

文章目录 React 组件复合组件 React 组件 本节将讨论如何使用组件使得我们的应用更容易来管理。 接下来我们封装一个输出 “Hello World&#xff01;” 的组件&#xff0c;组件名为 HelloMessage&#xff1a; React 实例 <!DOCTYPE html> <html> <head> &…...

硕士学位论文的几种常见节奏

摘要: 本文描述硕士学位论文的几种目录结构, 特别针对机器学习方向. 1. 基础版 XX算法及其在YY中的应用 针对情况: 只有一篇小论文支撑. 第 1 章: 引言 ( > 5页) 1.1 背景及意义 (应用背景、研究意义, 2 页) 1.2 研究进展及趋势 (算法方面, 2 页) 1.3 论文结构 (1 页) 第 …...

找兄弟单词

描述 定义一个单词的“兄弟单词”为&#xff1a;交换该单词字母顺序&#xff08;注&#xff1a;可以交换任意次&#xff09;&#xff0c;而不添加、删除、修改原有的字母就能生成的单词。 兄弟单词要求和原来的单词不同。例如&#xff1a; ab 和 ba 是兄弟单词。 ab 和 ab 则不…...

python字典翻转教学

目录 第1关 创建大学英语四级单词字典 第2关 合并大学英语四六级词汇字典 第3关 查单词输出中文释义 第4关 删除字典中特定字母开头的单词 第5关 单词英汉记忆训练 第1关 创建大学英语四级单词字典 本关任务&#xff1a;编写一个能创建大学英语四级单词字典的小程序。 测…...

sentinel 随笔 3-降级处理

0. 像喝点东西&#xff0c;但不知道喝什么 先来段源码&#xff0c;看一下 我们在dashboard 录入的降级规则&#xff0c;都映射到哪些字段上 package com.alibaba.csp.sentinel.slots.block.degrade;public class DegradeRule extends AbstractRule {public DegradeRule(String…...

如何解决IP能ping通但无法上网的问题?

当我们在网络环境中遇到无法上网的问题时&#xff0c;可能会尝试使用ping命令来测试网络连接是否正常。如果ping测试成功&#xff0c;说明我们的IP地址能够和网络中其他设备进行通信&#xff0c;但是无法上网。这种情况下&#xff0c;我们需要采取一些措施来解决这个问题。本文…...

Autosar实践-CANTp

文章目录 前言一、CanTp是什么?二、Autosar配置三、诊断数据传输流程1.接收单帧失败,上层没有适当的buffer2.成功接收单帧3.成功发送单帧4.成功接收多帧5.成功发送多帧前言 CANTp模块作为提供数据拆包、组包、流控制传输的服务,在Autosar基础软件通信中起着至关重要的作用。…...

Redis简介

Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的键值对&#xff08;key-value&#xff09;数据库&#xff0c;支持网络、可基于内存亦可持久化。 Redis的数据结构包括列表&#xff08;List&#xff09;、集合&#xff08;Set&#xff09;、有序集合&#…...

报错问题修改

Vue 项目报错&#xff1a;‘$‘ is not defined ( no-undef ) 错误原因是不认识 $ 符&#xff0c;他是 JQuery 中得符号&#xff0c;引入了 JQuery 文件里的函数报错onclick is not defined问题(作用域问题) window.onload function (){ onload function (){ 第二种方法…...

专访惠众科技|元宇宙应用如何借助3DCAT实时云渲染实现流畅大并发呈现?

当前互联网流量红利已经逐渐消失&#xff0c;营销同质化愈发严重。在这样的背景下&#xff0c;催生了以为元宇宙 焦点的虚拟产业经济。元宇宙在各行各业中以不同形式快速萌生、成长&#xff0c;呈现出多元化的应用场景。尤其是众多品牌&#xff0c;将元宇宙视为品牌建设与营销新…...

加速开放计算产业化,OCTC五大原则瞄准需求痛点

回顾计算产业过去十余载的历程&#xff0c;开放计算始终是一个绕不开的核心焦点。 始于2011年Facebook发起的数据中心硬件开源项目--开放计算项目&#xff08;简称&#xff1a;OCP&#xff09;&#xff0c;开放计算犹如星星之火&#xff0c;不仅迅速形成燎原之势&#xff0c;更…...

【RabbitMQ】安装及六种模式

文章目录 安装rabbitmq镜像访问容器内部15672端口映射到外面的端口地址RabbitMQ六种模式Hello world模式Work queues模式Publish/Subscribe模式交换机fanout类型 Routing模式Topics模式RPC模式 rabbitmq&#xff1a;0->1的学习 学习文档&#xff1a;https://www.cnblogs.com…...

5步掌握多平台资源捕获:res-downloader全场景应用指南

5步掌握多平台资源捕获&#xff1a;res-downloader全场景应用指南 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 在数字化内…...

百度网盘下载加速终极指南:3分钟学会高速下载技巧

百度网盘下载加速终极指南&#xff1a;3分钟学会高速下载技巧 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘的龟速下载而烦恼吗&#xff1f;每次下载大文件都…...

收藏必备!小白程序员轻松入门大模型:从零排查RAG检索问题

本文针对RAG系统上线后常见的检索问题&#xff0c;提出了从源头到后处理的排查思路。文章首先强调文档入库的重要性&#xff0c;接着深入分析向量化和检索召回环节的常见错误&#xff0c;如模型不一致、表述差异等&#xff0c;并给出解决方案。最后&#xff0c;文章还关注排序和…...

SEO_中小企业必备的快速见效SEO优化解决办法

SEO: 中小企业必备的快速见效SEO优化解决办法 在当前竞争激烈的市场环境中&#xff0c;中小企业如何迅速提升在搜索引擎上的曝光率&#xff0c;成为每个企业家关注的焦点。搜索引擎优化&#xff08;SEO&#xff09;不仅能帮助企业吸引更多潜在客户&#xff0c;还能显著提高网站…...

ClusterFuzz终极内存泄漏检测指南:LSAN与UBSAN的完整配置教程

ClusterFuzz终极内存泄漏检测指南&#xff1a;LSAN与UBSAN的完整配置教程 【免费下载链接】clusterfuzz Scalable fuzzing infrastructure. 项目地址: https://gitcode.com/gh_mirrors/cl/clusterfuzz ClusterFuzz是一款强大的可扩展模糊测试基础设施&#xff0c;能够帮…...

弦音墨影模型部署排错大全:从“镜像启动失败”到“生成结果空洞”

弦音墨影模型部署排错大全&#xff1a;从“镜像启动失败”到“生成结果空洞” 你是不是也遇到过这种情况&#xff1f;好不容易在星图GPU平台上找到了弦音墨影这个强大的AI模型&#xff0c;满心欢喜地点击部署&#xff0c;结果却卡在了第一步——镜像拉取失败。或者&#xff0c…...

Emotion2Vec+ Large多语种支持实测:中文英文情感识别效果对比

Emotion2Vec Large多语种支持实测&#xff1a;中文英文情感识别效果对比 1. 引言 语音情感识别技术正在改变我们与机器交互的方式。想象一下&#xff0c;当你在电话客服中表达不满时&#xff0c;系统能立即识别你的愤怒情绪并转接高级客服&#xff1b;当你在语言学习中发音时…...

用FreeCAD模拟机械运动:以旋转把手为例,快速检查零件干涉与间隙

用FreeCAD模拟机械运动&#xff1a;以旋转把手为例&#xff0c;快速检查零件干涉与间隙 在机械设计领域&#xff0c;验证运动机构的可行性是产品开发过程中至关重要的一环。无论是简单的创客项目还是复杂的产品原型&#xff0c;设计师都需要确保各部件在运动过程中不会发生干涉…...

Spark依赖管理二选一:spark.yarn.archive和spark.yarn.jars到底怎么选?

Spark依赖管理深度抉择&#xff1a;spark.yarn.archive与spark.yarn.jars的架构师级决策指南 当你在凌晨三点被集群告警惊醒&#xff0c;发现数百个Spark作业因依赖加载超时而堆积&#xff0c;那一刻你会明白&#xff1a;依赖管理策略的选择绝非配置文件中的简单参数调整&#…...

30 秒学会!手机隐藏数码技巧,超实用!打工人、学生党直接封神

家人们谁懂啊&#xff01;每天手机不离手&#xff0c;结果 90% 的隐藏功能全在吃灰&#xff0c;简直亏到姥姥家&#xff01;别再只会打电话、刷短视频了&#xff0c;这些30 秒就能上手的数码冷知识&#xff0c;实用到跺脚&#xff0c;学会直接变身玩机大神&#xff0c;效率直接…...