ZeroMQ系列 之NetMQ

一:zeromq简介

二:NetMQ 请求响应模式 Request-Reply

三:NetMQ 发布订阅模式 Publisher-Subscriber

四:NetMQ 推拉模式 Push-Pull

NetMQ 推拉模式 Push-Pull

1:简介

推拉模式,也叫 管道模式”Parallel Pipeline”。想象一下这样的场景,如果需要统计各个机器的日志,我们需要将统计任务分发到各个节点机器上,最后收集统计结果,做一个汇总。PipeLine比较适合于这种场景,他的结构图,如图1所示

图1 官方图

Ventilator,在管道中生产任务;
Worker ,处理任务;
Sink,收集Worker处理的结果。

2:案例

下面有三个对象Ventilator 消息分发者,Worker 消息处理者,Sink 接受Worker处理消息后返回的结果,耗时的计算处理工作是交给Worker的,如果开多个Worker.exe,可以提升处理速度,Worker的最终目的是分布式计算,部署到多台PC上面,把计算工作交给他们去做(在分布式爬虫上面,每个Worker相当于一个爬虫)。
下面案例结构,如图2所示:


图2

源码:

Ventilator

    static void Main(string[] args)
    {
        // Task Ventilator
        // Binds PUSH socket to tcp://localhost:5557
        // Sends batch of tasks to workers via that socket
        Console.WriteLine("====== VENTILATOR ======");

        //socket to send messages on
        using (NetMQSocket sender = new DealerSocket())
        {
            sender.Bind("tcp://*:5557");

            using (var sink = new DealerSocket())
            {
                sink.Connect("tcp://localhost:5558");

                Console.WriteLine("Press enter when worker are ready");
                Console.ReadLine();

                //the first message it "0" and signals start of batch
                //see the Sink.csproj Program.cs file for where this is used
                Console.WriteLine("Sending start of batch to Sink");
                sink.SendFrame("0");

                Console.WriteLine("Sending tasks to workers");

                //initialise random number generator
                Random rand = new Random(0);

                //expected costs in Ms
                int totalMs = 0;

                //send 100 tasks (workload for tasks, is just some random sleep time that
                //the workers can perform, in real life each work would do more than sleep
                for (int taskNumber = 0; taskNumber < 100; taskNumber++)
                {
                    //Random workload from 1 to 100 msec
                    int workload = rand.Next(0, 100);
                    totalMs += workload;
                    Console.WriteLine("Workload : {0}", workload);
                    sender.SendFrame(workload.ToString());
                }
                Console.WriteLine("Total expected cost : {0} msec", totalMs);
                Console.WriteLine("Press Enter to quit");
                Console.ReadLine();
            }
        }
    }  

Worker

    static void Main(string[] args)
    {
        // Task Worker
        // Connects PULL socket to tcp://localhost:5557
        // collects workload for socket from Ventilator via that socket
        // Connects PUSH socket to tcp://localhost:5558
        // Sends results to Sink via that socket
        Console.WriteLine("====== WORKER ======");

        //socket to receive messages on
        using (var receiver = new DealerSocket())
        {
            receiver.Connect("tcp://localhost:5557");

            //socket to send messages on
            using (var sender = new DealerSocket())
            {
                sender.Connect("tcp://localhost:5558");

                //process tasks forever
                while (true)
                {
                    //workload from the vetilator is a simple delay
                    //to simulate some work being done, see
                    //Ventilator.csproj Proram.cs for the workload sent
                    //In real life some more meaningful work would be done
                    string workload = receiver.ReceiveString();

                    //simulate some work being done
                    Thread.Sleep(int.Parse(workload));

                    //send results to sink, sink just needs to know worker
                    //is done, message content is not important, just the precence of
                    //a message means worker is done.
                    //See Sink.csproj Proram.cs
                    Console.WriteLine("Sending to Sink");
                    sender.SendFrame(string.Empty);
                }
            }
        }
    }

