问题

  我们已经熟练的掌握了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. 关于iframe和div窗口中ajax请求200状态时执行的回调问题

    上一篇说了在ajax回调里面处理iframe窗口的刷新问题,这一篇记录一下遇到的一个分别在iframe和div窗口中ajax请求200状态时执行的回调问题. 我们先来看一下ajax请求的写法(这里使用 ...

  2. android事件传递机制以及onInterceptTouchEvent()和onTouchEvent()总结

    老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料,才知道是怎么回事,这里总结一下,记住这个原则就会很清楚了: 1.onInterceptTouchEvent( ...

  3. Kotlin 第二弹:Android 中 PDF 创建与渲染实践

    这是 Kotlin 练习的的第二篇.这一篇的由来是因为刚刚在 Android 开发者官网查看 API 的时候,偶然看到了角落里面的 pdf 相关. 我仔细看看了详细文档,发现这个还蛮有意思的,关键是编 ...

  4. 使用Reaver破解开启了WPS功能的wifi密码(wpa/wpa2)

    来自wikipeida: Wi-Fi保护设置(简称WPS,全称Wi-Fi Protected Setup)是一个无线网络安全标准,旨在让家庭用户使用无线网络时简化加密步骤.此标准由Wi-Fi联盟(Wi ...

  5. InnoSetup使用笔记

    今天用InnoSetup做安装包时,因为要装的驱动区分32位.64位,64位系统中要安装32位+64位驱动. 想在脚本中进行判断.折腾一阵,终于搞定: 参考了:http://379910987.blo ...

  6. python库之selectors

    在之前的博客中已经总结过分别在windows和linux操作系统下实现socket高并发(I/O异步)的方法,可以参考基于epoll的TP传输层实现和Windows之IOCP 下面对Python中实现 ...

  7. SSH框架(1)

    一. SSH框架相关的面试题:   1.  BeanFactory的作用是什么?   [中] BeanFactory是配置.创建.管理bean的容器,有时候也称为bean上下文.Bean与bean的依 ...

  8. Docker从入门到安装MySQL

    Docker 的简介 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后 ...

  9. 洛谷P1119 灾后重建

    传送门 题目大意:点被破坏,t[i]为第i个点修好的时间,且t[1]<t[2]<t[3].. 若干询问,按时间排序,询问第t时刻,u,v的最短路径长度. 题解:floyed 根据时间加入点 ...

  10. WPF 自定义BarChartControl(可左右滑动的柱状图)(转)

    自定义可左右滑动.拖拽滑动的平面柱状图 在做这种样式控件之前,可先浏览我之前预研的控件: A.自定义左右滑动ScrollViewer(可拖动滑动) B.自定义Bar柱状图 OK,现在说下控件具体设计过 ...