zeromq -- 第三篇

分治模式         
         
作为一个最终的例子(也许你已经厌倦了代码而想要探讨下抽象的概念),让我们做一些超级计算机的事情;         
超级计算机应用是一个典型的并行处理模式,我们有         
         
一个通风口,作为生成可并行处理的任务;         
一组处理任务的工作者;         
一个工作池,用来收集工作者完成的任务;         
         
100003_QBvk_2413521.png         
         
    
         
         
实际上,工作者可能运行在很高的性能机器上;例如使用GPU处理较难的数学运算;下边是通风口         
它产生100个任务;每个消息都告诉工作者休息几毫秒;         
         
         
//  Task ventilator         
//  Binds PUSH socket to tcp://localhost:5557         
//  Sends batch of tasks to workers via that socket         
         
#include "zhelpers.h"         
         
int main (void)         
{         
    void *context = zmq_ctx_new ();         
         
    //  Socket to send messages on         
    void *sender = zmq_socket (context, ZMQ_PUSH);         
    zmq_bind (sender, "tcp://*:5557");         
         
    //  Socket to send start of batch message on         
    void *sink = zmq_socket (context, ZMQ_PUSH);         
    zmq_connect (sink, "tcp://localhost:5558");         
         
    printf ("Press Enter when the workers are ready: ");         
    getchar ();         
    printf ("Sending tasks to workers…\n");         
         
    //  The first message is "0" and signals start of batch         
    s_send (sink, "0");         
         
    //  Initialize random number generator         
    srandom ((unsigned) time (NULL));         
         
    //  Send 100 tasks         
    int task_nbr;         
    int total_msec = 0;     //  Total expected cost in msecs         
    for (task_nbr = 0; task_nbr < 100; task_nbr++) {         
        int workload;         
        //  Random workload from 1 to 100msecs         
        workload = randof (100) + 1;         
        total_msec += workload;         
        char string [10];         
        sprintf (string, "%d", workload);         
        s_send (sender, string);         
    }         
    printf ("Total expected cost: %d msec\n", total_msec);         
         
    zmq_close (sink);         
    zmq_close (sender);         
    zmq_ctx_destroy (context);         
    return 0;         
}         
         
         
         
下面是工作者程序,它接受一个消息,然后休眠一会,然后就报告任务完成了;         
         
//  Task worker         
//  Connects PULL socket to tcp://localhost:5557         
//  Collects workloads from ventilator via that socket         
//  Connects PUSH socket to tcp://localhost:5558         
//  Sends results to sink via that socket         
         
#include "zhelpers.h"         
         
int main (void)         
{         
    //  Socket to receive messages on         
    void *context = zmq_ctx_new ();         
    void *receiver = zmq_socket (context, ZMQ_PULL);         
    zmq_connect (receiver, "tcp://localhost:5557");         
         
    //  Socket to send messages to         
    void *sender = zmq_socket (context, ZMQ_PUSH);         
    zmq_connect (sender, "tcp://localhost:5558");         
         
    //  Process tasks forever         
    while (1) {         
        char *string = s_recv (receiver);         
        printf ("%s.", string);     //  Show progress         
        fflush (stdout);         
        s_sleep (atoi (string));    //  Do the work         
        free (string);         
        s_send (sender, "");        //  Send results to sink         
    }         
    zmq_close (receiver);         
    zmq_close (sender);         
    zmq_ctx_destroy (context);         
    return 0;         
}         
         
         
下面是工作池程序,它收集到100个任务,然后计算出总计任务完成耗时,         
         
//  Task sink         
//  Binds PULL socket to tcp://localhost:5558         
//  Collects results from workers via that socket         
         
#include "zhelpers.h"         
         
int main (void)         
{         
    //  Prepare our context and socket         
    void *context = zmq_ctx_new ();         
    void *receiver = zmq_socket (context, ZMQ_PULL);         
    zmq_bind (receiver, "tcp://*:5558");         
         
    //  Wait for start of batch         
    char *string = s_recv (receiver);         
    free (string);         
         
    //  Start our clock now         
    int64_t start_time = s_clock ();         
         
    //  Process 100 confirmations         
    int task_nbr;         
    for (task_nbr = 0; task_nbr < 100; task_nbr++) {         
        char *string = s_recv (receiver);         
        free (string);         
        if ((task_nbr / 10) * 10 == task_nbr)         
            printf (":");         
        else         
            printf (".");         
        fflush (stdout);         
    }         
    //  Calculate and report duration of batch         
    printf ("Total elapsed time: %d msec\n",         
        (int) (s_clock () - start_time));         
         
    zmq_close (receiver);         
    zmq_ctx_destroy (context);         
    return 0;         
}         
         
         
平均耗时为5秒;我们分别启动1个 ,2 个,4个工作者,获取的性能结果如下所示:         
         
1 个工作者: 总计耗时: 5034 毫秒.         
2 个工作者: 总计耗时: 2421 毫秒.         
4 个工作者: 总计耗时: 1018 毫秒.         
         
         
让我们仔细的看下这些代码:         
         
工作者上接通风口,下连工作池;这就意味着你可以随意添加工作者;如果工作者绑定         
到一个端点上,当你添加一个工作者时,你可能需要多个端点,并且需要修改通风口和工作池;         
因此,通风口和工作池一个稳定的部件,工作者是动态的;         
         
我们须同步所有的工作者和批次启动,在zeromq中这是一个常见的事情,没有其他好的办法;         
zmq_connect会消耗点时间,因此当一组工作者连接到通风口时,第一个连接成功的工作者会获取一堆消息;         
如果你不进行同步批次启动,系统就不会并行处理;试着删除通风口的等待看看会发生什么事情;         
         
通风口的推送套接字会分发任务给工作者(假定批次启动后,所有的工作者都已经连接上)         
这就叫负载均衡,         
         
工作池的推送套接字会均匀的收集工作者的任务,这焦作公平排队;         
         
         
         
         
         
         100037_uSQV_2413521.png         
         

         
管道线模式展现了“slow joiner”,导致了推送套接字不能负载均衡;如果你使用了         
PUSH和PULL,则你的某个工作者可能获取消息比其他的多;这是因为PULL套接字比其他的要参与的快,         
所以会收集到更多的消息;如果你像要均衡负载,则需要查看第三节的负载均衡模式-- 高级请求响应模式         

转载于:https://my.oschina.net/u/2413521/blog/546557

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值