两个主要目标。
网络透明。
最重要的目标是提供对分布在计算机网络上的文件的相同访问,这些文件在集中式计算机上的分时系统中提供。
高可用性。
另一个重要目标是高可用性。系统错误或复制和维护操作不应导致文件不可用。
文件服务和文件服务器的概念。
文件服务是文件系统向其客户端提供的服务,即 文件系统接口。
文件服务器是实现文件服务的进程。
用户不需要知道有多少文件服务器以及它们的位置。
由于文件服务器通常是一个普通的用户进程,因此系统上可能有不同的文件服务器提供不同的服务(例如,UNIX 文件服务和 MS-DOS 文件服务)。
分布式系统通常有两个根本不同的组件——文件服务本身和目录服务。
5.1.1 文件服务器接口
对于任何文件系统,第一个基本问题是什么是文件。在许多系统上,例如 UNIX 和 MS-DOS,文件是不可解释的字节序列。在许多集中式计算机 (IBM/370) 上,文件由一系列记录表示,这些记录可以通过其编号或某些字段(键)的内容来指定。由于大多数分布式系统都是基于 UNIX 和 MS-DOS 环境的使用,所以它们使用了文件概念的第一个版本。
文件可以具有属性(关于不属于它的文件的信息)。典型的属性是所有者、大小、创建日期和权限。
文件模型的一个重要方面是文件创建后是否可以修改 。通常它们可以,但是有些系统具有不可变文件。此类文件将开发人员从许多缓存和传播问题中解放出来。
保护由与单处理器计算机相同的机制提供——凭据和访问权限列表。票据是针对每个文件发给用户的一种票据,表示访问权限。访问权限列表为每个文件指定了具有其权限的用户列表。最简单的权限方案是 UNIX 方案,它区分了三种类型的访问(读、写、执行)和三种类型的用户(所有者、他的组的成员和其他人)。
文件服务可以基于两种模型之一—— 上传/下载模型和远程访问模型。第一种情况,文件在客户端(内存或磁盘)和服务器之间作为一个整体传输,而第二种情况,文件服务提供了许多操作(打开、关闭、读取和写入部分文件、移动文件)指针、检查和更改属性等)。第一种方法需要来自客户端的大量内存,这是移动文件不必要部分的成本。在第二种方法中,文件系统在服务器上运行,客户端可能没有磁盘和大量内存。
5.1.2 目录服务器接口
提供创建和删除目录、命名和重命名文件、将文件从一个目录移动到另一个目录的操作。
指定名称的字母和语法。要指定文件中信息的类型, 使用名称的一部分(扩展名)或显式属性。
所有分布式系统都允许目录包含子目录——这样的文件系统称为分层文件系统。某些系统允许您创建指向可以放入目录中的任意目录的指针或链接。在这种情况下,不仅可以构建树,还可以构建任意图(它们之间的差异对于分布式系统非常重要,因为在图的情况下,删除连接会导致出现无法访问的子树。它在分布式系统中很难检测到这样的子树)。
设计分布式文件系统的一个关键决定是机器(或进程)是否应该以相同的方式查看目录层次结构。与此解决方案密切相关的是单个根目录的存在(您可以拥有这样一个目录,其中包含每个服务器的子目录)。
命名透明度。
区分命名透明的两种形式 - 位置透明 (/server/d1/f1) 和迁移透明(更改文件位置时不需要更改名称)。
命名方法有以下三种:
后一种方法是实现看起来像单台计算机的分布式系统所必需的,但它很复杂,需要仔细设计。
二级命名。
大多数系统使用某种形式的两级命名。文件(和其他对象)具有用户的符号名称,但也可能具有供系统本身使用的内部二进制名称。例如,在打开一个文件的操作中,用户指定一个符号名,并作为回报接收一个二进制名,该二进制名用于对该文件的所有其他操作。
二进制名称的形成方式在不同的系统上有所不同:
作为对符号名称的响应,某些系统可能会返回多个二进制名称(用于文件及其副本),这可以提高处理文件的可靠性。
5.1.3 文件分离语义
UNIX 语义
单处理器计算机的自然语义 - 如果写操作之后是读操作,则结果由之前的写操作中的最后一个确定。在分布式系统中,这种语义只有在只有一个文件服务器并且客户端没有缓存的情况下才容易实现。在存在缓存的情况下,语义被违反。要么立即反映文件中缓存中的所有更改,要么更改文件分离的语义。
另一个问题是很难保留公共文件指针的语义(在 UNIX 中,打开文件的进程及其子进程很常见)——不同计算机上的进程很难拥有一个公共指针。
不可变文件是改变文件共享语义的一种非常激进的方法。
只有两个操作 - 创建和读取。您可以用新文件替换旧文件 - 即 可以更改目录。如果一个进程读取一个文件而另一个进程替换它,那么您可以让第一个进程在旧文件上工作,而其他进程已经可以在新文件上工作。
会话语义
对打开文件的更改仅对进行这些更改的进程(或机器)可见,并且仅在文件关闭后它们对其他进程(或机器)可见。如果两个进程同时处理同一个文件会发生什么 - 结果将由最后关闭文件的进程确定,或者只能争辩说文件的两个变体之一将成为当前文件一。
事务
一个进程发出一个 BEGIN TRANSACTION 操作,从而表明后续操作应该在不受其他进程干扰的情况下执行。然后它发出一系列读取和写入,以 END OF TRANSACTION 操作结束。如果多个事务同时开始,则系统保证结果将与事务按顺序执行(以不确定的顺序)相同。一个例子是银行交易。
上面已经讨论了用户可见的分布式文件系统的各个方面。下面讨论实施方面。
5.2.1 使用文件
在开始实施时,了解系统的使用方式非常重要。以下是一些关于大学使用文件(静态和动态)的研究结果。评估研究数据的代表性非常重要。
5.2.2 系统结构
客户端和服务器之间有区别吗?在某些系统中,所有机器都具有相同的软件,并且任何机器都可以提供文件服务。在某些系统中,服务器是常规用户进程,可以配置为在与客户端相同的机器上或不同机器上运行。在某些系统中,客户端和服务器在硬件或软件方面是根本不同的机器(例如,需要不同的操作系统)。
第二个问题是文件服务器和目录服务器应该是单独的服务器还是合并为一个服务器。分离允许您拥有不同的目录服务器(UNIX、MS-DOS)和一个文件服务器。合并可以降低通信成本。
当服务器被拆分,不同的子树有不同的目录服务器时,就会出现以下问题。如果第一个被调用的服务器依次调用所有后续的服务器,那么会有很大的通信开销。如果第一台服务器将名称的其余部分传递给第二台服务器,然后将其传递给第三台服务器,以此类推,则不允许使用 RPC。
一种可能的出路是使用提示缓存。但是,在这种情况下,当从目录服务器接收到一个过时的二进制名称时,客户端必须准备好被文件服务器拒绝并再次联系目录服务器(客户端可能不是最终用户!)。
最后一个重要问题是服务器是否应该存储有关客户端的信息。
有状态的服务器。好处。
无状态服务器。好处。
5.2.3 缓存
在具有内存和磁盘的客户端-服务器系统中,有四个可能的位置来存储文件或其中的一部分。
首先,将文件存储在服务器磁盘上。由于存在一份文件副本,因此不存在一致性问题。主要问题是效率,因为与文件交换需要双向传输信息并与磁盘交换。
在服务器内存中缓存。这两个问题是是否缓存整个文件或磁盘块,以及如何将它们从缓存中弹出。
通信成本仍然存在。
摆脱通信允许在客户端机器中进行缓存。
在客户端磁盘上缓存可能不会比在服务器内存中缓存提供任何优势,并且复杂性显着增加。
因此,让我们仔细看看缓存在客户端内存中的组织。
仅考虑应用程序的性质和有关处理器、内存、磁盘和网络速度的数据,就可以评估一种或另一种方法的选择。
通过算法写入。
需要检查缓存中的信息是否过期。写入会导致通信开销 (MS-DOS)。
懒惰写算法。
定期将所有修改的块写入文件。效率更高,但语义对用户来说是不可理解的(UNIX)。
关闭文件时写入文件的算法。
实现会话语义。这并不比同一台计算机上的两个进程打开一个文件、读取它、在它们的内存中修改它并写回文件的情况差多少。
集中控制算法。
坚持使用 UNIX 语义是可能的,但它效率低下、不可靠并且不能很好地扩展。
5.2.4 育种
系统可以提供服务,例如在不同的服务器上维护指定文件的多个副本。主要目标:
校正协议。
简单地发送消息来更正每个副本并不是一个很好的解决方案,因为在发生崩溃时,一些副本可能仍然未更正。有两种算法可以解决这个问题。
5.2.5 示例:Sun Microsystems 网络文件系统 (NFS)
最初由 Sun Microsystem 于 1985 年实现,用于其基于 UNIX 的工作站。目前第三方也支持 UNIX 和其他操作系统(包括 MS-DOS)。NFS 的以下方面令人感兴趣 - 体系结构、协议和实现。
NFS 架构。
允许您在本地或大型网络上的任意计算机上拥有任意一组客户端和服务器。
每台服务器都会导出一些目录以供远程客户端访问。同时,导出目录及其所有子目录,即 实际上是子树。导出目录的列表存储在一个特殊的文件中,这样就可以在服务器启动时自动导出它们。
客户端通过挂载来访问导出的目录。如果客户端没有磁盘,它可以将目录挂载到其根目录。
如果多个客户端同时挂载了同一个目录,它们可以在一个公共目录中共享文件,而无需任何额外的努力。简单是 NFS 的美妙之处。
NFS 协议。
由于 NFS 的目标之一是支持异构系统,因此客户端和服务器可以运行在具有不同架构和不同操作系统的不同计算机上。因此,有必要为它们的交互制定严格的协议。NFS 有两个这样的协议。
第一个协议支持挂载. 客户端可以将目录路径名(pathname)发送到服务器并请求挂载它的权限。客户端将在哪里挂载服务器的目录无关紧要,因此不会向他报告。如果路径正确并且目录被定义为可导出,则服务器将目录句柄返回给客户端。描述符包含唯一标识给定目录的计算机类型、磁盘、i-顶点编号(UNIX OS 概念)的字段,以及有关访问权限的信息。客户端在后续目录操作中使用此句柄。
许多客户端在启动时自动挂载所需的远程目录(使用 UNIX shell 命令过程)。
Sun (Solaris) 开发的 UNIX 版本有自己特殊的自动挂载模式。许多远程目录可以与每个本地目录相关联。当打开本地目录中不存在的文件时,操作系统会向所有服务器(指定目录的所有者)发送请求。谁先回答,谁的目录将被挂载。这种方法既提供了可靠性又提供了效率(谁更自由,谁会更早回答)。这假定所有备用目录都是相同的。由于 NFS 不支持复制文件或目录,因此这种自动挂载方式主要用于有程序代码的目录或其他很少修改的文件。
第二个协议用于访问目录和文件。客户端发送消息来操作目录、读取和写入文件。您可以获取文件属性。支持大多数 UNIX 操作系统系统调用,但 OPEN 和 CLOSE 除外。要通过符号名称获取文件描述符,使用 LOOKUP 操作,这与打开文件的不同之处在于不创建内部表。因此,NFS 中的服务器是无状态的。因此,使用了一种特殊的机制来捕获文件。
NFS 使用 UNIX 安全机制。在第一个版本中,所有请求都包含用户及其组的标识符(以检查访问权限)。该系统几年的运行显示了这种方法的弱点。现在使用公钥加密机制来验证每个请求和响应的合法性。数据未加密。
用于访问控制的所有密钥都由特殊服务(和服务器)维护 - 网络信息服务 (NIS)。通过存储对(键、值),服务确保在正确验证键时返回代码的值。此外,它还提供机器名称到其网络地址的映射以及其他映射。NIS 服务器使用主从方案来实现传播(惰性传播)。
虚拟文件系统层的任务是为每个打开的文件在表(v-top)中维护一行,类似于 UNIX i-top。此行允许您区分本地文件和远程文件。对于远程文件,所有必要的信息都存储在 NFS 客户端中的一个特殊 r-node 中,由 v-node 引用。服务器没有任何表。
NFS 客户端和服务器之间的信息传输以 8K 块为单位进行(为了提高效率)。
两个缓存 - 一个数据缓存和一个文件属性缓存(它们被非常频繁地访问,NFS 开发人员从 90% 的估计开始)。实现了惰性写入语义 - NFS 批评的主题。
还有一个提示缓存可以通过符号名称加速 v-vertex 检索。当使用 legacy 提示时,NFS 客户端将联系 NFS 服务器并更新其缓存(用户不应该对此一无所知)。