你的位置:首页 > ASP.net教程

[ASP.net教程]第5章分布式系统模式 Broker(代理程序)


许多复杂的软件系统运行在多个处理器或分布式计算机上。将软件分布在多台计算机上的原因有多种,例如:

  • 分布式系统可以利用多个 CPU 或一群低成本计算机的计算能力。
  • 某个软件可能仅在特定计算机上可用。
  • 出于安全考虑,软件的各部分可能必须运行在不同的网段上。
  • 一些服务可能是由业务合作伙伴提供的,并且只能通过 Internet 进行访问。

但是,实现分布式系统是不容易的,因为您必须处理诸如并发性、跨平台连接和不可靠网络连接之类的问题。

影响因素

在构建分布式系统时,必须协调下列影响因素:

  • 虽 然分布式系统具有许多优点,但是它们往往也会使软件系统变得很复杂。运行在同一网络上的进程或计算机之间存在物理的和逻辑的边界。要使运行在不同进程或计 算机上的对象跨越这些边界相互通信,您必须处理诸如通信、编码和安全之类的问题。如果您将这些实现细节与应用程序代码混合在一起,则通信基础结构中的简单 更改就会导致大量的代码更改。
  • 在开发完成之后,通常需要分布系统。例如,可能将软件分布在多台服务器上以提高处理能力。您不会希望在生命周期中如此晚的阶段更改应用程序代码。
  • 跨进程通信的细节可能是相当乏味的。您必须处理 TCP/IP 套接字、封送和拆收、序列化、超时和许多其他难题。因此,有必要让一个特殊的工作组致力于处理基础结构,以便让应用程序开发人员不必了解远程通信。
  • 要维护能够在部署时将组件移动到不同位置这一灵活性,您必须避免对具体组件的位置进行硬编码。

解决方案

使用 Broker 模式可以隐藏远程服务调用的实现细节,方法是将这些细节封装到一个与业务组件自身不同的层 [Buschmann96]。

这个层为客户端提供一个接口,使客户端可以像调用任何本地接口一样调用方法。但是,客户端接口内的方法会触发要对远程对象执行的服务。这对客户端是透明的, 因为远程服务对象实现了相同的接口。该模式将启动远程服务调用的业务组件当作"客户端",而将响应远程服务调用的组件当作"服务器"。

图 1 显示没有进行任何分布的简单示例的静态结构。客户端直接调用服务器上的 performFunctionA 方法。仅当服务器对象与客户端对象驻留在同一台计算机上时,才能发生这种情况。

图 1:没有实现分布的结构

图 2 显示实现分布后的静态结构。

图 2:实现分布后的结构

ServiceInterface 是一个必需的抽象,对于在服务器端不必公开实现细节的情况下将由服务器提供的服务来说,这样的抽象可以通过提供有关该服务的和约而使分布成为可能。在实现 分布时,将添加客户端和服务器代理,以处理通过网络将方法调用及其参数发送到服务器,然后将响应发回客户端的所有传送工作。代理将完成所有数据封送和拆 收、安全控制、传输通道配置和任何其他附加工作。客户端只需调用客户端代理的 performFunctionA 方法,就像它是本地调用一样,这是因为客户端代理实际上实现的是 ServerInterface。对客户端进行的代码更改将是最低限度的,因此您可以开发整个业务域模型,而不必知道系统是否是分布式的。对远程服务调用的实现方式的任何更改都将被限制在代理类以内,并且不会对域模型产生任何影响。图 3 显示这些组件之间的一种交互方案。

图 3:实现分布后的行为

服务器查找

Broker 解 决方案所针对的是前面所述的大多数问题。但是,因为客户端代理直接与服务器代理进行通信,所以客户端必须能够在编译时找到服务器的位置。这意味着,您不能 在运行时将服务器更改或移动到不同位置。要克服这一限制,需要避免公开服务器的确切位置。而应当将新组件(即代理程序组件)部署在一个众所周知的位置,然 后向客户端公开该位置。此后,代理程序组件负责为客户端查找服务器。代理程序组件还会实现一个用于添加和删除服务器组件的储存库,这样就有可能在运行时添 加、删除或交换服务器组件。图 4 显示包含代理程序组件的静态结构。

