前面已经介绍了套接字API以及在Python中使用的基础IP网络操作来构建通信信道的方式。本章研究服务负载较重时常用的两项基本技术:缓存与消息队列。这两项技术有如下一些共同特点:

  • 都是非常强大的工具,因而广为流行。使用Memcached或一个消息队列,不是为了实现一个有趣的协议来与其他工具进行交互,二是为了编写优雅的服务来解决特定的问题。
  • 这两项技术解决的问题通常是机构内部特有的问题。我们通常无法仅从外界就得知一个特定的网站或网络服务使用了哪种缓存、哪种消息队列以及哪种负载分配工具。
  • 尽管HTTP和SMTP这样的工具都是针对一个特定的负载设计的(HTTP针对超文本文档,SMTP针对电子邮件消息),但是缓存和消息队列是无需了解它们所要传输的数据的。
  • 我们可以将缓存和消息队列视为提供了两个已经造好的轮子,以避免重复的劳动。
Memcached意为“内存缓存守护进程“(memory cache daemon).Memcached将安装它的服务器上的空闲RAM与一个很大的近期最少使用(LRU)的缓存结合使用。我们可以从Memcached的实现中学习到一个重要的现代网络概念--分区(Sharding).使用Memcached的实际步骤是相当简单的。
  • 在每台拥有空闲内存的服务器上都运行一个Memcached守护进程。
  • 将所有Memcached守护进程的IP地址与端口号列出,并将该列表发送给所有将要使用Memcached的客户端。
  • 客户端程序现在可以访问一个组织级的速度极快的键值缓存,它就像是所有服务器之间共享的一个巨大的Python字典。该缓存是基于LRU的。如果有些项长时间没有被访问的话,就会将这些项丢弃,为新访问的项挪出空间,并记录被频繁访问的项。
Memcached Points :
  • Memcached的接口和Python的字典极其类似。将一个字符串作为值传入set()时,该字符串会以utf-8编码直接被写入Memcached,稍后在通过get()获取该字符串时会进行解码。除了简单字符串之外,写入任何其他Python对象都会自动触发memcache模块的pickle操作,然后将二进制的pickle存储在Memcached中。要牢记这一不同点,因为有时我们编写的Python应用程序会与用其他语言写的客户端共享Memcached缓存,此时,只有一字符串形式存储的值才可以被使用其他语言编写的客户端直接使用。
  • 服务器是可以丢弃存储在Memcached中的数据的。Memcached的目的是将重复计算花销较高的结果记录下来,以此来加速操作。它不是用来作为数据的唯一存储区的!
  • 当Memcached客户端得到了包含多个Memcached实例的列表时,会根据每个键的字符串的散列值对Memcached数据库进行分区(shard),由计算出的散列值决定用Memcached集群中的哪台服务器来存储特定的记录。
消息队列协议允许我们发送可靠的数据块。协议将这样的数据块称为消息(message),而不是数据报(datagram)。这是因为,数据报这一概念是用来特指不可靠服务的,传输过程中数据可能会丢失、重复或是被网络重新排列。一般来说,消息队列保证消息的可靠自动传输:一条消息约么被完好无损地传输至目的地,要么完全不传输。 消息队列协议会负责封帧,使用消息队列的客户端从来都不需要在接收到完整的消息之前一直在循环中不断调用recv()这样的函数。
消息队列还有一个创新之处,即与TCP这样基于IP传输机制提供的点对点连接不同,使用消息队列的客户端之间可以设置各种各样的拓扑结构。消息队列有很多可能的应用场景。
  • 当使用电子邮箱地址在网站注册账号时,通常会立刻返回一个页面,请于邮件收件箱内查收确认邮件。在这一过程中,用户无需等待,而网站通过我们的电子邮箱服务提供商传输邮件则可能需要好几分钟的时间。网站的通常做法是将电子邮箱地址放在一个消息队列里,当后台服务器准备好建立一个用于发送的SMTP连接时,就会从消息队列中获取邮箱地址。如果发送暂时失败,那么电子邮箱地址会被直接放回到队列中,在经历更长的时间间隔后重试。

消息队列可以作为自定义远程过程调用(RPC,Remote Procedure Call)服务的基础。远程过程调用服务允许繁忙的前端服务器将一些困难的工作交给后端服务器来负责。前端服务器可以将请求置于消息队列中,几十甚至几百个后端服务器会对该消息队列进行监听。后端服务器在处理完消息队列中的请求后会将响应返回给正在等待的前端服务器。经常需要将一些大容量的事件数据作为小型的有效消息流集中存储在消息队列中并进行分析。在一些网站中,消息队列已经彻底代替了存储到本地硬盘中的日志系统以及syslog这样更古老的日志传输机制。

