本篇作为MD-SAL核心内容的第三篇,我们将介绍RPC和Notification,并从进程内外的通信开始,着重介绍远程过程调用和发布-订阅机制,然后分析MD-SAL的通信交互过程。
图片来自网络
我们在编写单体程序的代码时,通常关注的是类和类之间关系的设计、类内的方法以及方法间的调用关系。在跨系统调用时,我们通常需要关注系统调用的接口,并根据接口文档进行编程,此时,涉及到跨系统、跨进程的调用。有关进程内外的通信分类大致如下:
单体程序代码通常是进程内通信,也就是本地过程调用,在同一CPU、同一内存空间进行。进程间通信最原始的莫过于Socket通信,但写起来相对于比较麻烦,人们希望能够“简单地”编程,后来基于“如何实现分布式计算的编程?”这一课题,在论文《Implementing Remote Procedure Calls》中给出了方案,即“调用远程机器上的程序就像在本地机器的地址空间中一样。隐藏分布式环境重要的部分:对参数和结果的编解码、消息传递以及保留过程调用的语义”,提出了RPC的解决方案。
间接通信的本质是“中介者”通信,是一种“间接”通信。它使得发送者和接收者不需要知道彼此的身份,并且不需要两者同时在线,一方不在线的情况下也可以通信,实现了空间上和时间上的解耦。间接通信比较流行的技术有:
l发布-订阅系统:“中介者”;
l消息队列系统:发送者发送消息到队列中,接收者从队列中提取消息。
RPC系统由User、User-stub、RPCRuntime、Server-stub和Server等5部分组成。其中,User、User-stub和RPCRuntime的实例在Caller machine上执行;Server、Server-stub和RPCRuntime实例在Callee machine上执行。简单调用的交互过程:
① User发起一个远程调用,则调用user-stub;
② user-stub负责封装方法和参数放置,并放置到一个或多个包中,然后请求RPCRuntime;
③ RPCRuntime将这些包可靠地传输给被调用者机器,同时,调用进程被挂起并等待结果包的返回;
④ Server的RPCRuntime将包传送给Server-stub;
⑤ Server-stub解包,并本地调用会调用Server中相对应的程序逻辑;
⑥ Server的逻辑执行完成,则将结果返回给Server-stub打包;
⑦ Server-stub将结果传给RPCRuntime;
⑧ Server的RPCRuntime将包将被传送回给User machine;
⑨ User machine进行解包,User得到返回结果。
我们通过发布订阅的一个开源实现Kafka来讲述发布-订阅机制。Kafka是一种高吞吐量的分布式发布订阅消息系统。如下图所示,producer发布消息,consumer从消息队列中获取消息,broker用来接收发送的消息并将这些消息路由至队列中。生产者将数据发布到他们选择的主题。 生产者负责选择分配给主题中哪个分区的记录。
而消息是由Topic(主题)的形式组织起来的,一个Topic可以有0、1或多个consumer订阅。对于每个Topic,又可分为多个Partition(分区)。每个分区都是一个有序的,不可变的序列。 如下所示:
Partition中的每个记录都分配了一个称为偏移的顺序ID号,它唯一地标识每个记录。如下所示:
RPC采用YANG语言建模,使用“rpc”语句建模。我们以OpenDaylight示例-Toaster为例介绍:rpc make-toast定义RPC操作的方法名、input用于定义RPC操作的输入参数、output用于定义RPC操作的输出参数。如下图所示:
1.生成代码
YANG文件定义好之后,我们执行命令:mvn clean install,可自动生成:
l ToasterService:接口文件,定义与yang数据模型定义的RPC方法;
l MakeToastInput:提供make-toast调用的输入参数。
l MakeToastInputBuilder:用于创建MakeToastInput实例的具体类。
2.实现接口
编写OpenDaylightToaster实现ToasterService接口,添加makeToast函数代码。
3. 注册RPC服务
使用blueprint注册RPC服务。
我们可以使用POSTMAN测试工具,或者编写应用APP调用makeToast函数,调用的请求为:
请求方法:POST
URL地址:http://localhost:8080/restconf/operations/toaster:make-toast
请求Body体:
从RPC的定义和代码编写不难看出,RPC的定义通过YANG语言来建模,RPC的访问可以通过RESTCONF协议进行,RPC的提供者通过blueprint来注册RPC服务。
在支持NETCONF协议的网络中,网络设备使用Notification消息向网络监控发送通知事件以说明网络设备的某种状态。OpenDaylight也采用了Notification消息通知,它被设计为一种发布/订阅模式。同样,我们以OpenDaylight示例Toaster来说明该机制。
在示例Toaster中,烤面包机不仅能烤面包,还能在没有面包的情况下,发送一个toasterOutOfBread通知,告知消费者现已无面包可烤。我们在YANG文件中定义这个通知,如下图所示:
1.生成代码
YANG文件定义好之后,我们执行命令:mvn clean install,可自动生成:
l ToasterOutOfBread:为toasterOutOfBread通知定义DTO接口。
l ToasterOutOfBreadBuild:用于创建ToasterOutOfBread实例的具体类。
l ToasterListener:实现烤面包机通知消费者的接口,定义每种通知类型的接收方法。
2.生产者实现通知
3.生产者实现配置
OpenDaylightToaster需要访问MD-SAL的NotificationPublishService才能发送通知。 我们需要在blueprint文件中注入OpenDaylightToaster:
4.消息者实现
我们来看下如何从控制器中以编程方式访问ToasterService,实现消费者KitchenService。示例中采用了“硬编码”的方式。如下所示:
接下来,我们修改KitchenServiceImpl以实现ToasterListener接口和通知方法。
KitchenServiceImpl需要在MD-SAL的NotificationPublishService中注册才能接收通知。 我们需要配置blueprint文件:
这样就可以OpenDaylightToaster在发生OutOfBread事件时发送通知。
Notification采用的是发布订阅机制,本例中生产者为OpenDaylightToaster,消费者为KitchenServiceImpl,中间代理为MD-SAL,具体为YANG和NotificationPublishService。如下图所示:
ToasterService接口通过YANG模型构建自动生成,OpenDaylightToaster是该接口的一个具体实现,通过blueprint实现关系的绑定。KitchenService理应采用YANG模型构建,但示例中采用的是硬编码的形式,在KitchenServiceImpl中直接声明ToasterService对象,如图中的①和①ɑ所示。无论是生产者还是消费者,都需要NotificationPublishService来进行消息的发布和订阅。
文章写到这里,就将YANG、DataStore、RPC和Notification这3个在MD-SAL中非常重要的点讲述完了,在支持NETCONF协议配置的网络,还涉及到需要将网络设备的Yang文件mount到控制器以实现基于NETCONF的控制。下一篇我们将MD-SAL的各个点串联起来,形成一条线。
全部0条评论
快来发表一下你的评论吧 !