这种类型的功能通常称为"名称服务"。查找远程对象是企业计算中的一项常见要求。因此,许多平台实现了名称服务,例如,Microsoft 使用 Active Directory® 目录服务。

图 4:具有服务器查找功能的代理程序结构

代 理程序驻留在一个不应该频繁更改的、众所周知的位置。已被激活并且准备接收请求的任何服务器都将向代理程序注册自己,以便下一次客户端向代理程序请求这种 类型的服务器时,代理程序能够使用它。这还可能提高系统的性能和可用性,因为它使您可以拥有多个同时运行并服务于多个客户端的、完全相同的服务器组件。这 种机制有时称为负载平衡。图 5 显示了一个这些组件之间的交互方案示例。

图 5:具有服务器查找功能的代理程序行为

代理程序作为中介

在 前面的方案中,代理程序仅负责为客户端查找服务器。这种方案中,客户端从代理程序获得服务器的位置,然后在不涉及代理程序的情况下直接与服务器进行通信。 但是,在某些情况下,我们并不希望客户端与服务器之间进行直接通信。例如,由于安全原因,您可能希望将所有服务器放在位于防火墙后面的公司专用网络中,并 且只允许代理程序访问它们。这种情况下,您必须让代理程序转发服务器和客户端这二者之间的所有请求和响应,而不是让它们直接相互通信。图 6 显示将此模型修订后的静态结构。

图 6:用作中介的代理程序的结构

图 7 显示用作客户端和服务器之间的信使的代理程序的交互图。此示例还说明了客户端和服务器之间的通信可以是异步的(注意 sendRequest 调用上的开放箭头)。

也 存在这样的情况:客户端必须对同一服务器进行一系列方法调用,才能完成一个持续时间长而且复杂的业务事务。在这样的情况中,服务器必须在前后客户端调用之 间保持状态不变。然后,代理程序必须确保客户端在基本会话内所进行的所有服务器调用都会被路由到完全相同的服务器组件。

图 7:用作中介的代理程序的行为

Broker 模式具有 Layered Application 模式的许多优点和缺点。

优点

Broker 具有下列优点:

  • 隔离。通过将所有与通信有关的代码分离到它自己的层中,从而使其与应用程序隔离。您可以决定在不必更改任何应用程序代码的情况下以分布方式运行应用程序,或者在一台计算机上运行全部应用程序。
  • 简单。将复杂的通信逻辑封装到单独的层中,可以使问题变得更简单。为代理程序编写代码的工程师不必关心无法预知的用户要求和业务逻辑,而应用程序开发人员也不必关心多播协议和 TCP/IP 路由。
  • 灵活。通过将多个函数封装在一个层中,可以允许您以不同的实现来交换该层。例如,您可以从 DCOM 切换到 .NET Remoting,再切换到标准 Web Service,而不用更改应用程序代码。

缺点

可惜的是,抽象层可以损害性能。基本规则是,拥有的信息越多,就可以优化得越好。使用单独的代理程序层可能隐藏有关应用程序如何使用较低层的细节,这可能又 会阻止较低层执行特定的优化操作。例如,使用 TCP/IP 时,路由协议不知道正在路由的是什么数据包。因此,很难决定包含视频流的数据包(例如)应该具有比包含垃圾邮件的数据包更高的路由优先级。

安全考虑事项

包含敏感业务数据的服务器组件通常位于公司的专用网络中,并受到防火墙的保护。而代理程序位于外围网络(也称为非管制区 (DMZ) 或屏蔽子网)中,外围网络是作为公司专用网络与外部公用网络之间的中性区域而插入的小型网络。只允许从外围网络访问服务器组件,而不允许从外部公用网络访 问这些组件。这一额外的网络层阻止了外部用户直接访问服务器。