65.9K
CodeProject 正在变化。 阅读更多。
Home

向 Web 服务添加 zip 过滤器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (71投票s)

2004 年 7 月 17 日

5分钟阅读

viewsIcon

416389

downloadIcon

1007

通过 Web 服务传递大量数据可能会成为 WAN 应用程序架构(例如,服务器位于 Web 上)中的巨大瓶颈,并且无论如何都会给网络流量带来实际负载。这是降低网络成本的一种解决方案。

引言

请稍等,我知道这里没有图片,但还是请您看看,特别是如果您是 Web 服务开发人员 ;-)

在编写 Web 服务时,当客户端和服务器需要通过 Web 进行通信时,通过网络传输数据的成本正成为一个问题,这既消耗响应能力,又增加网络负载。

此库通过使用 SOAP 过滤器,在服务器端压缩 SOAP 信封正文,并在客户端将其解压缩回来,这一切都在后台进行。

背景

编写此类应用程序时,有一些通用建议应遵循,其中包括以下列表:

  1. 尽量每页调用一次服务器 - 通常,实际成本是与服务器的往返访问,而不是传递实际数据。
  2. 在客户端缓存数据,以尽可能减少访问服务器的需求。
  3. 设计应用程序,仅传递必需的信息(即,不要创建“所有供应商”屏幕,而是创建“搜索特定供应商”屏幕)。

话虽如此,有时您确实需要通过 Web 传递大量数据,通常是一个包含数千行等内容的庞大的 DataSet。我的代码就在这里派上用场。

我编写了一个 Zip 过滤器和相应的 Unzip 过滤器,您可以非常简单地将其添加到您的 Web 服务(添加引用并在 web.config 文件中声明过滤器)和 WinForms 客户端(同样,添加引用和一行代码),然后即可完成。

完全无需更改代码,也没有其他开销。

代码描述

该代码是一个 DLL,客户端和服务器项目都应引用它,它由 3 个简单的类组成。

ZipWrapper

ZipWrapper 是 ICSharpZipLib 库(一个免费的 Zip 工具代码库,来自此处)的包装类,通过它可以选择所需的压缩方法(BZ2、GZip、tar 等),同时使用相同的接口。(此类代码来自此链接,并根据我的需要进行了轻微修改。)

我使用的 Zip 类型是 GZip;虽然不是最好的压缩,但它比 BZip2 快得多,并且在我们的情况下被证明更受青睐。

ZipFilter

ZipFilter 是一个 SoapOutputFilter 类,负责压缩 SOAP 信封的正文。它还公开了两个属性:

  • MinFilterSizeKB:开始压缩的最小正文大小,并非所有消息都值得压缩。
  • Enabled:过滤器是否已启用。

此类还可以确定压缩方法。

UnZipFilter

UnZipFilter 是一个 SoapInputFilter 类,它将压缩的正文恢复为其原始形式。只有当 Zip 过滤器在信封上生效时,unzip 过滤器才会运行,因此不需要任何配置参数。

代码片段

我们必须重写 ProcessMessage 方法,通过 SOAP 机制的管道更改信封的正文。首先,我们验证过滤器是否已启用以及消息是否足够大以进行压缩。然后,我们创建一个自定义标头,通知客户端应解压缩消息。接下来,我们创建一个压缩的信封正文元素的流。最后,我们将正文替换为新的压缩对象。

public override void ProcessMessage(SoapEnvelope envelope)
{
   if ( !m_bEnabled )
      return;

   //adding an attribute to specify that the filter has been 

   //applied on this envelope.

   XmlElement soapHeader = envelope.CreateHeader();

   if ( envelope.Body.InnerText.Length < ( m_MinFilterSize ) )
      return;
   else
      soapHeader.AppendChild(CreateCustomHeader(soapHeader, "1" ));

   //compress the body element.

   MemoryStream result = new 
      MemoryStream( ZipWrapper.Compress( 
      Encoding.UTF8.GetBytes( envelope.Body.InnerXml ) ) );

   //Attach zipped result to the envelope.

   Microsoft.Web.Services2.Attachments.Attachment attch = 
      new Microsoft.Web.Services2.Attachments.Attachment( 
      "APPLICATION/OCTET-STREAM",result );

   envelope.Context.Attachments.Add( attch );

   //remove old body.

   XmlElement newBody = envelope.CreateBody();
   newBody.RemoveAll();

   envelope.SetBodyObject( newBody );
}

