目录
一、Requestor
二、RpcCaller
三、Publish_Subscribe
四、Registry-Discovery
五、Client
在客户端的模块划分中,基于以上理解的功能,可以划分出这么几个模块
-
Protocol:应用层通信协议模块
-
Network:网络通信模块
-
Dispatcher:消息分发处理模块
-
Requestor:请求管理模块
-
RpcCaller:远端调用功能模块
-
Publish-Subscribe:发布订阅功能模块
-
Registry-Discovery:服务注册/发现/上线/下线功能模块
-
Client:基于以上模块整合而出的客户端模块
其中,NetWork是基于moduo库实现网络通讯的客户端,Protocol 与 Dispatcher 的逻辑都与服务端保持一致。
一、Requestor
Requestor模块存在的意义:针对客户端的每⼀条请求进行管理,以便于对请求对应的响应做出合适的操作。
在 Requestor 模块,有两个问题需要解决:
-
当存在多个客户端发送请求时,多线程下,针对多个请求进行响应可能会存在时序的问题(我们无法区分先来的消息与后来的消息),如果是这样,我们也没办法进行响应后保证⼀个线程发送⼀个请求后,收到的响应是针对自己这条请求的响应。
-
像Muduo库这种异步IO网络通信库,通常IO操作都是异步操作,即发送数据就是把数据放入发送缓冲区,但是什么时候会发送由底层的网络库来进行协调,并且也并不会提供recv接口(不知道什么时候发送就无法得知什么时候去接收),而是在连接触发可读事件后(epoll会检查已就绪的),IO读取数据完成后调用处理回调进行数据处理,因此也无法直接在发送请求后去等待该条请求的响应。
针对以上问题,需要创建出当前的请求管理模块来解决,它的思想是给每⼀个请求都设定⼀个请求ID
,服务端进行响应的时候标识响应针对的是哪个请求(也就是响应信息中会包含请求ID),因此客户端这边我们不管收到哪条请求的响应,将数据存储入⼀则hash_map中,以请求ID作为映射,并向外提供获取指定请求ID响应的阻塞接口,这样只要在发送请求的时候知道自己的请求、ID,那么就能获取到自己想要的响应。
基于这个思想,可以将每个请求进⼀步封装描述,添加⼊异步的future
控制,或者设置回调函数的方式,在不仅可以阻塞获取响应,也可以实现异步获取响应以及回调处理响应
二、RpcCaller
RpcCaller模块存在的意义:向用户提供进行rpc调用的模块。
Rpc服务调用模块,只需要向外提供几个rpc调用的接口,内部实现向服务端发送请求,等待获取结果即可,稍微麻烦⼀些的是Rpc调⽤我们需要提供多种不同方式的调⽤:
-
同步调用:发起调用后,等收到响应结果后返回
-
异步调用:发起调用后立即返回,在想获取结果的时候进行获取
-
回调调用:发起调用的同时设置结果的处理回调,收到响应后自动对结果进行回调处理
三、Publish_Subscribe
Publish-Subscribe模块存在意义:向用户提供发布订阅所需的接口,针对推送过来的消息进行处理。
在发布订阅中有两种角色,⼀个客户端可能是消息的发布者,也可能是消息的订阅者。
而且不管是哪个角色都是对主题进行操作,因此其中也包含了主题的相关操作,比如,要发布⼀条消息需要先创建主题。且⼀个订阅者可能会订阅多个主题,每个主题的消息可能都会有不同的处理方式,因此需要有订阅者主题回调的管理。
四、Registry-Discovery
在注册发现模块,同样要区分不同的客户端角色:注册者与发现者
首先来看注册者:
作为Rpc服务的提供者,需要向注册中心注册服务,因此需要实现向服务器注册服务的功能
然后来看发现者:
作为Rpc服务的调用者,需要先进行服务发现,也就是向服务器发送请求获取能够提供指定服务的主机地址,获取地址后需要管理起来留⽤,且作为发现者,需要关注注册中心发送过来的服务上线/下线消息,以及时对已经下线的服务和主机进行管理。
因为不论是注册者还是发现者,都需要向服务端发送请求,所以它们都要和Requestor
模块交互。
五、Client
-
RegistryClient
:服务注册功能模块与网络通信客户端结合 -
DiscoveryClient
:服务发现功能模块与网络通信客户端结合 -
RpcClient
:DiscoveryClient&RPC功能模块与网络通信客户端结合 -
TopicClient
:发布订阅功能模块与网络通信客户端结合