当前位置:网站首页>Go语言 RPC通讯
Go语言 RPC通讯
2022-04-23 13:59:00 【面试被拒1万次】
RPC 远程调用过程,
调用其他服务的过程,是分布式系统中调用不同节点的常用通信方式
RPC 服务接口的分为三个部分
-
服务的名字
为了避免包名的冲突,我们可以在服务注册的时候加上包的路径,这个路径并不是go的执行路径,
rpc.RegisterName() 函数在注册,编译器会要求传入符合 服务接口的函数,const HelloServiceNmae = "/path/to/pkg.HelloService" // 注册的时候加上包的名字 type HelloServiceInterface = interface { hello( requst string,replace *string ) error // 函数的声明 }
-
服务要实现的详细方法列表
服务对应方法中的函数,hello函数
- 方法有两个可序列化参数,第二个参数是指针类型 ,返回一个error类型
Hello(request string, reply *string) error
- 方法必须是公开的,也就是大写开头的
-
注册该服务类型的函数
- 根据服务名字或者路径名字,注册服务到RPC
// 注册函数 func RegisterHelloService(src HelloServiceInterface) error { return rpc.RegisterName(HelloServiceNmae,src) }
- 在客户端调用的时候,也会根据规范调用RPC中注册的函数
func (p *HelloServiceClient) Hello(request string, repley *string) error { // 调用RPC的服务名字 和 方法,传入返回参数的地址 return p.Client.Call(service.HelloServiceName+".Hello", request, repley) }
demo
- 基于的hello接口 /RPC/service/HelloService.go
package service
const HelloServiceName = "HelloService"
type HelloService interface {
Hello(request string, reply *string) error
}
- 服务端 /RPC/server/main.go
package main
import (
"gowork/RPC/service"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type HelloService struct {
}
//约束 服务端
var _ service.HelloService = (*HelloService)(nil)
func (p *HelloService) Hello(request string, reply *string) error {
*reply = "hello -" + request
return nil
}
func main() {
// 将对象注册成一个rpc的 recevier
// 其中Rpc.Register 函数将对象类型中所有满足RPC规则的对象方法 注册为RPC函数
// 所有注册的函数都会放在 HelloService 这个空间里面
rpc.RegisterName(service.HelloServiceName, new(HelloService))
// 建立一个TCP 连接
lissenter, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatal("Tcp listen is error", err)
}
// 通过rpc.ServeConn函数在该TCP链接上为对方提供RPC服务。
// 每Accept一个请求,就创建一个goroutie进行处理
for {
connect, err := lissenter.Accept()
if err != nil {
log.Fatal(" Tcp Accept error")
}
// 为每个 TCP 为客户端提供rpc 服务
go rpc.ServeCodec(jsonrpc.NewServerCodec(connect))
}
}
- RPC 包是建立在net上的,在每个TCP链接过来之后提供服务的
- 在注册满足RPC规则的方法时候,这个RPC规则 主要有两点:
- 方法有两个可序列化参数,第二个参数是指针类型 ,返回一个error类型
Hello(request string, reply *string) error
- 方法必须是公开的,也就是大写开头的
- 注册成功的方法都放在,注册服务名空间里,在使用RPC调用方法的时候,使用服务名+方法的形式调用
- 客户端 /RPC/client/main.go
package main
import (
"fmt"
"gowork/RPC/service"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type HelloServiceClient struct {
*rpc.Client
}
// 约束客户端
// 新增加 HelloServiceClient 类型,但是 新增的类型必须满足 service.HelloService 接口类型
// 简单的说 HelloServiceClient 跟 HelloService 类型一致,两个接口中的函数一致 函数一致
var _ service.HelloService = (*HelloServiceClient)(nil)
//RPC 拨号服务,连接服务器
func DialHelloService(network, adress string) (*HelloServiceClient, error) {
connect, err := net.Dial(network, adress)
if err != nil {
log.Fatal("net dial is error")
}
// 采用json编码方式的客户端
c := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(connect))
return &HelloServiceClient{
Client: c}, nil
}
func (p *HelloServiceClient) Hello(request string, repley *string) error {
// 调用RPC的服务名字 和 方法,传入返回参数的地址
return p.Client.Call(service.HelloServiceName+".Hello", request, repley)
}
func main() {
client, err := DialHelloService("tcp", "localhost:1234")
if err != nil {
log.Fatal("dialting ")
}
var reply string
err = client.Hello("world", &reply)
if err != nil {
log.Fatal(" client hello error ", err)
}
fmt.Println("reply ", reply)
}
- 调用RPC的方法,首先先拨号连接,net.Dial
- 调用具体的RPC方法时候,使用RPC.Call() 传入服务名字,请求参数,返回参数
- 测试
启动服务器
cd /RPC/server/main.go
go run main.go
启动客户端:
cd /RPC/client/main.go
go run main.go
结果:
reply hello -world
跨语言的RPC 通信
golang 提供的编码方式gob,使用其他语言跟go通讯的时候,可以选用常用的编码方式
- MessagePack: 高效的二进制序列化格式。它允许在多种语言(如JSON)之间交换数据。但它更快更小
- JSON: 文本编码
- XML:文本编码
- Protobuf 二进制编码
RPC在go中的特色:
- 是RPC数据 打包时可以通过插件实现自定义的编码和解码;
- 建立在抽象的io.ReadWriteCloser接口之上的,我们可以将RPC 架设在不同的通讯协议之上
基于json编码重新实现RPC服务
server.go(服务端) :
go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
// 传入的参数是针对服务端的json 编解码器。
client.go(客户端) :
client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
基于该链接建立针 对客户端的json编解码器。
在获取到RPC调用对应的json数据后,我们可以通过直接向架 设了RPC服务的TCP服务器发送json数据模拟RPC方法调用:
echo -e ‘{“method”:“HelloService.Hello”,“params”:[“hello”],“id”:1}’ | nc localhost 1234
模拟客户端发送rpc 调用
- method 是调用的服务名字
- params 传入参数
- id 调用端维护的一个唯一的调用编号
返回结果:
{ “id” : 1 , “result” : “hello:hello” , “error” : null }
这篇读书笔记,读《GO语言高级编程》所得,
版权声明
本文为[面试被拒1万次]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_38023160/article/details/124326291
边栏推荐
- 编程旅行之函数
- Express②(路由)
- UML Unified Modeling Language
- Spark入门基本操作
- What is the difference between blue-green publishing, rolling publishing and gray publishing?
- try --finally
- freeCodeCamp----arithmetic_ Arranger exercise
- 联想产品经理林林:天津当地网络运营商网络故障 ZUI系统后台服务器暂时无法正常工作
- Problems encountered in the project (V) understanding of operating excel interface poi
- Leetcode? The first common node of two linked lists
猜你喜欢
freeCodeCamp----time_ Calculator exercise
蓝绿发布、滚动发布、灰度发布,有什么区别?
美联储数字货币最新进展
Question bank and answer analysis of the 2022 simulated examination of the latest eight members of Jiangxi construction (quality control)
商家案例 | 运动健康APP用户促活怎么做?做好这几点足矣
【项目】小帽外卖(八)
SQL learning window function
Quartus Prime硬件实验开发(DE2-115板)实验二功能可调综合计时器设计
【报名】TF54:工程师成长地图与卓越研发组织打造
Express②(路由)
随机推荐
SQL learning | complex query
Leetcode | 38 appearance array
cnpm的诡异bug
Es introduction learning notes
【项目】小帽外卖(八)
Tensorflow Download
Atcoder beginer contest 248c dice sum (generating function)
Handling of high usage of Oracle undo
[code analysis (5)] communication efficient learning of deep networks from decentralized data
剑南春把文字游戏玩明白了
Two ways to deal with conflicting data in MySQL and PG Libraries
Dolphin scheduler integrates Flink task pit records
记录一个奇怪的bug:缓存组件跳转之后出现组件复制
Lenovo Saver y9000x 2020
解决方案架构师的小锦囊 - 架构图的 5 种类型
【vmware】vmware tools 地址
Modify the Jupiter notebook style
Reading notes: Secure federated matrix factorization
联想产品经理林林:天津当地网络运营商网络故障 ZUI系统后台服务器暂时无法正常工作
The latest development of fed digital currency