基本概念
在开始之前,先说几个概念:
- RpcEndPoint:RPC分布式的一个实例,他用于指定音讯的解决,比方接管音讯。
- RpcEndpointRef:RpcEndPoint的援用,也就是说,他指向的是服务端的RpcEndPoint,所以RpcEndpointRef会有服务端的RPC地址。
- Inbox:除了RpcEndPoint和RpcEndpointRef(下图太挤了这两个没画),还存储InboxMessage的音讯队列。
- EndpointData:包含了RpcEndpoint、NettyRpcEndpointRef及Inbox。
综上,EndpointData的构造是这样:
RpcEndPoint注册
RpcEndPoint实例化并通过Dispatcher注册的时候,就会实例化下面那些组件,并封装一个EndpointData。这里须要留神的是,Inbox组件在实例化的时候,会往messages这个音讯队列放入OnStart音讯。
当拿到EndpointData后,Dispatcher就会把这个Dispatcher扔到receivers队列中。
除此之前,还会存储EndpointData和名称的映射关系、RpcEndPoint和RpcEndPointRef的映射关系。
扔到receivers队列的EndpointData必定不是仅仅就扔在那边的,所以他会有一个线程池来进行解决,这个线程池里会有N个叫做MessageLoop的线程,会监听receivers队列,如果队列里有数据,就会把队列的数据拿进去。
这个数据就是EndpointData,对EndpointData进行解决的,是EndpointData外部的Inbox。
咱们下面说过,Inbox外面也保护了一个InboxMessage的音讯队列messages,Inbox就会把messages的音讯拿进去,一个个进行生产。这里的音讯都是有本人的类型,比方RpcMessage、OnStart、OnStop等等。
下面还提了,实例化Inbox的时候,messages会有一个OnStart,所以刚开始Inbox的messages队列就是有货色的,也就是说马上就会执行OnStart里对应的办法,也就是RpcEndpoint的onStart。
所以RpcEndpoint的生命周期的签名局部就是结构->onStart。
客户端申请发送
RpcEndpoint注册后,就能够承受申请了,咱们当初看看客户端怎么发送申请的。
客户端在发送音讯前,会把音讯封装成RequestMessage,而后再判断音讯发送的地址是否是以后地址,如果是以后地址,那流程和下面一样,把音讯放入inbox,而后存入receivers队列,期待线程生产。
如果是不一样,那就须要把音讯进行序列化,并封装成OutboxMessage,交给Outbox进行解决。
和Inbox相似,Outbox也有本人的OutboxMessage音讯队列,一直的从队列拿出messages,把音讯发送进来。
服务端接管到申请后,就会把音讯进行反序列化,而后扔到receivers队列。
总体流程
1、客户端产生一个音讯,而后序列化后放入Outbox的队列中。
2、客户端的一个线程把音讯取出来,依据服务端的地址,通过netty进行发送
3、服务端接管到音讯,把音讯进行反序列号,而后通过客户端给定的信息,找到EndpointData。
4、从EndpointData中取出Inbox,并把音讯放入到队列。
5、把EndpointData放入receivers队列。
6、线程池中的线程会从receivers队列取出EndpointData,而后调用Inbox的RpcEndPoint对音讯进行解决。
7、如果有返回值,就会通过RpcEndPointRef,把音讯序列号后,存入Outbox,服务端的线程就会把这个音讯返回给客户端。
8、客户端接管音讯后,反复第三步骤对音讯进行解决。
源码思维导图
RpcEnv的创立
NettyRpcEnv#stop
Dispatcher#postMessage
Dispatcher#stop
客户端发送申请
服务端解决申请