您的位置:首页 > 其它

6.8.2 qmgr_transport_select函数: 选择QMGR_TRANSPORT 与round borin策略

2016-04-07 15:28 423 查看
/qmgr/qmgr_transport.c/qmgr_transport_select函数使用roundborin策略选择MDA进行发信。

/qmgr/qmgr_transport.c
268 /* qmgr_transport_select - selecttransport for allocation */
269
270 QMGR_TRANSPORT*qmgr_transport_select(void)
271 {
272    QMGR_TRANSPORT *xport;
273    QMGR_QUEUE *queue;
274    int     need;
275
276    /*
277     * If we find a suitable transport, rotate the list of transports to
278     * effectuate round-robin selection. See similar selection code in
279     * qmgr_peer_select().
280     *
281     * This function is called repeatedly until all transports have maxed out
282     * the number of pending delivery agent connections, until all delivery
283     * agent concurrency windows are maxed out, or until we run out of"todo"
284     * queue entries.
285     */
286 #define MIN5af51743e4eef(x, y) ((x)< (y) ? (x) : (y))
287
288    for (xport = qmgr_transport_list.next; xport; xport =xport->peers.next) {
289        if ((xport->flags & QMGR_TRANSPORT_STAT_DEAD) != 0
290             || xport->pending >=QMGR_TRANSPORT_MAX_PEND)
291             continue;
292        need = xport->pending + 1;
293        for (queue = xport->queue_list.next; queue; queue =queue->peers.next) {
294             if (QMGR_QUEUE_READY(queue) == 0)
295                 continue;
296             if ((need -=MIN5af51743e4eef(queue->window - queue->busy_refcount,
297                                          queue->todo_refcount)) <= 0) {
298                QMGR_LIST_ROTATE(qmgr_transport_list, xport, peers);
299                if (msg_verbose)
300                    msg_info("qmgr_transport_select: %s", xport->name);
301                 return (xport);
302             }
303        }
304    }
305    return (0);
306 }


先来回顾一下QMGR_QUEUE结构体的三个字段:

window:即参数initial_destination_concurrency,表示MDA默认并发发信量,随运行状况变化。

todo_refcount和busy_refcount记录QMGR_QUEUE当前的todo和busy收件人数量。

288-304 用双重循环来选择QMGR_TRANSPORT,外层循环针对QMGR_TRANSPORT链表(288行),内层循环针对QMGR_QUEUE(293行),选择条件如下:

1 为其分配的QMGR_TRANSPORT_ALLOC不超过QMGR_TRANSPORT_MAX_PEND(290行,QMGR_TRANSPORT_MAX_PEND默认为2) 。

2 该QMGR_TRANSPORT依然有QMGR_QUEUE可以承受本服务器向其并发发信(294行):

#define QMGR_QUEUE_READY(q) ((q)->window > 0)。

3 该QMGR_TRANSPORT依然有QMGR_QUEUE有未发送的(todo)QMGR_ENTRY_LIST供QMGR_TRANSPORT_ALLOC发送。

总之一句话:按“最近最少”原则,先选择没有充分完成任务的MDA来发信,这样对MDA的利用是平衡的,类似于linux的“完全公平调度算法”的思路——因为他们追求的都是“吞吐量”。qmgr_peer_select的实现和这里类似。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: