RPC 文档和命名空间¶
https://blueprints.launchpad.net/neutron/+spec/rpc-docs-and-namespaces
该蓝图旨在增强现有 oslo.messaging 的使用,使版本方案对开发人员来说更加清晰。 许多人表示当前代码难以理解,因此该规范旨在改进这一点。
问题描述¶
Neutron 使用 oslo.messaging 库在 Neutron 服务之间提供内部通信通道。 此通信通常通过 AMQP 进行,但这些细节大多被 oslo.messaging 隐藏,并且将来可以使用其他协议。
RPC API 在 Neutron 中定义为两部分:客户端和服务器端。
客户端¶
这是一个 rpc 客户端定义的示例
from oslo import messaging
from neutron.common import rpc as n_rpc
class ClientAPI(object):
"""Client side RPC interface definition.
API version history:
1.0 - Initial version
1.1 - Added my_remote_method_2
"""
def __init__(self, topic):
target = messaging.Target(topic=topic, version='1.0')
self.client = n_rpc.get_client(target)
def my_remote_method(self, context, arg1, arg2):
cctxt = self.client.prepare()
return cctxt.call(context, 'my_remote_method', arg1=arg1, arg2=arg2)
def my_remote_method_2(self, context, arg1):
cctxt = self.client.prepare(version='1.1')
return cctxt.call(context, 'my_remote_method_2', arg1=arg1)
此类定义了 rpc API 的客户端接口。 该接口有两个方法。 第一个方法存在于接口版本 1.0 中。 第二个方法是在版本 1.1 中添加的。 当调用较新的方法时,它指定远程端必须实现至少版本 1.1 才能处理此请求。
服务器端¶
rpc 接口的服务器端如下所示
from oslo import messaging
class ServerAPI(object):
target = messaging.Target(version='1.1')
def my_remote_method(self, context, arg1, arg2):
return 'foo'
def my_remote_method_2(self, context, arg1):
return 'bar'
此类实现了接口的服务器端。 定义的 messaging.Target() 表示该类当前实现接口版本 1.1。
版本控制¶
请注意,对 rpc 接口的更改必须始终以向后兼容的方式进行。 服务器端应始终能够处理较旧的客户端(在同一主要版本系列中,例如 1.X)。
可以升级主要版本号并删除仅用于向后兼容的代码。 有关如何执行此操作的更多信息,请参阅 https://wiki.openstack.org/wiki/RpcMajorVersionUpdates。
每个版本号流都与一个目标相关联。 在客户端,您设置一个目标来标识方法调用的目标。 在该目标上公开的每个方法都是 oslo.messaging 视角的单个 API,无论另一侧的实现细节如何。
不幸的是,在今天的 Neutron 代码中,它是不一致的,并且通常很难确定哪些被认为是相同版本流的一部分,哪些是独立的。
一个演示示例:DHCP Agent¶
定义了一个 RPC 接口,允许 Neutron 插件远程调用 DHCP agent 中的方法。 客户端在 neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.DhcpAgentNotifyApi 中定义。 此接口的服务器端在 DHCP agent 中运行,为 neutron.agent.dhcp_agent.DhcpAgent。
DHCP agent 包含一个客户端 API,neutron.agent.dhcp_agent.DhcpPluginAPI。 DHCP agent 使用此类调用 Neutron 服务器中的远程方法。 服务器端在 neutron.api.rpc.handlers.dhcp_rpc.DhcpRpcCallback 中定义。 版本控制从这里开始变得复杂。
版本号与 oslo.messaging.Target 相关联。 使用主题(以及该主题上的可选特定主机)指定消息的目标。 通过相同目标公开的所有内容必须被版本化为相同版本流的一部分。 DhcpRpcCallback API 在“q-plugin”主题上公开。 许多其他内容也在同一主题上公开。 例如,在使用 ml2 插件时,相关代码是
self.endpoints = [rpc.RpcCallbacks(self.notifier, self.type_manager),
securitygroups_rpc.SecurityGroupServerRpcCallback(),
dvr_rpc.DVRServerRpcCallback(),
dhcp_rpc.DhcpRpcCallback(),
agents_db.AgentExtRpcCallback(),
metadata_rpc.MetadataRpcCallback()]
根据当前代码的编写方式,通过“q-plugin”主题公开的 API 是以下类定义的 API 的联合
neutron.plugins.ml2.rpc.RpcCallbacks
neutron.plugins.ml2.drivers.type_tunnel.TunnelRpcCallbackMixin
neutron.api.rpc.handlers.securitygroups_rpc.SecurityGroupServerRpcCallback
neutron.api.rpc.handlers.dvr_rpc.DVRServerRpcCallback
neutron.api.rpc.handlers.dhcp_rpc.DhcpRpcCallback
neutron.db.agents_db.AgentExtRpcCallback
neutron.api.rpc.handlers.metadata_rpc.MetadataRpcCallback
这意味着对任何这些 API 的更改都意味着增加跨所有这些接口的版本号流。 但是,实现似乎表明它们被独立版本化,但并不一致。
提议的变更¶
该规范提出了两个更改。 这些更改的目的是帮助更清楚地了解版本号的范围。 这应该使这些版本号的处理更容易理解,并希望减少错误。
文档
对于 Neutron 中的每个客户端和服务器 rpc 接口定义,添加文档,清楚地说明接口的另一侧在代码中的位置。 此外,文档将列出包含在同一版本流中的任何其他类。
使用命名空间
在定义 oslo.messaging.Target 时,您可以添加一个命名空间。 这允许您在同一主题上公开多个接口,但仍然可以独立地对其进行版本化。
如果我们重新访问“q-plugin”主题和 ml2 驱动程序的示例,我们有几个接口在默认命名空间中的同一主题上公开。 将使用命名空间来分隔这些接口,以便可以独立地对每个接口进行版本化。
例如,公开的接口之一是 neutron.api.rpc.handlers.dhcp_rpc.DhcpRpcCallback。 该实现的开头如下所示
class DhcpRpcCallback(object):
"""DHCP agent RPC callback in plugin implementations."""
target = messaging.Target(version='1.1')
相反,现在将使用命名空间定义目标
class DhcpRpcCallback(object):
"""DHCP agent RPC callback in plugin implementations."""
target = messaging.Target(namespace='dhcp', version='1.1')
类似地,客户端也必须进行更新。 neutron.agent.dhcp_agent.DhcpPluginAPI.__init__ 包含以下代码
target = messaging.Target(topic=topic, version='1.0')
self.client = n_rpc.get_client(target)
这里的更改与服务器端所做的工作非常相似
target = messaging.Target(namespace='dhcp', topic=topic, version='1.0')
self.client = n_rpc.get_client(target)
现在,当客户端发出请求时,它变得更加明确。 服务器端将仅在标记有“dhcp”命名空间的端点上查找请求的方法,而不是所有包含的端点。
数据模型影响¶
无
REST API 影响¶
无
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
无
性能影响¶
无
IPv6 影响¶
无
其他部署者影响¶
从技术上讲,此更改不向后兼容。 现实是,只有当您期望任何形式的实时升级工作时,这才是重要的。 由于实际上并不期望实时升级工作,因此该规范建议接受这种理论上的不兼容性,因为目前这并不重要。
开发人员影响¶
开发人员的影响应该很小。 希望影响只是,当开发人员遇到需要更改这些接口之一的情况时,更清楚地了解受影响的代码的其他部分。 开发人员还必须了解任何未来添加的新接口的新命名空间用法。
社区影响¶
这里提出的内容只是文档和使用标准的 oslo.messaging API。
备选方案¶
不使用命名空间,您可以将每个接口公开到自己的主题上。 命名空间更方便,因为服务倾向于使用通用代码设置一个主题。 该通用代码需要进行修改才能支持映射到主题的任意端点列表。
实现¶
负责人¶
- 主要负责人
russellb
工作项¶
将代码库转换为适当使用命名空间。
将文档字符串添加到所有 rpc 客户端和服务器接口。
依赖项¶
drop-rpc-compat 蓝图:https://blueprints.launchpad.net/neutron/+spec/drop-rpc-compat
测试¶
现有的测试将验证这些更改没有导致回归。
Tempest 测试¶
无
功能测试¶
无
API 测试¶
无
文档影响¶
无
用户文档¶
无
开发人员文档¶
额外的开发人员文档是该蓝图的关键交付成果。
参考资料¶
oslo.messaging 文档:https://docs.openstack.org/developer/oslo.messaging/