Sink

    static void Main(string[] args)
    {
        // Task Sink
        // Bindd PULL socket to tcp://localhost:5558
        // Collects results from workers via that socket
        Console.WriteLine("====== SINK ======");

        //socket to receive messages on
        using (var receiver = new DealerSocket())
        {
            receiver.Bind("tcp://localhost:5558");

            //wait for start of batch (see Ventilator.csproj Program.cs)
            var startOfBatchTrigger = receiver.ReceiveString();
            Console.WriteLine("Seen start of batch");

            //Start our clock now
            Stopwatch watch = new Stopwatch();
            watch.Start();

            for (int taskNumber = 0; taskNumber < 100; taskNumber++)
            {
                var workerDoneTrigger = receiver.ReceiveString();
                if (taskNumber % 10 == 0)
                {
                    Console.Write(":");
                }
                else
                {
                    Console.Write(".");
                }
            }
            watch.Stop();
            //Calculate and report duration of batch
            Console.WriteLine();
            Console.WriteLine("Total elapsed time {0} msec", watch.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }  

效果图:

处理一个Ventilator任务,可以使用数量不同的worker:

一个worker:
在我本地计算机上,耗时 5566 mesc

二个worker:
在我本地计算机上,耗时2917 mesc

三个worker:
在我本地计算机上,耗时2031 msec

3:总结

  1. 使用的NetMQ版本是3.3.3.1,实例化DealerSocket,来创建socket。
  2. Ventilator分发工作到不同的Worker,实现负载均衡。
  3. Ventilator和Sink是静态部分,Worker是动态的。开启更多的Worker,理论上完成工作更快。
  4. Sink收集Worker处理的结果.

4:下载

NetMQ3.3.3.1例子
NetMQ3.3.2.2例子

NetMQ(四): 推拉模式 Push-Pull的更多相关文章

  1. ActiveMQ基本详解与总结& 消息队列-推/拉模式学习 & ActiveMQ及JMS学习

    转自:https://www.cnblogs.com/Survivalist/p/8094069.html ActiveMQ基本详解与总结 基本使用可以参考https://www.cnblogs.co ...

  2. 消息队列-推/拉模式学习 & ActiveMQ及JMS学习

    一种分类是推和拉 . 还有一种分类是 Queue 和 Pub/Sub . 先看的这一篇:http://blog.csdn.net/heyutao007/article/details/50131089 ...

  3. RabbitMQ入门_03_推拉模式

    我们知道,消费者有两种方式从消息中间件获取消息: 推模式:消息中间件主动将消息推送给消费者 拉模式:消费者主动从消息中间件拉取消息 推模式将消息提前推送给消费者,消费者必须设置一个缓冲区缓存这些消息. ...

  4. 实战ZeroMQ的PUSH/PULL推拉模式

    原文地址: http://ju.outofmemory.cn/entry/235976

  5. 微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨

    sns系统,微博系统都应用到了feed(每条微博或者sns里的新鲜事等我们称作feed)系统,不管是twitter.com或者国内的新浪微博,人人网等,在各种技术社区,技术大会上都在分享自己的feed ...

  6. [转] 消息系统该Push/Pull模式分析

    信息推拉技术简介 “智能信息推拉(IIPP)技术”是在网上信息获取技术中加入了智能成份,从而有助于用户在海量信息中高效.及时地获取最新信息,提高了信 息系统主动信息服务的能力.如果引入基于IIPP的主 ...

  7. 理解bootstrap的列偏移offset 和 推拉push/pull的区别?

    参考: http://www.cnblogs.com/jnslove/p/5430481.html & https://blog.csdn.net/hly_coder/article/deta ...

  8. 脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

    本文原作者阮一峰,作者博客:ruanyifeng.com. 1.前言 新一代HTTP/2 协议的主要目的是为了提高网页性能(有关HTTP/2的介绍,请见<从HTTP/0.9到HTTP/2:一文读 ...

  9. RocketMQ(一):推拉消费模型客户端实践

    消息中间件是为解耦生产者和消费者的目的,三大服务点:解耦.异步.削峰. 现在的的互联网系统中,mq已经必备基础设施了,我们已明显感觉它的必要性与强大.然而,它的本质是啥?存储转发系统罢了! MQ有很多 ...

随机推荐

  1. Python 下载 tushare 数据,然后调用 C++ DLL 计算 wMA 存入本地 csv 文件再 python 读取

    CMakeLists.txt project(wMA) add_library(wMA SHARED wMA.cpp) wMA.h #pragma once #ifndef WMA_WMA_H #de ...

  2. Caf.CMS是一个免费的、 开源,功能齐全的CMS

    Caf.CMS(疯狂蚂蚁CMS) 是一个免费的. 开源,功能全面的CMS(内容管理系统).定位CMS也有点狭义呢,因为Caf.CMS是基于国外SmartStore.NET 开源商城源码的基础上改造而成 ...

  3. webSphere内存溢出

    有一个做了很长时间的项目,是用websphere做生产环境的,可是一旦加载的项目过多,webSphere就很傲娇的内存溢出,这是一个折腾了公司里某个前辈很久很久的问题,因为是测试版,所以各种官方文档说 ...

  4. [asp.net core]定义Tag Helpers

    原文地址 https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/authoring Getting started wi ...

  5. linux查看端口及端口详解

    今天现场查看了TCP端口的占用情况,如下图   红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说E ...

  6. adb install INSTALL_FAILED_ALREADY_EXISTS

    安装时候碰到的一个问题:已经签名的包,重新通过adb install 会提示安装错误.提示:Failure [INSTALL_FAILED_ALREADY_EXISTS] 为啥eclipse自己就可以 ...

  7. touch

    Linux touch 命令   在 Linux 下运用 touch 命令创建一个空文件.当然我们也可以使用其他命令例如 vi, nano 或是任意一个编辑工具来实现.但是你可能需要更多的步骤来完成操 ...

  8. Javascript设计模式学习二(单例)

    定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点 普通的单例模式: 使用一个变量来标记当前是否已经为某个类创建过对象,如果是的话,在下一次获取该类的实例时,直接返回之前创建的对象.比如:使用 ...

  9. Bootstrap table使用心得

    序号显示带分页信息的连续编号,在序号列添加以下格式化代码即可. { field: 'number', title: '序号', align:'center', width:45, formatter: ...

  10. Asp.Net Core--发布到IIS

    翻译如下: 支持的操作系统 Windows 7及更高版本 Windows Server 2008 R2及更高版本 概念上,本文档中描述的IIS配置也适用于在Nano Server IIS上托管ASP. ...