问题

  我们已经熟练的掌握了REQ/REP模式,它是一个一对多的模式,一个REP对应多个REQ。

  但是现实工作中,我们会遇到这样的难题,一个REP无法满足REQ的提问,因为REQ太多了,虽然可以增加一个REP,但是,这样做会带来很多问题。两个REP的端口不可能是一个,那么就需要将原来的一些REQ与这个新的REQ连接,这里面的工作量可想而知。那么我们能不能采取一种简单方便的方式,使得REQ和REP都可以灵活的增加减少而不对系统造成负面影响导致工作量上升呢?

  面对这样的要求,我们需要一个代理。让REQ和REP都连接这个代理,一切繁杂的事情都由这个代理进行。我从《ZeroMQ 云时代极速消息通信库》这本书里拍下了扩展的请求-应答解析图。

  在扩展的请求-应答系统里,REQ和REP并不直接通信,而是通过ROUTER和DEALER,ROUTER是路由器,DEALER是经销商,所有的请求到达路由器以后公平的排队,然后由经销商负载均衡后发送给REP服务器,服务器应答的结果再由经销商和路由器返回给REQ客户端。

  在这个系统里,你可以随意的增加和减少REQ,可以随意的增加和减少REP,而不必为此付出额外的工作量。

  到了这一步,聪明的朋友已经发现了问题了,一个DEALER怎么可以连接多个REP呢?没错,一个DEALER不能连接多个REP,但多个REP可以连接一个DEALER。在一对多的REQ/REP模型中,REP都是等待REQ来连接的,但在我们上图所示的系统中,REP是主动连接DEALER的,而不是等待DEALER来连接它。

实例代码:

客户端:

#coding=utf-8
'''''
发起请求
'''
import zmq # Prepare our context and sockets
context = zmq.Context()
socket = context.socket(zmq.REQ)
#这一次,我们不连接REP,而是连接ROUTER,多个REP连接一个ROUTER
socket.connect("tcp://localhost:8000") # 发送问题给ROUTER
for request in range(1,11):
socket.send(b"Hello")
message = socket.recv()
print("Received reply %s [%s]" % (request, message))
socket.close()
context.term()

中间代理

#coding=utf-8  

import zmq  

# Prepare our context and sockets
context = zmq.Context() frontend = context.socket(zmq.ROUTER)
backend = context.socket(zmq.DEALER)
frontend.bind("tcp://*:8000")
backend.bind("tcp://*:8001") # Initialize poll set
poller = zmq.Poller()
poller.register(frontend, zmq.POLLIN)
poller.register(backend, zmq.POLLIN) # Switch messages between sockets
while True:
socks = dict(poller.poll()) # frontend 收到了提问后,由backend发送给REP端
if socks.get(frontend) == zmq.POLLIN:
message = frontend.recv_multipart()
backend.send_multipart(message) # backend 收到了回答后,由frontend发送给REQ端
if socks.get(backend) == zmq.POLLIN:
message = backend.recv_multipart()
frontend.send_multipart(message)

服务端

#coding=utf-8
'''''
收到请求后回复world
'''
import zmq context = zmq.Context()
socket = context.socket(zmq.REP)
# REP连接的是DEALER
socket.connect("tcp://localhost:8001") while True:
message = socket.recv()
print("Received request: %s" % message)
socket.send(b"World")

在服务端,REP没有调用bind函数,而是调用了connect函数去连接DEALER。请求的排队和服务端的负载均衡均由中间的代理完成了,事情就是这样的简单。  

