管道过滤器模式

模式定义

管道过滤器模式将执行复杂处理的任务分解为可重复使用的一系列离散元素,这种模式可以提高性能,可扩展性和可重用性,允许执行部署和缩放独立处理的任务元素。

特定场景

整个应用的处理可以被分解成一系列离散的,独立的步骤的情况下,可以考虑使用管道过滤器模式。

当应用处理的不同的步骤,有不同的扩展性需求的情况下,可以考虑实现管道过滤器模式。

如果需要较强的灵活性的时候,可以考虑使用管道过滤器模式。管道过滤器模式令应用可以灵活的配置不同的执行步骤和执行序列,而且应用还可以按需来增加或者减少对应的处理单元。

当需要最大化服务器利用率的时候,可以选择管道过滤器模式。

如果解决方案需要保证的可靠,需要尽量降低每一个单独的处理单元中执行的失败的可能性的时候,可以考虑使用管道过滤器模式。

管道过滤器模式将执行复杂处理的任务分解为可重复使用的一系列离散元素,这种模式可以提高性能,可扩展性和可重用性,允许执行部署和缩放独立处理的任务元素。

问题

一个应用程序可能根据其处理的不同的信息需要执行各种复杂的任务。一个简单的,但不灵活的方法就是可以将应用的处理作为一个单独的模块。但是,如果部分相同的处理需要在应用程序的其他地方,这种方法可能会减少代码重构,重用,优化的机会。

很多独立模块执行的一些任务在功能上非常相似,但是因为这些模块是分开设计的,实现任务的代码都是紧密耦合在一个模块中,其中的重复部分无法得到重用来提高扩展性和重用性。

然而,每个模块执行的处理任务,或每个任务的部署要求,可能都会随着业务需求的修改而改变。有些任务可能是计算密集型的,可能会受益于运行在强大的硬件,而其他任务可能不需要这样昂贵的资源。此外,在未来可能需要执行一些额外的处理,或命令执行的任务可能会改变。所以需要一个技能解决这些问题,同时也能增加代码重用的解决方案。

解决方案

将每个数据流所需的处理分解成一组离散的组件(或过滤器),然后由每个组件来执行一个任务是一种不错的解决方案。通过标准化每个组件接收和发出的数据的格式,这些组件(过滤器)可以组合成一个管道。这种解决方案有助于避免重复代码,并且在需求发生变化的时候,可以很容易地删除,替换或集成额外的组件来实现功能。

处理单个请求的时间取决于管道中最慢的过滤器的速度。尤其在大量请求发送到组件的时候,某个或者某些组件就可能成为系统的性能瓶颈。管道结构的一个主要优点就在于,它为运行缓慢的过滤器提供了使用并行实例的机会,这样使系统能够均衡负载,以提高吞吐量。

组成管道的过滤器完全可以运行在不同的机器上,并且它们可以利用许多云环境提供的弹性能够来实现独立扩展。一个计算密集型的过滤器可以运行在高性能硬件上,而其他要求较低的过滤器可以运行在稍差的硬件上。过滤器甚至不必在相同的数据中心或不在同一个地点,管道解决方案允许管道中的每个元素可以在接近其所需资源的环境中运行。

如果一个过滤器的输入和输出被结构化为一个流,它就有可能对多个过滤器进行并行处理。管道中的第一个过滤器可以开始它的工作,并开始分发它的处理结果,这是直接传递到下一个过滤器的序列之前,第一个过滤器已完成其工作。

另一个好处是管道过滤器模式可以提供很好的跳转。如果过滤器失败或正在运行的机器不再可用,则管道可以重新安排过滤器正在执行的工作,并将此工作直接指向组件的另一实例。一个过滤器的故障并不会导致整个管道的故障。

使用管道和过滤器模式与事务补偿模式相结合,可以提供一种替代的方法来实现分布式事务。分布式事务可以分解成独立的有偿任务,每一个都可以通过使用一个过滤器,还实现了事务补偿模式。管道中的过滤器可以作为独立的托管任务来执行,这些任务还可以在物理位置上接近他们所维护的数据,以降低网络代价。

实例

Servlet Filter

凡是开发过J2EE的web application的人员都知道,经常需要处理以下几种情况:

  1. 访问特定资源(Web 页、JSP 页、servlet)时的身份认证
  2. 应用程序级的访问资源的审核和记录
  3. 应用程序范围内对资源的加密访问,它建立在定制的加密方案基础上
  4. 对被访问资源的及时转换, 包括从 servlet 和 JSP 的动态输出

在servlet2.3之前这些功能处理是很难实现的,但是Java Servlet 2.3 规范新增了不少激动人心的功能,其中之一便是过滤器(Filter),其实这就是我们所说的管道和过滤器体系架构在J2EE中的应用实践. 通过使用该模式使得Web Application开发者能够在请求到达Web资源之前截取请求,在处理请求之后修改应答。

一个执行过滤器的Java 类必须实现javax.servlet.Filter 接口。这一接口含有三个方法:

  1. init(FilterConfig):这是容器所调用的初始化方法。它保证了在第一次 doFilter() 调用前由容器调用。它能获取在 web.xml 文件中指定的filter初始化参数。
  2. doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。它同样是上一个过滤器调用的方法。引入的 FilterChain 对象提供了后续过滤器所要调用的信息。
  3. destroy():容器在销毁过滤器实例前,doFilter()中的所有活动都被该实例终止后,调用该方法。

猜你喜欢

转载自www.cnblogs.com/maosonglin/p/9084780.html