大画 Spark :: 网络(2)-上篇-通过网络收取消息的过程
回顾
上一篇,,对spark网络进行了初探,了解了client端与server端大概的构成,以及一个非常简单的交互模型。

重点
消息分为和两类
:client端发送,需要server端进行response返回,返回后在client端处理完成response,一去一回,类似于传输层的TCP协议
:相反,一去不返的方式,类似于传输层的UDP
server端对于request的response返回,使用的是callback调用的方式
client端对于收到response后,识别到底是对应的哪一个request,采用的是缓存一个map数据结构的方式,通过requestId找到相应的callback的方式
本篇主旨
对于上图,我们高度抽象成下图。本篇解读当服务端收到消息后
如何把消息传递到spark处理业务的核心组件
在这个过程中涉及到的Dispatcher、endpoint、endpointRef到底是什么
这些组件是如何相互配合完成工作的
处理和处理的区别
注意
读者可以用图当作架构说明文档,对照代码一起来看,这样效果最好

网络服务的基础:NettyRpcEnv
对于接收到的消息,打开spark核心业务处理的桥接通道就是的的方法

回忆NettyRpcEnv
我把原图做了一个镜像,网络世界放到了左侧,为了和上面的图可以合成到一起。
可以看到当我们需要通过client端访问外面的服务的时候,最终需要使用调用,发起的是的ask或者send(这个概念后面细说)
并且,上一篇我也提到了也是构成所有网络服务的基础,下文会细讲

NettyRpcEnv是消息处理的双工桥梁
是基础,但是充当桥梁的是它构建的其他组件,如,如

再细化一下,选取2个有代表性的方法,和

和外部网络图合并来理解一下

整体的层次
我们先来总结一个层次图,罗列起来比较能看得清层次感

Spark的逻辑处理世界的宏观结构
上图中引入和“Spark的逻辑处理世界”这个概念,到这里就基本上解藕了网络层,来到业务处理的部分
High level看逻辑处理过程
是的,你没看错,其实大的逻辑处理过程就是这么素颜。我很喜欢把复杂问题先简单化,然后再逐步深入细节,从而避免从入门到放弃,打造一个从入门→兴趣→钻研→成功的过程。

上图中,到是虚线,说明这个调用不是一个线性直接调用的过程,中间涉及到了线程池等复杂调用。
解释Dispatcher
稍稍有些经验的技术同学看到这个名词一定会想到,嗯,是的,我就希望这么记忆这个组件,它的大概功能也基本相当,就是一个前置控制器,拦截请求,匹配后续的操作。
解释RpcEndpoint (trait)
是,也就是java中我们经常说的接口。它有很多的实现类,比如

的实现类就是最终实现收到消息,处理这个消息的逻辑业务的部分
Dispatcher与RpcEndpoint的关系
根据上面的描述,可以知道就是根据message的类型,选择不同的的实现类来执行业务处理

Dispatcher的构建
上一章的图经过加工就是下图,也是通过构建出来的
构建关系

层次关系
通过下图看层次关系

深入一下Spark的逻辑处理世界
NettyRpcHandler→Dispatcher
通过2个方法联通起。前文说过,因为有单向和带反馈的,所以会对应2个receive方法和2个post...Message方法,如下图所示

NettyRpcHandler→Dispatcher→RpcEndpoint
因为最终会选择一个的实例来处理请求,所以会是这样的一种关系,注意,图中的虚线代表不是直接调用,而是“最终会调用到”的意思
,会在的方法处理,从而最终调用到实例的方法
,会在的方法处理,从而最终调用到实例的方法
注意图中的A、B、C
A:代表一个既可以接收又可以接收消息的实例
B:代表一个只可以接收消息的实例
C:代表一个只可以接收消息的实例
所以,通过下图也可以看出
如果一个中包含方法, 那么它只可以接收消息,
如果一个中包含方法, 那么它只可以接收消息
如果一个中包含上述2种方法, 那么它既可以接收消息也可以接收消息

解读RpcEndpoint
说到这里,根据上面的各类图,为了理解我们可以做一个技术的横向类比。
先看一个简单的SpringMVC的例子
如果访问/main/index的RESTful的接口,则是AClass的method1来进行处理,这个大家都很清楚。后续会用SpringMVC的例子做对比记忆,非常简单。
我们都知道被注解注释的class,在Spring启动的时候会进行扫描,对所有注释的方法进行管理,对每一个请求进行到的path的匹配,如下图
通过 找到AClass
通过找到method1,最终由method1来处理这个请求
以上的过程就是SpringMVC中的基本原理

什么是RpcEndpoint
先说结论,的实例就可以理解为SpringMVC中的注释的类。只不过在spark中不是注解,而是需要所有的class来实现的trait
定义RpcEndpoint
翻译过来是端点,顾名思义,一个请求可以触及到的最终的目的地。这个目的地也是处理请求的地方
类比RpcEndpoint和SpringMVC中处理请求的过程
左侧是SpringMVC的例子,右侧是spark中的,很像对吧。我们对比来说
spark中的消息请求分为1-4的4个部分
我用一个spark中的探活的 : 举例

引出RpcEndpointRef的概念
通过上面的图,我们可以知道,如果想访问上面例子中的的的话,起码需要3个必要条件,即上图中的
1: ip和port
3:的唯一识别名称:name
4:需要模式匹配的case class,也就是消息体类型
以上No.1和No.3的2个条件即可唯一识别出可以精准访问到,而具体访问到哪个case class的模式匹配处理,则需要上面的No.3在消息中动态的来指定
spark将上面的三个东东抽象成了一个结构,叫做,是一个抽象类,其实现类叫做。讲的有点干,我们画个图
RpcEndpointRef是RpcEndpoint的引用

通过RpcEndpointRef访问RpcEndpoint
所对应的会被另一台服务器所持有,通过send方法的调用来访问到本尊。至于下图中,在client端是如何获取到的,我们后面会用一个详细的案例来讲述

总结:RpcEndpointRef → RpcEndpoint

阶段性总结消息到RpcEndpoint的流程
以的消息为例,整个1-6的过程如下图所示,下一篇我们会把5再做细化的讲解

总结
本篇,我们从串通了从到最后的的大概流程,在这个过程中,我们弄清了以下几个概念
:前置控制器,用于选择消息到底发送到哪里
:处理消息的最终的端点的一个trait,里面含有处理消息的业务逻辑
的消息:调用方法
的消息:调用方法
:描述的基础信息,包括ip、port、和name,利用这三个基本属性可以找到在某一台服务器的,利用的ask或者send方法即可访问当相应的
我们用了SpringMVC的方式类比了消息处理的过程,方便小伙伴的理解
下一篇,我们详细介绍→的具体流程,这是一个很有意思的过程。