![](https://csdnimg.cn/release/download_crawler_static/86331988/bg5.jpg)
注:总体耗时约为4.5秒。(因网络波动每次测试结果有所变动,本文取多次平均值)
如上图所示,blocking_way() 的作用是建立 socket 连接,发送HTTP请求,然后从 socket读取HTTP响应并返回数据。示例中我们请求
了 example.com 的首页。在sync_way() 执行了10次,即下载 example.com 首页10次。
在示例代码中有两个关键点。一是第10行的 sock.connect((‘example.com’, 80)),该调用的作用是向example.com主机的80端
口发起网络连接请求。 二是第14行、第18行的sock.recv(4096),该调用的作用是从socket上读取4K字节数据。
我们知道,创建网络连接,多久能创建完成不是客户端决定的,而是由网络状况和服务端处理能力共同决定。服务端什么时候返回了响应数
据并被客户端接收到可供程序读取,也是不可预测的。所以sock.connect()和sock.recv()这两个调用在默认情况下是阻塞的。
注:sock.send()函数并不会阻塞太久,它只负责将请求数据拷贝到TCP/IP协议栈的系统缓冲区中就返回,并不等待服务端返回的应答
确认。
假设网络环境很差,创建网络连接需要1秒钟,那么sock.connect()就得阻塞1秒钟,等待网络连接成功。这1秒钟对一颗2.6GHz的CPU
来讲,仿佛过去了83年,然而它不能干任何事情。sock.recv()也是一样的必须得等到服务端的响应数据已经被客户端接收。我们下载10
篇网页,这个阻塞过程就得重复10次。如果一个爬虫系统每天要下载1000万篇网页呢?!
上面说了很多,我们力图说明一件事:同步阻塞的网络交互方式,效率低十分低下。特别是在网络交互频繁的程序中。这种方式根本不可能
挑战C10K/C10M。
3.2 改进方式:多进程
在一个程序内,依次执行10次太耗时,那开10个一样的程序同时执行不就行了。于是我们想到了多进程编程。为什么会先想到多进程呢?发
展脉络如此。在更早的操作系统(Linux 2.4)及其以前,进程是 OS 调度任务的实体,是面向进程设计的OS。
深入理解 Python 异步编程(上) - Earendil - 博客园 https://www.cnblogs.com/earendil/p/7411115.html
第5页 共21页 2018/2/2 13:24