Skip to content

4.6 分布式计算 ​

INFO

来源:4.6 Distributed Computing

对应:无

大规模数据处理应用往往要在多台计算机之间协调工作。分布式计算(distributed computing)应用,就是让多台相互连接、彼此独立的计算机协作完成同一项计算。

这些计算机彼此独立,也就是说它们不直接共享内存。它们靠消息(message)通信——消息就是通过网络从一台计算机传到另一台计算机的信息。

4.6.1 消息 ​

计算机之间发送的消息是字节序列(sequences of bytes)。消息的用途各不相同:可以请求数据、发送数据,也可以指示另一台计算机求值一次过程调用。无论哪种情况,发送方都必须以接收方能解码并正确解读的方式来编码信息。为此,计算机会采用一种消息协议,为字节序列赋予含义。

消息协议(message protocol)是一套用于编码和解读消息的规则。发送方和接收方必须就消息的语义达成一致,通信才能成功。许多消息协议规定消息要遵循特定格式,比如固定位置上的某些位(bit)表示固定的含义。另一些协议则用特殊的字节或字节序列来划定消息的各个部分,就像标点符号在编程语言的语法中划分出子表达式那样。

消息协议不是某个具体的程序或软件库,而是一套规则,各种程序都能遵循它,哪怕这些程序是用不同编程语言写的。因此,软件系统千差万别的计算机,只要遵守同一个系统的消息协议,就能加入同一个分布式系统。

TCP/IP 协议。在互联网上,消息通过 互联网协议(Internet Protocol,IP)从一台机器传输到另一台机器。IP 规定了如何在不同网络之间传输数据包(packet),从而让全球范围的互联网通信成为可能。IP 的设计前提是:网络在任何一点上都不可靠,结构也是动态变化的;它也不假设存在任何集中式的通信跟踪或监控。每个数据包都含有一个头部,里面有目标 IP 地址以及其他信息。所有数据包都按简单的路由规则,以尽力而为(best-effort)的方式在网络中朝着目的地转发。

这种设计给通信带来了一些限制。用现代 IP 实现(IPv4 和 IPv6)传输的数据包,最大为 65,535 字节,更大的数据必须拆分成多个数据包。IP 不保证数据包按发送时的顺序送达。有些数据包可能丢失,有些可能被重复传输。

传输控制协议(Transmission Control Protocol,TCP)是建立在 IP 之上的一种抽象,提供对任意大小字节流的可靠、有序传输。它靠三点做到这一点:把 IP 传输的数据包正确排序,去除重复,并在数据包丢失时请求重传。可靠性提高的代价是延迟(latency),也就是把消息从一点发到另一点所需的时间。

TCP 把数据流切分成 TCP 段(TCP segment)。每个段都含一部分数据,数据前面有一个头部,里面是序列和状态信息,用来支持数据的可靠、有序传输。有些 TCP 段根本不含数据,只负责在两台计算机之间建立或终止连接。

在两台计算机 A 和 B 之间建立连接,分三个步骤:

  1. A 向 B 的一个端口(port)发送请求,要求建立 TCP 连接,并给出一个端口号(port number),供 B 发送响应。
  2. B 向 A 指定的端口发送响应,然后等待自己的响应被确认。
  3. A 发回确认响应,表示数据可以双向传输。

经过这三步「握手」,TCP 连接就建立好了,A 和 B 可以互相发送数据。关闭 TCP 连接也要经过一系列步骤,客户端和服务器都要请求并确认连接结束。

4.6.2 客户端/服务器架构 ​

客户端/服务器架构是一种从一个中心源提供服务的架构。服务器(server)提供服务,多个客户端(client)与服务器通信来使用这项服务。在这种架构里,客户端和服务器角色不同。服务器的职责是响应客户端的服务请求,客户端的职责则是发出请求,并利用服务器的响应完成某项任务。下图说明了这种架构。

客户端/服务器架构

这种模型最具影响力的应用是万维网(World Wide Web)。当 Web 浏览器显示网页内容时,运行在各自独立计算机上的几个程序靠客户端/服务器架构相互配合。本节描述请求网页的过程,借此说明客户端/服务器分布式系统的核心思想。

角色。请求网页时,Web 用户计算机上的浏览器应用充当客户端。要从互联网上的某个域名(例如 www.nytimes.com)获取内容,它必须和至少两个不同的服务器通信。

客户端先向域名服务器(Domain Name Server,DNS)请求该域名对应计算机的 IP 地址。DNS 提供的服务,就是把域名映射为 IP 地址,也就是计算机在互联网上的数字标识符。Python 可以用 socket 模块直接发出这种请求。

python
>>> from socket import gethostbyname
>>> gethostbyname('www.nytimes.com')
'170.149.172.130'

接着,客户端再向位于该 IP 地址的 Web 服务器请求网页内容。这里的响应是一份 HTML 文档,里面有当天的新闻标题和文章摘录,还有一些表达式,用来指示浏览器客户端如何在用户屏幕上排布这些内容。Python 可以用 urllib.request 模块发出检索这些内容所需的两次请求。

python
>>> from urllib.request import urlopen
>>> response = urlopen('http://www.nytimes.com').read()
>>> response
b'<!DOCTYPE.html>'

收到这份响应后,浏览器还会为图像、视频和页面的其他附属组件发出更多请求。之所以要发这些请求,是因为原始 HTML 文档里含有这些额外内容的地址,以及它们如何嵌入页面的说明。

