首页 > 其他分享 >go rpc

go rpc

时间:2022-08-26 14:34:05浏览次数:42  
标签:err RPC rpc HelloService go Hello

go rpc

RPC是远程过程调用的简称,是分布式系统中不同节点间流行的通信方式。在互联网时代,RPC已经和IPC一样成为一个不可或缺的基础构件。

image

  • RPC传输协议
  • 消息序列化与反序列化

下面是一个基于HTTP的 JSON的 RPC:
image

1.1 Go语言RPC

Go语言的标准库也提供了一个简单的RPC实现, 包的路径为net/rpc,也就是放在了net包目录下面。因此我们可以猜测该RPC包是建立在net包基础之上的

因此是之前着2中知识的集合:

  • Socket编程
  • 序列化(json/xml/...)

2.1 "Hello, World"

由上图可知一个rpc服务由2个部分组成:

  • server
  • client
    我们分别建2个项目

2.1.1 RPC Server

下面是HelloService, 提供了一个 Hello 方法

type HelloService struct {}

// Hello的逻辑 就是 将对方发送的消息前面添加一个Hello 然后返还给对方
// 由于我们是一个rpc服务, 因此参数上面还是有约束:
// 		第一个参数是请求
// 		第二个参数是响应
// 可以类比Http handler
func (p *HelloService) Hello(request string, reply *string) error {
	*reply = "hello:" + request
	return nil
}

如何把这个Hello方法, 变成一个RPC,直接供客户端调用喃?
Restful接口, 我们已经很熟悉了, 这也是一种RPC: JSON + HTTP
我们使用net/rpc包, 来实现一个rpc server:

func main() {
	// 把我们的对象注册成一个rpc的 receiver
	// 其中rpc.Register函数调用会将对象类型中所有满足RPC规则的对象方法注册为RPC函数,
	// 所有注册的方法会放在“HelloService”服务空间之下
	rpc.RegisterName("HelloService", new(HelloService))

	// 然后我们建立一个唯一的TCP链接,
	listener, err := net.Listen("tcp", ":1234")
	if err != nil {
		log.Fatal("ListenTCP error:", err)
	}

	// 通过rpc.ServeConn函数在该TCP链接上为对方提供RPC服务。
	// 没Accept一个请求,就创建一个goroutie进行处理
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Fatal("Accept error:", err)
		}

		// 前面都是tcp的知识, 到这个RPC就接管了
		// 因此 你可以认为 rpc 帮我们封装消息到函数调用的这个逻辑,
		// 提升了工作效率, 逻辑比较简洁,可以看看他代码
		go rpc.ServeConn(conn)
	}
}

2.1.2 RPC Client

客户端如何调用我们server的Hello函数喃?

func main() {
	// 首先是通过rpc.Dial拨号RPC服务, 建立连接
	client, err := rpc.Dial("tcp", "localhost:1234")
	if err != nil {
		log.Fatal("dialing:", err)
	}

	// 然后通过client.Call调用具体的RPC方法
	// 在调用client.Call时:
	// 		第一个参数是用点号链接的RPC服务名字和方法名字,
	// 		第二个参数是 请求参数
	//      第三个是请求响应, 必须是一个指针, 有底层rpc服务帮你赋值
	var reply string
	err = client.Call("HelloService.Hello", "hello", &reply)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(reply)
}

rpc服务最多的优点就是 我们可以像使用本地函数一样使用 远程服务上的函数, 因此有几个关键点:

  • 远程连接: 类似于我们的pkg
  • 函数名称: 要表用的函数名称
  • 函数参数: 这个需要符合RPC服务的调用签名, 及第一个参数是请求,第二个参数是响应
  • 函数返回: rpc函数的返回是 连接异常信息, 真正的业务Response不能作为返回值

2.1.3 测试

//启动服务端
go run rpc/server/main.go

//客户端请求服务端
$ go run rpc/client/main.go
hello:hello

一个基础的rpc服务就是这么简单

3.1 基于接口的RPC服务

// Call invokes the named function, waits for it to complete, and returns its error status.
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error {
	call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
	return call.Error
}

上面是client call 方法, 里面3个参数2个interface{}, 你再使用的时候 可能真不知道要传入什么, 这就好像你写了一个HTTP的服务, 没有接口文档, 容易调用错误

如何避免这种情况喃? 我们可以对客户端进行一次封装, 使用接口当我们的 文档, 明确参数类型

定义hello service的接口

package service

const HelloServiceName = "HelloService"

type HelloService interface {
	Hello(request string, reply *string) error
}

约束服务端:

// 通过接口约束HelloService服务
var _ service.HelloService = (*HelloService)(nil)

封装客户端, 让其满足HelloService接口约束

标签:err,RPC,rpc,HelloService,go,Hello
From: https://www.cnblogs.com/liwenchao1995/p/16627469.html

相关文章

  • Go语言 字符串切片转字符串
    []btye可以直接转换成string,但是如果有使用到split函数的需求,然后再str:=string([]string{}),go不支持这样的强转.参考博客:Golang字符切片转字符串不过go的......
  • 1. mongodb基础:cursor.forEach使用
    varxtdb_db=connect("ip:port/实例名").getSisterDB("xtdb");varback_db=connect("ip:port/实例名").getSisterDB("xtdb_del_back");xtdb_db.auth("username","pass......
  • Mongodb安装教程
    1.下载Mongodb安装包:地址:https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.2.21-signed.msi2.选择安装路径:  3.安装完之后找到对应的安装......
  • django2.x -- auth模块的authenticate方法一直返回None,认证不成功
    创建用户时是否使用的是create_user在账号注册的时候,要用objects.create_user()函数,create()是明文存储create_user()这个函数会将密码自动加密,密文存储,加密规则“pbkdf......
  • Go语言方法
    Go语言方法两种接收者Go语言方法有他的接收者,如下代码packagemainimport"fmt"typeAstruct{ namestring}func(aA)Name()string{ a.name="hi"+a.......
  • Go errors All In One
    GoerrorsAllInOnesh:gin:commandnotfoundzshgopath$echo$GOPATH$echo$PATH|grep$GOPATHhttps://github.com/codegangsta/gin/issues/114$co......
  • go-redis和redigo连接池的区别
    go-redis是自动管理,类似go/sql包的方式,在真正执行的时候从连接池取一个连接,执行完毕后放回去,对调用者透明。调用者如果手动关闭连接,连接不能被复用,表现上看就是redis服务器......
  • 1-2 django的app创建和说明+启动运行django+模板和静态文件+django的模板语法+请求和
    1.视频【1-6、1-7、1-8、1-9、1-10】https://www.bilibili.com/video/BV1S44y1K7Hd?p=6&spm_id_from=pageDriver 2.笔记 3.创建APP项目-app,用户管理【表结......
  • 【HDFS】一次Namenode的RPC延迟故障排查引发的深入思考
    一次Namenode的RPC延迟故障排查引发的深入思考前言正文问题排查初步定位临时恢复定位可疑进程问题分析问题脚本分析问题原因分析代码分析测试代码prometheus_clien......
  • Django ORM中常用字段和参数
    DjangoORM中常用字段和参数 一些说明:表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特......