原书地址:http://tumregels.github.io/Network-Programming-with-Go前端
若是不知道想要构建什么,是不可能建立一个系统的。并且若是不知道它工做的环境,也一样没法构建。git
GUI程序不一样于批处理程序;游戏程序不一样于商业程序;分布式程序不一样于单机程序。程序员
他们都有本身的方法、通常模式和问题,都有各自的常见问题和常看法决方案。github
本章讨论分布式系统高层架构层面的一些内容。有多种方式看待这样的系统,并且其中的许多问题已经被解决。数据库
分布式系统很难!其中涉及到多台计算机,他们必须以某种方式进行链接。编写的程序必须在系统中每台计算机都能正常运行,而且他们必须通力协做才能完成分布式任务。编程
处理复杂性问题的经常使用方法是将其划分红一个个更小更简单的分块儿。这些一个个分块儿有本身的结构,但它们也定义了与其余相关分块儿通讯的方法。在分布式系统中,这些分块儿称为协议层,他们具备明肯定义的功能。全部的分块儿组成了一个栈,每一层只同本身的上一层和下一层进行通讯。各层之间的通讯由协议定义。后端
网络通讯要求协议涵盖从高级应用程序通讯到金属导线通讯的全部通讯,而且经过协议层封装处理其中的复杂性。浏览器
尽管历来没有真正实现,在分布式系统设计的讨论和影响方面OSI(Open Systems Interconnect,开放式系统互联)协议一直是主要的影响因素。该协议一般以下图所示:安全
每一层的功能:服务器
在OSI模型被争论、辩论、争夺时,DARPA互联网研究项目正在忙于构建TCP / IP协议,并取得了巨大的成功,且挟裹资本带来了互联网。这是一个简单得多的协议栈:
虽然它看起来TCP/IP已经一统天下,但TCP / IP协议并非惟一存在的协议,从长远来看可能甚至不是最成功的协议。 有许多协议占据重要的位置,例如:
许多其余协议的工做仍在积极进行,甚至是一些很是奇怪的协议,如“太空互联网”协议。
本书的重点是TCP / IP,但你应该知道是有其余协议存在的。
网络是一种用于链接主机终端系统的通讯系统。链接载体能够是铜线、以太网、光纤或无线电磁波,但这些与咱们无关。局域网( LAN )将距离较近的计算机链接在一块儿,这些计算机一般属于家庭、小型组织或大型组织的一部分。广域网(WAN)将更大物理区域的计算机链接在一块儿,例如城市之间。还有一些其余类型网络,如城域网、我的区域网,甚至是身体区域网。
互联网是两个或更多不一样网络的链接,一般是局域网或广域网。内部网是全部网络都属于一个组织的互联网。
因特网和内部网之间有很大的区别。一般内部网将处于单一的管理控制之下,这将强加一套统一的策略。另外一方面,互联网不受单一机构的控制,对不一样部分的控制甚至可能不兼容。
这种差别的一个例子是,内部网一般会被少数供应商限制运行特定操做系统标准化版本的计算机上。另外一方面,互联网中一般会是不一样计算机和操做系统的大杂烩。
本书的技术将适用于互联网。它们对内部网也是有效的,可是在内部网中你还能碰到专用的不可移植系统。
而后是全部互联网(internet)的“母亲”:因特网/互联网(译注:The Internet,注意,在英文中加定冠词The且首字母大写特指i因特网,也就是中国大陆普称的互联网。中国台湾所称的网路,而internet表示互联网这一类网络。)。这是一个很是很是大的互联网,它把咱们链接到谷歌,把个人电脑链接到你的电脑,等等。
网关是用于链接两个或多个网络的实体的通用术语。中继器在物理层面上工做,将信息从一个子网复制到另外一个子网。网桥在数据链路层运行,并在网络之间复制帧。路由器在网络层上运行,不只在网络之间传输信息,并且选取决定路由
不管OSI仍是TCP/IP堆栈,其各层之间的通讯是经过将数据包从一层发送到下一层,而后最终经过网络完成的。每一层都有关于它本身的层的管理信息。 在发送端,当数据包向下传递时,它经过将报头信息添加到从上面的层接收到的数据包中来实现这一点。 在接收端,随着数据包的向上移动,这些报头会被删除。(译注:发送时就像是一层层的包洋葱,接收时就像一层层剥洋葱)。
例如,TFTP(Trivial File Transfer Protocol,简单文件传输协议)将文件从一台计算机移动到另外一台计算机。它使用IP协议之上的UDP协议,IP协议能够经过以太网发送。这看起来像:
经过以太网传输的数据包固然是最下层的那个。
为了让两台计算机通讯,它们必须设置一条路径,以便在一个会话中至少发送一条消息。这有两种主要模式:
会为会话创建单个链接。沿着链接的双向通讯流(译注:双工通讯),会话结束时,链接断开。这相似于电话交谈,TCP就是一个例子。
在无链接系统中,消息彼此独立地发送。普通邮件就是一个例子。无链接消息可能会无序到达。一个例子是IP协议。
面向链接的传输能够创建在无链接的传输之上——IP上的TCP。无链接传输能够创建在面向链接的传输之上——基于TCP的HTTP。
这也有一些有所不一样。例如,会话可能强制消息到达,但可能不能保证它们按照发送的顺序到达。然而,这两个是最多见的。
一些非过程性语言是基于消息传递原则构建的。并发语言常用这种机制,最著名的例子多是Unix管道。Unix管道是一个字节管道,但没有固有的限制:微软的PowerShell能够沿其管道发送对象,Parlog等并发语言能够在并发进程之间的消息中发送任意逻辑数据结构。
消息传递是分布式系统的一种基本机制。 创建链接并向其输送一些数据。 在另外一端,弄清楚消息是什么并对其作出响应,可能会发回消息。 以下图所示:
低层事件驱动系统,如X窗口系统,以与此种相似的方式运行:等待来自用户的消息(鼠标单击等),对其进行解码并对其进行操做。
更高级别的事件驱动系统假设这个解码已经由底层系统完成,而后事件被分派到一个适当的对象,好比ButtonPress handler。这也能够在分布式消息传递系统中完成,由此经过网络接收到的消息被部分解码并分派给适当的handler。
在任何系统中,都有信息和流量控制从系统的一部分转移到另外一部分。在面向过程的语言中,这可能包括过程调用,其中信息被放置在调用堆栈中,而后控制流被转移到程序的另外一部分。
即便使用过程调用,也会有一些变化。 为了控制从程序可执行代码的一部分转移到另外一部分。代码有多是静态连接的。因为愈来愈多地使用库例程,在控制权转移到独立的代码段动态连接库( DLL-s )中拥有这样的代码已经变得司空见惯。
DLLs与调用代码在同一台机器上运行。将控制转移到另外一台机器上运行的过程在概念上是一个简单的步骤。然而这其中的机制并不简单!这种控制模型驱动了“远程过程调用”(RPC),这将在后面的章节中详细讨论。如图所示:
微软在从16位应用程序到32位应用程序的转换过程当中发明了一种名为“轻量级远程过程调用”的历史怪物。16位应用程序可能须要将数据传输到同一台计算机上的32位应用程序。因为没有网络,这使得它很是轻巧!可是在数据表示和转换方面,它还有许多RPC系统的其余问题。
在最高层,咱们能够考虑分布式系统组件的等价性或不等价性。最多见的状况是不对称的:客户机向服务器发送请求,服务器做出响应。这是一个C/S系统。
若是两个组件都是等效的,都可以启动和响应消息,那么咱们就有了一个点对点系统(peer-to-peer,p2pm对等系统)。请注意,这是一个逻辑分类:一个对等点多是16000核心主机,另外一个多是移动电话。但若是他们都能作出相似的行为,那么他们就是对等的。
第三种模型是所谓的过滤器。在这里,一个组件将信息传递给另外一个组件,后者在将信息传递给第三个组件以前对其进行修改。这是一种至关常见的模型:例如,中间组件以SQL记录的形式从数据库获取信息,并将其转换为第三个组件(多是浏览器)的HTML表。
客户端/服务器系统的另外一个观点是:
第三种观点是:
C/S系统并不简单。基本模型是单客户机、单服务器:
可是你也能够有多个客户端,单个服务器:
在这种状况下,主服务器接收请求以后将它们传递给其余服务器来处理,而不是一次处理一个请求。当客户端是能够并发时,这是一种常见的模型。
还有单个客户机和多个服务器:
当服务器须要充当其余服务器的客户端时,这种状况常常发生,例如业务逻辑服务器从数据库服务器获取信息。
固然,也能够有多个客户机和多个服务器。
分解许多应用程序的一种简单但有效的方法是将它们视为由三部分组成:
表现组件负责与用户交互,包括显示数据和收集输入。它多是一个带有按钮、列表、菜单等的现代GUI界面,也多是一个较旧的命令行风格的界面,用于提问和获取答案。在这个概念层次上,细节并不重要。
应用程序逻辑负责解释用户的响应、应用业务规则、准备查询和管理来自组件的响应。
数据存储组件负责存储和检索数据。这一般会经过数据库进行,但也不必定。
基于这种应用程序的三重分解, Gartner考虑了组件在客户端-服务器系统中的分布方式, 他们提出了五种模型:
Gartner 分类:1
现代手机就是一个很好的例子:因为内存有限,它们可能在本地存储数据库的一小部分,这样它们一般能够快速响应。可是,若是须要的数据不是本地保存的数据,那么可能会向远程数据库发出请求以获取这些额外的数据。
谷歌地图是另外一个很好的例子。全部地图都位于Google的服务器上。当用户请求时,“附近”的地图也会被下载到浏览器中的一个小数据库中。当用户稍微移动地图时,所需的额外数据已经在本地存储中,能够快速响应。
Gartner 分类:2容许远程客户端访问共享文件系统
这种系统有不少例子:NFS,Microsoft共享,DCE等等。
Gartner 分类 3的一个例子是使用Java applet的网页。这是一个分布式超文本系统,具备许多其余机制。
Gartner 分类 4的一个例子是终端模拟。它容许远程系统充当本地系统上的普通终端。
Telnet是最多见的例子。
Expect是Gartner分类5的一个新颖示例。它就像一个经典系统(好比命令行界面)的包装器。它围绕此构建一个X Window接口,以便用户与GUI交互,而后GUI又与命令行界面交互。
X Window系统自己就是Gartner分类 5的一个例子。应用程序执行诸如DrawLine之类的GUI调用,但这些调用不是直接处理,而是传递给X Window服务器进行渲染。这解耦了窗口的应用程序视图和窗口的显示视图。
固然,若是有两层,那么能够有三层、四层或更多层。图中显示了三层中的一些可能性:
现代Web就是其中最右边的一个很好的例子。后端由数据库组成,一般运行存储过程来保存一些数据库逻辑。中间层是一个HTTP服务器,例如Apache运行PHP脚本(或Ruby on Rails,或JSP页面等)。这将管理一些逻辑,而且将数据,如HTML页面存储在本地。 前端是一个浏览器,在一些Javascript的控制下显示页面。在HTML 5中,前端也可能有一个本地数据库。
组件的一个常见标签就是“重”和”轻“。重型组件占用大量内存并进行复杂处理。另外一方面,轻型组件对这两种状况都几乎不起做用。彷佛没有任何“正常”大小的成分,只有重和轻。
重和轻是一个相对的概念。浏览器一般被贴上“瘦”的标签,由于“它们所作的只是显示网页”。我Linux上的Firefox占用了将近1 / 2千兆字节的内存,我认为这一点都不小!
中间件是链接分布式系统组件的技术“粘合剂/胶水”。中间件模型是
中间件的组件包括:
中间件的例子包括:
中间件的功能包括:
Gartner模型基于将应用程序分解为表示组件、应用程序逻辑和数据处理组件。更细粒度的分解是:
分布式应用程序运行在复杂的环境中。这使得它们比单个计算机上的独立应用程序更容易出现故障。 失败的缘由包括:
应用程序在设计时必须考虑到这些可能发生的故障。若是系统的其余部分发生故障,一个组件执行的任何操做都必须是可恢复的。须要使用诸如事务和连续错误检查等技术来避免错误。
分布式系统的“圣杯”将提供如下内容:
SSun Microsystems是一家在分布式系统中完成大部分早期工做的公司,甚至还有一句口号“网络就是计算机”。 根据他们多年的经验,Sun公司的一些科学家提出了如下常见的谬误:
其中许多直接影响到网络编程。例如,大多数远程过程调用系统的设计都基于这样一个前提:网络是可靠的,所以远程过程调用的行为将与本地调用相同。零延迟和无限带宽的谬误也致使RPC调用的持续时间与本地调用的持续时间相同的假设,而它们是数量级变慢的。
对这些谬误的认识致使Java的RMI(远程方法调用)模型要求每一个RPC调用均可能抛出RemoteException。这迫使程序员至少认识到网络错误的可能性,并提醒他们不能期待与本地调用有相同的速度。