HTTP 请求。超文本传输协议(Hypertext Transfer Protocol,HTTP)是一种基于 TCP 实现的协议,负责万维网(World Wide Web,WWW)的通信。它假定 Web 浏览器和 Web 服务器之间是客户端/服务器架构。HTTP 规定了浏览器和服务器之间交换的消息格式。所有 Web 浏览器都用 HTTP 格式向 Web 服务器请求页面,所有 Web 服务器也都用 HTTP 格式发回响应。

HTTP 请求有几种类型,最常见的是索取某个网页的 GET 请求。GET 请求会指定一个位置。例如,在 Web 浏览器里输入地址 http://en.wikipedia.org/wiki/UC_Berkeley,就会向 en.wikipedia.org 的 80 端口发出一个 HTTP GET 请求,索取 /wiki/UC_Berkeley 处的内容。服务器会返回一个 HTTP 响应:

HTTP
HTTP/1.1 200 OK
Date: Mon, 23 May 2011 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2011 23:11:55 GMT
Content-Type: text/html; charset=UTF-8

... web page content ...

第一行里的 200 OK 表示响应请求时没有出错。头部的后面几行给出了服务器、日期和所发送内容类型的信息。

如果你输入了错误的网址,或者点开了一个失效的链接,可能见过这样的错误提示:

HTTP
404 Error File Not Found

这表示服务器发回的 HTTP 头部开头是:

HTTP
HTTP/1.1 404 Not Found

200 和 404 是 HTTP 响应代码。一组固定的响应代码,是消息协议的常见特征。协议设计者会设法预测协议上会出现的常见消息,为它们分配固定的代码,以缩小传输体积、确立统一的消息语义。在 HTTP 协议中,响应代码 200 表示成功,404 则表示找不到资源这一错误。HTTP 1.1 标准里还有各种其他 响应代码。

模块化。客户端和服务器是强大的抽象。服务器提供服务,可能同时服务多个客户端,客户端则使用这项服务。客户端不必知道服务具体如何提供,也不必知道自己收到的数据如何存储或计算;服务器同样不必知道自己的响应会怎么被使用。

在 Web 上,我们认为客户端和服务器位于不同的计算机上,但即使系统只在一台计算机上,也可以采用客户端/服务器架构。例如,计算机上输入设备的信号,需要能被计算机上运行的程序普遍使用。程序是客户端,使用鼠标和键盘输入数据。操作系统的设备驱动是服务器,接收物理信号,把它们变成可用的输入提供出来。此外,中央处理单元(CPU)和专用的图形处理单元(GPU)也常常以客户端/服务器架构协作,其中 CPU 是客户端,GPU 是图像的服务器。

客户端/服务器系统的一个缺点,是服务器会成为单点故障。它是唯一能提供这项服务的组件。客户端的数量不限,它们彼此可以替换,也可以按需要随时加入或退出。

另一个缺点是,客户端太多时计算资源会变得紧缺。客户端只会增加系统的负担,却不贡献任何计算资源。

4.6.3 对等系统 ​

客户端/服务器模型适合面向服务的情况。但对另一些计算目标来说,更平均的分工可能是更好的选择。「对等」(peer-to-peer)一词,用来描述工作分摊到系统所有组件上的分布式系统。所有计算机都收发数据,都贡献一部分处理能力和内存。分布式系统规模越大,其计算资源容量也越大。在对等系统中,所有组件都为分布式计算贡献处理能力和内存。

所有参与者共同分担工作,是对等系统的标志性特征。这意味着各对等体必须能可靠地互相通信。为了确保消息能送达预定的目的地,对等系统需要有组织良好的网络结构。这些系统里的各个组件通力合作,掌握足够多关于其他组件位置的信息,好把消息送到预定的目的地。

有些对等系统里,维持网络健康的工作由一组专门的组件承担。这样的系统并不是纯粹的对等系统,因为它有类型不同、功能也不同的组件。支撑对等网络的组件就像脚手架:它们帮网络保持连通,维护不同计算机位置的信息,还帮新成员在自己的邻域里找到位置。

对等系统最常见的应用是数据传输和数据存储。数据传输方面,系统里每台计算机都出力,把数据发到网络上。如果目标计算机正好在某台计算机的邻域里,这台计算机就帮忙把数据送过去。数据存储方面,数据集可能太大,一台计算机存不下;也可能太宝贵,只存一台不放心。于是每台计算机只存一小部分数据,同一份数据还可能有多个副本分散在不同计算机上。当某台计算机出故障时,上面的数据可以从其他副本恢复,等替换的计算机到位后再放回去。

Skype 是一款语音和视频聊天服务,也是采用对等架构的数据传输应用的例子。当不同计算机上的两个人进行 Skype 会话时,他们的通信通过一个对等网络传输。这个网络由运行 Skype 应用的其他计算机组成。每台计算机都知道自己邻域内几台其他计算机的位置。一台计算机要把数据包发往目的地,就把它交给一个邻居,邻居再交给另一个邻居,如此接力,直到数据包到达预定的目的地。Skype 并不是一个纯粹的对等系统。一个由超级节点(supernode)组成的脚手架网络,负责用户的登录和注销,维护其计算机位置的信息,并在用户加入和退出时调整网络结构。

基于 MIT 许可发布