前言
在分析L3的路由功能时,我们看到在L3Agent中有一种资源队列的应用,当对资源有申请和操作时会将信息存入到队列中,再根据规则进行提取;当执行失败后会重新将任务存入队列,等待下次提取重新创建。
queue
L3的调用
在l3agent初始化时
neutron.agent.l3.agent
from neutron.agent.common import resource_processing_queue as queue
class L3NATAgent():
def __init__():
......
self._queue = queue.ResourceProcessingQueue() #实例化
neutron.agent.common.resource_processing_queue
from six.moves import queue as Queue
class ResourceProcessingQueue(object):
def __init__(self):
self._queue = Queue.PriorityQueue()
def add(self, update):
update.tries -= 1
self._queue.put(update)
# add 增加到队列
def each_update_to_next_resource(self):
next_update = self._queue.get()
# 从队列取,然后执行这个消息
with ExclusiveResourceProcessor(next_update.id) as rp:
rp.queue_update(next_update)
for update in rp.updates():
yield (rp, update)
队列介绍
class PriorityQueue(Queue):
# Queue 会初始化一个队列__init__(self, maxsize=0)
# 本例中通过deque创建一个无大小限制的队列
def _init(self, maxsize):
self.queue = []
def _qsize(self, len=len):
return len(self.queue) #查询队列内消息个数
def _put(self, item, heappush=heapq.heappush):
heappush(self.queue, item)
# 将item事件推到队列中
# 注:本例中heappush为append到队列后,排序,排序的具体方法将以后介绍。暂未搞清:(
def _get(self, heappop=heapq.heappop):
return heappop(self.queue)
# 从队列取事件,能按照排序的方法取出位于堆最上方的值
l3对队列的操作
下面举几个例子
下面都是加入队列的操作,包括路由增删和同步,都会向对列传入;本例中根据update信息中优先级PRIORITY来排序。
neutron.agent.l3.agent
class L3NATAgent():
def router_deleted(self, context, router_id):
update = queue.ResourceUpdate(router_id,
PRIORITY_RPC,
action=DELETE_ROUTER)
self._queue.add(update)
def routers_updated(self, context, routers):
if routers:
if isinstance(routers[0], dict):
routers = [router['id'] for router in routers]
for id in routers:
update = queue.ResourceUpdate(
id, PRIORITY_RPC, action=ADD_UPDATE_ROUTER)
self._queue.add(update)
def _resync_router(self, router_update,
priority=PRIORITY_SYNC_ROUTERS_TASK):
if router_update.hit_retry_limit():
router_update.id, router_update.action)
if router_update.action != DELETE_ROUTER:
self._safe_router_removed(router_update.id)
return
router_update.timestamp = timeutils.utcnow()
router_update.priority = priority
router_update.resource = None # Force the agent to resync the router
self._queue.add(router_update)
提取:用popleft,从最左侧提取
之前文章写过启动l3-agent有进程不停执行_process_router_update去执行路由操作
def _process_router_update(self):
for rp, update in self._queue.each_update_to_next_resource():
总结
在OpenStack中,对路由进行操作时,首先将update的信息存入到队列queue中,然后通过其他进程不停对队列进行提取,提取的策略为根据信息的优先级来进行提取;提取后再进行操作;这样的好处有:
- 可以根据路由优先级执行;
- 将创建失败的信息重复加入到队列中;
后记
需要将队列排序的方法进一步分析:
heapq.py
def _siftup(heap, pos):
def _siftdown(heap, startpos, pos):