上篇文章提到过,OWT Server是模块化的结构,各个模块是可以独立部署的,模块之间的RPC调用都是基于消息队列RabbitMQ实现的。这篇文章分析一下OWT Server 基于RabbitMQ的RPC都有几种工作模式。
先简单复习一下RabbitMQ 的工作模式,详细浏览其官网介绍。
RabbitMQ有3个重要概念 交换机exchange、路由键routing_key、队列queue。
一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)。
一个生产者、多个消费者(竞争关系,只能消费一次),不需要设置交换机(使用默认的交换机)。
需要配置类型为 fanout 的交换机,把交换机和队列进行绑定,当发送消息到交换机上后,交换机会将消息发送到绑定的队列。
需要配置类型为 direct 的交换机,把交换机和自身的队列queue进行绑定,绑定的同时可以指定路由键 routing key,当发送消息到交换机后,交换机会根据 routing key 将消息发送到对应的队列。
例子中C1订阅error消息,C2订阅info error warning消息。
需要配置类型为 topic 的交换机,把交换机和自身的队列queue进行绑定,定时订阅带有通配符的路由键的消息。交换机收到消息后根据路由键分发消息到不同的队列。如果不同的队列订阅了相同的路由键,则都能收到相关的消息。
OWT Server使用node.js amqp
这个库来连接的RabbitMQ,这是一个古老的库,已经好久没更新了。并且它还不支持RabbitMQ集群,有能力可以使用其他更优秀的库替换。
OWT 把 amqp 库进行封装为amqp_client.js
文件,所有的模块都共用这个文件里面的函数。接下来分析一下这个文件。
rpcServer 主要提供RPC接口功能。
rpcServer 和 rpcClient 使用 direct 类型的交换机 owtRpc,对应RabbitMQ 路由工作模式。
先声明一个exchange,然后再声明一个固定名字的 queue 绑定到 direct 交换机 owtRpc 上。
例如:
Conference agent 在加入集群后,会声明一个名字格式为[email protected]
的queue,提供getNode()
等功能的RPC服务。
Conference node 启动后会声明一个名字类似 [email protected]_1
的queue,来提供实际的会议控制相关接口。
rpcClient 主要功能是对远程的模块进行RPC调用。
声明一个随机名字的队列queue,然后绑定到交换机 owtRpc 上,订阅消息用来接收RPC的结果。
调用的时候往交换机 owtRpc 上指定的路由键发 routing_key 送消息,这个路由键就是提供服务的模块绑定的路由键。
发送消息的同时把自身使用的随机名字的队列 queue 名字作为消息一起发送出去。rpcServer收到消息,即收到RPC调用,处理结束后把结果发到这个随机名字的queue上。这样就完成了一次RPC调用。
例如:
Conference agent 刚启动就会声明一个,随机名字 amq.gen-dfir4N5aySaqJVQnybz02Q
的queue,这个名字只作为远程调用的参数传递给RPC服务侧,供返回调用结果。
使用一个指定名字的 topic 类型的 交换机exchange,对应RabbitMQ的Topic模式。
声明一个随机名字的队列queue,可以订阅指定Topic的消息。
也可以发布指定Topic的消息。
例如:
Cluster manager 会声明一个topic类型的交换机owt-cluster.management
用来与其他的Cluster manager 通信。
monitoringTarget
和 faultMonitor
是一对,一个用来发送 模块退出消息,另一个接收模块退出消息。
使用 topic 类型的交换机 owtMonitoring
。用来发送Topic为'exit.'
前缀的消息。
例如:
Conference agent 在检测到其创建管理的进程异常退出后,会发送一个exit.abnormal
主题的消息出去,这里类似于广播。
使用 topic 类型的交换机 owtMonitoring
。订阅Topic为'exit.#'
的消息。
刚才说了Conference agent会广播一条exit.abnormal
消息通知大家 conference node-01
挂掉了,所有的模块收到这个消息后,如果发现自身与这个 conference node-01
有交互,比如video node检测到其所在的会议控制模块就是这个 conference node - 01
,那这个video node 自己就退出了,因为它活着已经没意义了。