目录​​​​​​​

什么是RPC

RPC 使用的步骤

服务端:

客户端:

RPC 相关函数

编码实现

server.go

client.go

RPC封装

目录结构

Client/main/design.go

client.go

Server/main/design.go

server.go

github


​​​​​​​

什么是RPC

RPC(Remote Procedure Call Protocol),是远程过程调用的缩写,通俗的说就是调用远处的一个函数。

RPC:远程进通信 —— 应用层协议(http协议同层)。底层使用 TCP 实现。

IPC: 进程间通信

像调用本地函数一样,去调用远程函数。

通过rpc协议,传递:函数名、函数参数。达到在本地,调用远端函数,得返回值到本地的目标。

为什么微服务使用 RPC:

1.  每个服务都被封装成 进程。彼此”独立“。

2.  进程和进程之间,可以使用不同的语言实现。

RPC 使用的步骤

服务端:

  1. 注册 rpc 服务对象。给对象绑定方法( 1. 定义类, 2. 绑定类方法 )

    rpc.RegisterName("服务名",回调对象)
    
  2. 创建监听器

    listener, err := net.Listen()
    
  3. 建立连接

    conn, err := listener.Accept()
    
  4. 将连接 绑定 rpc 服务。

    rpc.ServeConn(conn)

客户端:

  1. 用 rpc 连接服务器。

    conn, err := rpc.Dial()
    
  2. 调用远程函数。

    conn.Call("服务名.方法名", 传入参数, 传出参数

RPC 相关函数

  1. 注册 rpc 服务

    func (server *Server) RegisterName(name string, rcvr interface{}) error参1:服务名。字符串类型。参2:对应 rpc 对象。 该对象绑定方法要满足如下条件:1)方法必须是导出的 —— 包外可见。 首字母大写。2)方法必须有两个参数, 都是导出类型、內建类型。3)方法的第二个参数必须是 “指针” (传出参数)4)方法只有一个 error 接口类型的 返回值。
    举例:
    ​
    type World stuct {
    }
    func (this *World) HelloWorld (name string, resp *string) error {
    }
    rpc.RegisterName("服务名", new(World))
  2. 绑定 rpc 服务

    func (server *Server) ServeConn(conn io.ReadWriteCloser)conn: 成功建立好连接的 socket —— conn
  3. 调用远程函数:

    func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) errorserviceMethod: “服务名.方法名”args:传入参数。 方法需要的数据。reply:传出参数。定义 var 变量,&变量名  完成传参。

编码实现

server.go

package mainimport ("net/rpc""fmt""net"
)// 定义类对象
type World struct {
}// 绑定类方法
func (this *World) HelloWorld (name string, resp *string) error {*resp = name + " 你好!"return nil
}func main()  {// 1. 注册RPC服务, 绑定对象方法err := rpc.RegisterName("hello", new(World))if err != nil {fmt.Println("注册 rpc 服务失败!", err)return}// 2. 设置监听listener, err := net.Listen("tcp", "127.0.0.1:8800")if err != nil {fmt.Println("net.Listen err:", err)return}defer listener.Close()fmt.Println("开始监听 ...")// 3. 建立连接conn, err := listener.Accept()if err != nil {fmt.Println("Accept() err:", err)return}defer conn.Close()fmt.Println("链接成功...")// 4. 绑定服务rpc.ServeConn(conn)
}

client.go

package mainimport ("net/rpc""fmt"
)func main()  {// 1. 用 rpc 链接服务器 --Dial()// conn, err := rpc.Dial("tcp", "127.0.0.1:8800")conn, err := jsonrpc.Dial("tcp", "127.0.0.1:8800")if err != nil {fmt.Println("Dial err:", err)return}defer conn.Close()// 2. 调用远程函数var reply string      // 接受返回值 --- 传出参数err = conn.Call("hello.HelloWorld", "张三", &reply)if err != nil {fmt.Println("Call:", err)return}fmt.Println(reply)
}

RPC封装

目录结构

--RPC

------Client

----------main

--------------client.go

--------------design.go

------Server

----------main

--------------design.go

--------------server.go

Client/main/design.go

package mainimport ("net/rpc""net/rpc/jsonrpc"
)// 客户端的封装// 像调用本地函数一样,调用远程函数// 定义一个类
type Myclient struct {c *rpc.Client
}// 由于使用了c去调用Call ,因此需要初始化c
func InitClient(addr string) Myclient {conn, _ := jsonrpc.Dial("tcp", addr)return Myclient{c: conn}
}// 实现函数, 原型参照Interface来实现func (this *Myclient) HelloWorld(a string, b *string) error {// 参数1 参照Interface RegisterName 而来// a 传入参数  b 传出参数return this.c.Call("hello.HelloWorld", a, b)
}

client.go

package mainimport "fmt"// 结合 design.go 去测试
func main(){myClient := InitClient("127.0.0.1:8800")var resp stringerr := myClient.HelloWorld("李四", &resp)if err != nil{fmt.Println("HelloWorld err:", err)return}fmt.Println(resp, err)}

Server/main/design.go

package mainimport "net/rpc"// 要求 服务端在注册RPC对象时,能让编译器检测出 注册对象是否合法
// 避免运行时,发现注册对象不合法// 创建接口,在接口中定义方法原型
type MyInterface interface {HelloWorld(string, *string) error // 限定参数是两个
}// 封装一个函数实现
// 调用该方法时需要给i传参, 参数应该是实现了HelloWorld方法的类对象!
func RegisterService(i MyInterface) {rpc.RegisterName("hello", i)
}