使用该库

必备组件

  • ICSharpZipLib.dll - 在“资源”部分查找链接,WSE 2.0 - Microsoft 的 Web 服务增强包。

服务器端用法

  1. 创建一个 Web 服务项目。
  2. 在解决方案资源管理器中右键单击项目,然后选择 WSE 2.0 设置。
  3. 在“常规”选项卡中,同时选中两个复选框。
  4. 添加对 WebServiceZipFilter.dll 的引用。
  5. web.config 文件中,在 <microsoft.web.services2> 标签下添加
    <filters>
       <output>
          <add type="WebServiceZipFilter.ZipFilter, WebServiceZipFilter" />
       </output>
    </filters>

为了配置过滤器,您应该设置其属性。

// setting minimum zip size requirement to 10KB.

WebServiceZipFilter.ZipFilter.MinFilterSizeKB = 10; 
// enabling the filter

WebServiceZipFilter.ZipFilter.Enabled = true;

请注意:强烈建议通过 web.config 中的可配置部分设置这些值,以便根据调整需求动态更改它们。

客户端用法

重要提示:许多用户一再问我是否可以在双工模式下工作,以及客户端是否可以像服务器一样配置。答案是肯定的,而且都可以。下面的列表是添加到管道的过滤器的替代代码,但您可以将必要的部分添加到 app.config 文件中,无需编码即可完成(请参阅上面的“服务器端用法”部分)。关于双工模式,双方都可以随意压缩和解压缩!

  1. 创建一个 WinForms 客户端项目。
  2. 在解决方案资源管理器中右键单击项目,然后选择 WSE 2.0 设置。
  3. 在“常规”选项卡中,选中第一个复选框。
  4. 添加服务器的 Web 引用。
  5. 创建一个服务器代理(实例化 ServerNameWSE 代理类)。
  6. 在创建服务器代理后立即添加以下代码:
    // creating the server
    
    TestServer.Service1Wse myServer = 
       new TestClient.TestServer.Service1Wse();
    
    // Adding the unzip filter
    
    myServer.Pipeline.InputFilters.Add( 
       new WebServiceZipFilter.UnZipFilter() );

一些实证结果

我在一个专属于我的服务器上进行了测试,该服务器位于我们当地的 Web 农场,提供 5MB 的下载和 1MB 的上传,使用 750 KB 的 ADSL 连接,时间是周日下午,因此非压缩测试条件非常理想,但差异仍然非常显著。

发送 570 条异构数据记录,未压缩时耗时约 2.281 秒,压缩后耗时 1.843 秒(减少 20%)。

发送 10570 条记录(570 条异构数据 + 10000 条不同但相似的虚拟记录),未压缩时耗时约 29.43 秒,压缩后耗时 6.04 秒(减少 80%!!!)。如果数据完全异构,差异会微乎其微。

未来版本

会有什么变化吗?显然不会。这是好消息吗?是的!为什么?因为 Redmond 的人们意识到压缩功能缺失了,并且有几位优秀的人发布了WCF 实现,并且这些人还发布了 WSE 3.0 的版本在此处,所以我的任务基本完成了。每个人都很高兴。

资源

历史

  • 2004-7-18 v.1.0 - 首次发布。
  • 2006-5-12 v.1.1 - 修复了 tl11 报告的错误,根据字节数而不是文本长度进行压缩。

强烈建议您审阅并评论。

祝您编码愉快。

© . All rights reserved.