Bootstrap

大画 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的方式类比了消息处理的过程,方便小伙伴的理解

下一篇,我们详细介绍→的具体流程,这是一个很有意思的过程。