消息队列应用程序设计有一个重要特点,那就是它具有混合安排并匹配所有客户端与服务器或发布者与订阅者进程的能力。需要注意的是,它们都需要连接到同一个消息队列系统。

消息队列的意义:给程序编写带来了一些革命性的进步。典型的传统应用程序在单个应用程序中包含了所有功能。它由一层一层的API组成。一个控制线程可能会负责对所有API的调用,比如先从套接字读取HTTP数据,然后进行认证,请求解析,调用API进行特定的图像处理,最后将结果写入磁盘中,该控制线程使用所有的API都必须存在于同一台机器上,并且被载入到同一个Python运行时实例内。然而,一旦我们能够使用消息队列,那么久可能会产生一个疑惑:为什么像图像处理这样计算密集型、专业且对于网络不可见的工作要与前端HTTP服务共享CPU和磁盘驱动器?因此,我们可以不使用安装了大量不同库的强大机器来构建服务,二是转而使用一些专门用于单一目的的机器,将这些机器集合到集群中,共同提供某个服务。这样一来,只要负责运维的同事理解消息传递的拓扑结构,并且保证在进行服务器分离时没有任何信息丢失,他们在卸载、安装以及重装图像处理服务器时就完全不会影响位于消息队列前端的HTTP服务负载均衡池。
通常来说,所有消息队列都支持多种拓扑结构。
  • 管道(pipeline)拓扑结构可能是与我们脑海中对于队列的直观映像最相似的一种模式:生产者创建消息,然后将消息提交至队列中,消费者从队列中接收消息。例如,一个照片分享网站的前端网络服务器可能会将用户上传的图片存储在一个专门用于接收文件的内部队列中。包含许多缩略图生成工具的机房会从队列中读取图片。每个图像处理服务器每次从队列中接收一条消息(消息中包含需要生成缩略图的图片),然后为其生成缩略图。站点较为繁忙时,队列在运行过程中可能会越来越长;站点较为空闲时,队列就会变短或是再次清空。不过,无论站点是否繁忙,前端网络服务器都可以直接向等待的客户端返回一个响应,告诉用户,上传已经成功,并且很快就能在他们的照片流中看到。
  • 发布者-订阅者(publisher-subscriber)或扇出(fanout)结构看上去和管道结构差不多,不过二者有一个重要的区别。虽然管道结构的消息队列能够保证队列中的没个消息都会被发送给一个消费者(这是由于,把同一张图片发送给两台图像服务器毕竟是很浪费的),但是消息订阅者通常想要接收队列中的所有消息。因此另一种方法是,由订阅者设置一个过滤器,通过某种特定的格式限定有兴趣的消息范围。该类型的队列可以用于需要向外部世界推送事件的外部服务。服务器机房同样可以使用队列系统来对哪些系统启动了,哪些系统因为维护而关闭进行通知。除此之外,甚至还可以使用这种队列系统在其他消息队列创建和销毁的时候发布他们的地址。
  • 最后一个是请求-响应(request-reply)模式,这也是最为复杂的模式。复杂的原因在于消息需要进行往返。在前面两种模式中,消息生产者的工作是非常少的。生产者连接到队列,然后发送消息,仅此而已。但是,发起请求的消息队列客户端需要保持连接,并等待接收响应。为了支持这一点,队列必须提供某种寻址机制,从成百上千个已经连接并且仍然处于等待的客户端中找到正确的客户端,将响应发送到该客户端。不过也正是由于这一复杂性使得请求-响应模式几乎成为了最强大的模式。它允许我们将几十或是几百个客户端请求均匀分布到大量服务器中,除了设置消息队列外,不需要做其它任何工作。一个优秀的消息队列允许服务器在不丢失消息的前提下绑定到消息队列或解除绑定,因此这种拓扑结构的消息队列同样允许服务器在需要维护而关闭时的行为对客户端机器保持不可见。
请求-响应模式的队列是将能够在某台机器上大量运行的多个轻量级线程(比如网络前端服务器的许多线程)与数据库客户端或文件服务器连接起来的一种很好的方式。数据库客户端或文件服务器有事需要被调用,代替前端服务器进行一个高负荷的运算。请求-响应模式很自然地适用于RPC机制,而且还提供了普通RPC系统没有提供的额外优点:许多消费者或生产者都可以使用扇入或扇出的工作模式绑定到同一个队列,而模式的不同对于客户端来说是不可见的。