server.go

package mainimport ("fmt""net""net/rpc/jsonrpc"
)// 定义类对象
type World struct {
}// 绑定类方法
func (this *World) HelloWorld(name string, resp *string) error {*resp = name + " 你好!"return nil // 返回值不等于nil出错,等于nil不出错// return errors.New("未知错误!") // 假如有错误,存在返回的值也不会显示
}func main() {// 封装后的注册RegisterService(new(World))// 2.设置监听listener, err := net.Listen("tcp", "127.0.0.1:8800")if err != nil {fmt.Println("new.Listen err", err)return}defer listener.Close()fmt.Println("开始监听 ...")// 3.建立连接conn, err := listener.Accept()if err != nil {fmt.Println("Accept() err:", err)return}defer conn.Close()fmt.Println("连接建立成功 ...")// 4.绑定服务// rpc.ServeConn(conn)jsonrpc.ServeConn(conn)
}

github

https://github.com/YTIANYE/PractiseGo/tree/master/Microservices/RPC

微服务02——RPC协议相关推荐

  1. go语言微服务之RPC协议

    目录 1 什么是RPC 2 RPC 使用的步骤 3 RPC相关函数 4 代码实现 4.1 服务端代码实现 4.2客户端代码实现 4.3程序实现结果 ​ 1 什么是RPC Remote Procedur ...

  2. 微服务之RPC(远程过程调用)的四种方式

    微服务思想 微服务思想-注册中心zookeeper 微服务: 架构设计采用分布式思想,当服务器发生故障时,可以实现自动化的故障迁移.无需人为干预. 注册中心实现原理: ZK工作原理说明 Zookeep ...

  3. 【微服务】RPC、gRPC 和 C/S 架构的基本实现(Golang)

    一.RPC 1.1 what & why need? 一言以蔽之,RPC 是分布式系统的基石. RPC(Remote Procedure Call),中文名为远程过程调用.它最初由 Xerox ...

  4. rpc协议微服务器,go微服务之rpc:hprose服务端

    Hprose 2.0 for Golang 支持多种底层网络协议绑定的服务器,比如:HTTP 服务器,Socket 服务器和 WebSocket 服务器.其中 HTTP 服务器支持在 HTTP.HTT ...

  5. 高性能微服务 Dubbo RPC Redis 分布式框架

    开发目标 兼容电脑.平板和手机的浏览器 支持分布式部署,支持Redis集群 友好的代码结构及注释,便于阅读及二次开发 提供Swagger API接口,方便团队协作和功能测试 Shiro认证授权,包含菜 ...

  6. Go使用grpc+http打造高性能微服务

    大家可以发现,Go越来越流行,其一是目前云计算领域基本是使用Go作为底层开发语言:其二是随着区块链的火爆,引申出了其背后很多开源项目,很多都是使用Go语言进行开发:其三就是在微服务方面,Go也展示很大 ...

  7. RPC协议之争和选型要点

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析RPC协议之争和选型问题.李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的同学可 ...

  8. 微服务可靠性设计--转

    原文地址:http://www.infoq.com/cn/articles/micro-service-reliability-design?utm_source=infoq&utm_medi ...

  9. 单体应用微服务改造实践

    [摘要] 本文介绍了如何采用一种持续迭代演进的方法将单体应用改造为微服务应用.重点介绍了如何通过自动测试服务和网关服务来构造持续迭代演进的基础设施.文末介绍了如何使用CSE更好的完成这个过程. 微服务 ...

最新文章

  1. Open×××整合OpenLDAP
  2. 专访Matt Klein关于在Lyft构建Envoy的问答
  3. 在/proc/devices中只能看见一个,请问是什么原因
  4. 第一周(1.8-1.14)
  5. Linux内核进程管理基本概念-进程、运行队列、等待队列、进程切换、进程调度
  6. Agiliq署名的免费python书籍
  7. HDU 1232:流问题(并检查集合)
  8. RPA技术干货 | RPA防锁屏运行技巧
  9. 第一章 QT Creator 简介
  10. 20200208(补):翻转游戏Ⅰ Ⅱ(leetcode)
  11. PHP漏洞全解(三)-客户端脚本植入
  12. 国外图片分享网站有哪些?20个国外免费、高清图片素材网站、图库全合集
  13. Golang - Structs 包的使用
  14. Python学习之cookies及session用法
  15. 跳槽穷半年,转行穷三年,死守会穷一辈子
  16. 《HTML 编辑器》
  17. 我们该如何高效的学习?
  18. List中remove()方法的陷阱以及终极的解决方法!
  19. 英国大不列颠百科全书_也许大不列颠即将来临
  20. RabbitMQ狂神说笔记(RabbitMQ B站狂神说笔记、KuangStudy、学相伴飞哥)

热门文章

  1. 远程抄表和能耗系统之间的关系
  2. 10天手敲一个SpringBoot网上商城项目(九)—— 确认订单、创建订单功能的实现及AOP
  3. 安卓开发手电筒应用(打开或关闭闪光灯)
  4. 内推 | 字节提前批快开始了。。。。
  5. 给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n1并且m1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如
  6. 数据分析师,要懂多少算法模型?
  7. 自己玩玩ios逆向工程
  8. 李进良:TD-LTE高潮完全逆转 4G前景捏一把汗
  9. 上海电力学院计算机毕设查重,上海电力学院全日制本科生毕业设计(论文)学术不端行为检测管理办法...
  10. Android应用开发-小巫CSDN博客客户端之嵌入有米广告,android音视频开发面试