saltstack系列(六)——zmq扩展(二)的更多相关文章

  1. saltstack系列(五)——zmq扩展(一)

    问题 假设我们的一个客户端既有pull又有sub,他们两个都需要接收消息,该如何协调呢,毕竟,当一个socket要收消息的时候,函数recv是阻塞的,所以,我们第一个思路是不让它阻塞? 实例代码: # ...

  2. saltstack系列(四)——zmq Paraller Pipeline模式

    push/pull模式 push/pull模式,这是一个什么模式呢?战争时期,食物紧缺,实行配给制,大家都排好队,有人专门发放食物,前一个人领取了食物,后一个人跟上继续领取食物,这个push端就是发放 ...

  3. saltstack系列(三)——zmq订阅/发布模式

    zmq订阅发布模式 server端代码: #coding=utf-8 ''''' 服务端,发布模式 ''' import zmq from random import randrange contex ...

  4. Android系列之网络(二)----HTTP请求头与响应头

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  5. SQL Server 2008空间数据应用系列六:基于SQLCRL的空间数据可编程性

    原文:SQL Server 2008空间数据应用系列六:基于SQLCRL的空间数据可编程性 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 ...

  6. java基础解析系列(六)---深入注解原理及使用

    java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer ja ...

  7. LINQ学习系列-----1.3 扩展方法

    这篇内容继续接着昨天的Lambda表达式的源码继续下去.昨天讲了Lambda表达式,此篇讲扩展方法,这两点都是Linq带来的新特性.    一.扩展方法介绍   废话不多说,先上源码截图: 上图中Ge ...

  8. java基础解析系列(六)---注解原理及使用

    java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...

  9. Netty4.x中文教程系列(六) 从头开始Bootstrap

    Netty4.x中文教程系列(六) 从头开始Bootstrap 其实自从中文教程系列(五)一直不知道自己到底想些什么.加上忙着工作上出现了一些问题.本来想就这么放弃维护了.没想到有朋友和我说百度搜索推 ...

随机推荐

  1. QGrapicsView类

    QGraphicsView提供一个显示QGraphicsScene内容的窗口,该窗口可以滚动,可以在构造时候把场景对象作为参数,或者之后使用setScene()来设置view的场景,然后调用了show ...

  2. Android数据读取之Sqlite数据库操作

    咱们书接上文,继续来说说Android数据读取,这回,我们要讲的是Sqlite数据库的相关操作.以一个实例开始吧: 首先,上图,看看做成后的效果: 大概描述:类似于浏览器的收藏夹,网站名称,网站地址, ...

  3. Spring Boot下如何自定义Repository中的DAO方法

    环境配置介绍 jdk 1.8, Spring Boot 1.5.3.RELEASE, Mysql, Spring Data, JPA 问题描述 Spring Data提供了一套简单易用的DAO层抽象与 ...

  4. Linux部分常用命令学习(一)

    什么是linux命令? 是一个可执行程序,就像我们所看到的位于目录/usr/bin 中的文件一样. 属于这一类的程序,可以编译成二进制文件,诸如用 C 和 C++语言写成的程序, 也可以是由脚本语言写 ...

  5. Stars

    Astronomers often examine star maps where stars are represented by points on a plane and each star h ...

  6. C# 报警 控制蜂鸣器发声

    在C#中可以通过以下四种方式来实现蜂鸣或者报警,播放声音之类的功能.XP下对蜂鸣有用,win7下请接上扬声器. 1). Beep的报警实现 [c-sharp] view plaincopy     / ...

  7. 2 分支语句——《Swift3.0 从入门到出家》

    2 分支语句 当程序面临多个选择,每一个选择都会执行不同的代码块,这个时候就要使用分支语句.常见的分支语句有: if 选择语句:if... if…else if…elseif…else if是现实生活 ...

  8. 异常mongodb:Invalid BSON field name XXXXXX:YYYYY.zz

    1.本周遇到这个问题. 定位到发现一个很神奇的现象上面的结构无法顺利以map的key值存入mongodb里面. 而且到线上才发现这个问题. 而且是部分用户才会出现这样的情况 大部分人的该数据是这样的 ...

  9. Python中调用设置环境变量的bat

    工作中用到一个python脚本,自动化运行某目录下的多个vc工程代码. 编译工程代码的命令如下,直接运行会失败,系统找不到devenv,我们需要添加devenv.exe所在的目录到环境变量中. os. ...

  10. class_create(),class_device_create()创建/dev/xxx 名字

    在刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载 ...