在Python中使用消息队列
最流行的消息队列被实现为独立的服务器。构建应用程序时我们为了完成各种任务选用的所有组件(比如生产者、消费者、过滤器以及RPC服务)都可以绑定到消息队列,并且互相不知道彼此的地址,甚至不知道彼此的身份。AMQP协议是最常见的跨语言消息队列协议实现之一,我们可以安装许多支持AMQP协议的开源服务器,比如RabbitMQ、Apache Qpid服务器以及许多其他项目。
许多程序员从来都不去学习消息协议。相反,他们会去依赖一些第三方库,这些第三方库将消息队列的重要功能封装起来,并提供了易于使用的API。例如许多Django网络框架的Python程序员会使用非常流行的Celery分布式任务队列,而并不去学习AMQP协议。这些库同样可以支持其他后端服务,使得其不依赖于特定的协议。在Celery中,我们可以使用简单的Redis键值存储作为我们的”消息队列",而不需要使用专门的消息机制。

剩余内容在P143~146

Python网络编程 8 缓存与消息队列相关推荐

  1. 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)...

    RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三  多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...

  2. 读书笔记 - -《Python网络编程》重点

    文章目录 一.前言 二.客户/服务器网络编程简介 三.UDP 3.1 端口号 3.2 套接字 3.3 UDP分组 3.4 小结 四.TCP 4.1 TCP工作原理 4.2 绑定接口 4.3 死锁 4. ...

  3. python网络编程内容_图解Python网络编程

    Python Python开发 Python语言 图解Python网络编程 本篇索引 (1)基本原理 本篇指的网络编程,仅仅是指如何在两台或多台计算机之间,通过网络收发数据包:而不涉及具体的应用层功能 ...

  4. 【CSDN软件工程师能力认证学习精选】Python网络编程(socket编程)

    CSDN软件工程师能力认证(以下简称C系列认证)是由中国软件开发者网CSDN制定并推出的一个能力认证标准.C系列认证历经近一年的实际线下调研.考察.迭代.测试,并梳理出软件工程师开发过程中所需的各项技 ...

  5. Python 全栈系列122 redis消息队列搭建

    说明 不太喜欢rabbitmq之类的消息中间件,出问题不太好调试.打算使用redis替代. 内容 1 安装 1.1 版本 以docker方式安装,可以作为每台主机的一个标配.(其他的标配数据库还有mo ...

  6. python编程入门指南怎么样-学习python网络编程怎么入门

    第一部分底层网络学习 Python提供了访问底层操作系统Socket接口的全部方法,需要的时候这些接口可以提供灵活而强有力的功能. (1)基本客户端操作 在<python 网络编程基础>一 ...

  7. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)...

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程并行与并发同步与异步阻塞与非阻塞CPU密集型与IO密集型 线程与进程 进程 前言 ...

  8. python网络编程案例_Python 网络编程_python网络编程基础_python高级编程

    Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...

  9. python 网络编程 问题记录

    191223 python 网络编程 套接字的初使用 在本机配置服务端和客户端后,运行没问题:将服务端代码弄到另一台电脑上后启动,用原来的电脑去连接它,就连不上了,不知啥原因,是ip自动获取和指定ip ...

最新文章

  1. WebSocket学习与使用
  2. 如何解决文件明明存在nginx却提示404
  3. 51nod-有限背包计数问题【dp】
  4. python的read函数调用报错_从零开始学Python(七):文件存储I/O流和异常捕捉
  5. 计算机网络(一)——一些概念
  6. SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别 及动态查询中的标识符函数QUOTENAME
  7. MFC学习日志(一)
  8. 基于汽车运动学模型的LQR控制
  9. Ubuntu离线安装curl
  10. CMOS传输门原理及应用
  11. 官网Tomcat下载方法(亲测)
  12. 量化交易奇才大卫·哈丁的投资之路
  13. lol提示游戏环境异常重启计算机,出现LOL游戏环境异常请重启机器怎么解决?
  14. 为什么你微信公众号的阅读量越来越低了?
  15. bash shell实现并发多进程操作
  16. [转载]利用Web Services实现软件自动升级
  17. 用vue-cli3+vue-video-player写了个高佣联盟推广网站
  18. 草图大师SketchUp绘图-定制亚克力外壳教程
  19. sql语句利用into outfile写入一句话
  20. 编程小白从头学习ACM竞赛入门打卡 day 1

热门文章

  1. Python列表长度
  2. 回溯算法与深度优先算法
  3. Bacnet协议报文格式详解(一)
  4. C Primer Plus第五版记录
  5. 使用vue实现网上电影票购票选座
  6. Python计算机视觉读书笔记_04:获得文件夹中所有图片文件名,并生成列表
  7. 最大公因数和最小公倍数的求法
  8. ACM Weekly 2
  9. PCB设计软件之三:AD 23.0.1版本安装使用
  10. Echarts绘制带箭头的线