【golang】RPC服务框架

本文参照geektutu的geerpc实现,总结一下其实现的思想。

通信过程

在geerpc中,通信双方定义了一套规则,客户端先向服务端发送json串,json串主要用于告知服务端两件事:1、接下来的请求是rpc请求。2、使用什么方式编解码二进制数据。

服务端接受到json串后,根据客户端传来的codeType创建编解码器。然后循环接受、处理、响应数据。

geerpc将method,seq等数据抽象为head;args,reply等数据抽象为body。

image

通信模型

geekrpc的网络服务采取了connection-peer-goroutine的模式,编程简单易用。

服务注册

Q&A

问题一:如何保证并发请求数据之间不会串联?

1、由于server端每个connection都有独立的goroutine处理,因此不同连接之间的请求数据是独立的,并发请求之间不会有误。

2、对于单个connection,客户端在发送json串后,可能会并发的请求n个rpc,如果不加控制,服务端很容易读取完rpc a的head后,立刻读取到了rpc b的body。因此客户端必须保证每个rpc请求的原子性。geerpc中使用mutex解决这一问题。

3、服务端也会向客户端写回数据,也必须保证写回操作(head和body)是原子的。则server的写回方法也要加锁。

ps: 服务端程序轮询地读取head,body,然后执行具体的rpc业务逻辑,然后将结果写回。其中执行具体rpc逻辑这一过程应该是并发的,否则将必须等待rpc处理结束后,才能继续读取下一个请求数据。

这里必须注意,虽然handle rpc是并发的,但是必须保证write response是串行的。

问题二:客户端如何知道服务端返回的数据属于哪个rpc调用?

1、在geerpc中,为了提高并发性能,做了读写分离的处理(写数据和读数据在两个goroutine中),不会因为写之后的读而阻塞。

2、在读的goroutine中,为了能将响应匹配到正确的rpc请求,在head中seq字段发挥了作用。它在每个rpc请求后自增1,一次rpc的请求和响应数据中的seq都是一致的,且rpc之间的seq不同。客户端通过seq在map中找到匹配的rpc请求数据即可。

posted @ 2022-09-11 13:52  moon_orange  阅读(239)  评论(1编辑  收藏  举报