58

我一直在尝试在我的 Windows Azure 托管的 WCF Restful 服务上启用 gzip HTTP 压缩但未成功,该服务仅从 GET 和 POST 请求返回 JSON。

我已经尝试了很多事情,以至于我很难将它们全部列出来,现在我意识到我一直在处理相互冲突的信息(关于旧版本的 azure 等),所以认为最好从一个干净的状态开始!

我正在使用 Visual Studio 2008,使用 Visual Studio 的 2010 年 2 月工具。

所以,根据以下链接..

.. HTTP 压缩现已启用。我使用了下一页的建议(仅限 URL 压缩建议)..

http://blog.smarx.com/posts/iis-compression-in-windows-azure

<urlCompression doStaticCompression="true" 
         doDynamicCompression="true"
         dynamicCompressionBeforeCache="true" 
/>

..但我没有压缩。我不知道urlCompressionhttpCompression之间有什么区别,这无济于事。我试图找出答案,但无济于事!

Visual Studio 的工具是在支持压缩的 Azure 版本之前发布的,这可能是个问题吗?我在某处读到,使用最新的工具,您可以在发布时选择要使用的 Azure OS 版本……但我不知道这是不是真的,如果是,我找不到在哪里选择。我可以使用启用 http 的版本吗?

我也尝试过bloery http压缩模块,但没有结果。

有没有人对如何实现这一目标有任何最新的建议?即与当前版本的 Azure OS 相关的建议。

干杯!

史蒂文

更新:我编辑了上面的代码来修复 web.config 片段中的类型。

更新 2:使用下面答案中显示的whatsmyip URL 测试响应显示我的 service.svc 的 JSON 响应在没有任何压缩的情况下返回,但静态 HTML 页面正在通过 gzip 压缩返回。我们将不胜感激地收到有关如何获取 JSON 响应以进行压缩的任何建议!

更新 3:尝试了大于 256KB 的 JSON 响应,以查看问题是否是由于 JSON 响应小于此值,如下面的评论中所述。不幸的是,响应仍未压缩。

4

6 回答 6

74

好吧,花了长时间......但我终于解决了这个问题,我想为其他正在努力的人发布答案。解决方案非常简单,我已经验证它确实有效!

编辑您的 ServiceDefinition.csdef 文件以将其包含在 WebRole 标记中:

    <Startup>
      <Task commandLine="EnableCompression.cmd" executionContext="elevated" taskType="simple"></Task>
    </Startup>

在您的网络角色中,创建一个文本文件并将其保存为“EnableCompression.cmd”

EnableCompression.cmd 应包含以下内容:

%windir%\system32\inetsrv\appcmd set config /section:urlCompression /doDynamicCompression:True /commit:apphost
%windir%\system32\inetsrv\appcmd set config  -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost

..就是这样!完毕!这为 web-role 返回的 json 启用了动态压缩,我想我在某处读到的它有一个相当奇怪的 mime 类型,所以请确保您准确地复制代码。

于 2011-09-11T00:56:03.037 回答
13

好吧,至少我并不孤单 - 差不多一年后它仍然是一个愚蠢的 PITA。

问题是 MIME 类型不匹配。WCF 返回 JSON 响应,带有Content-Type: application/json; charset=UTF-8. 默认的IIS 配置,大约在该页面的一半,不包括作为可压缩 MIME 类型。

<httpCompression>现在,将一个部分添加到您的 web.config 中并添加 application/json可能很诱人。但这只是浪费一两个小时的好方法——您只能<httpCompression>在 applicationHost.config 级别更改元素。

所以有两种可能的解决方案。首先,您可以更改 WCF 响应以使用在默认配置中可压缩的 MIME 类型。text/json将起作用,因此将其添加到您的服务方法中将为您提供动态压缩:WebOperationContext.Current.OutgoingResponse.ContentType = "text/json";

或者,您可以使用 appcmd 和启动任务更改 applicationHost.config 文件。这在此线程上进行了讨论(除其他事项外)。请注意,如果您添加该启动任务并在开发结构中运行它,它将运行一次。第二次它会失败,因为您已经添加了配置元素。我最终使用单独的 csdef 文件创建了第二个云项目,这样我的 devfabric 就不会运行该启动脚本。不过,可能还有其他解决方案。

更新

我在上一段中对单独项目的建议并不是一个好主意。非幂等启动任务是一个非常糟糕的主意,因为有一天 Azure 结构会决定为您重新启动角色,启动任务会失败,并且会进入循环循环。最有可能在半夜。相反,使您的启动任务具有幂等性,正如在此 SO 线程中所讨论的那样。

于 2011-04-14T22:09:45.720 回答
4

为了处理首次部署后出现问题的本地开发结构,我在 CMD 文件中添加了适当的命令来重置配置。此外,我在这里专门设置了压缩级别,因为在某些(全部?)情况下它似乎默认为零。

REM Remove old settings - keeps local deploys working (since you get errors otherwise)
%windir%\system32\inetsrv\appcmd reset config -section:urlCompression
%windir%\system32\inetsrv\appcmd reset config -section:system.webServer/httpCompression 

REM urlCompression - is this needed?
%windir%\system32\inetsrv\appcmd set config -section:urlCompression /doDynamicCompression:True /commit:apphost
REM Enable json mime type
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost

REM IIS Defaults
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='text/*',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='message/*',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/x-javascript',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='*/*',enabled='False']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"staticTypes.[mimeType='text/*',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"staticTypes.[mimeType='message/*',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"staticTypes.[mimeType='application/javascript',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd set config -section:system.webServer/httpCompression /+"staticTypes.[mimeType='*/*',enabled='False']" /commit:apphost

REM Set dynamic compression level to appropriate level.  Note gzip will already be present because of reset above, but compression level will be zero after reset.
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"[name='deflate',doStaticCompression='True',doDynamicCompression='True',dynamicCompressionLevel='7',dll='%%Windir%%\system32\inetsrv\gzip.dll']" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression -[name='gzip'].dynamicCompressionLevel:7 /commit:apphost
于 2012-02-14T22:03:30.957 回答
3

MS 的这篇文章是他们如何为 JSON http://msdn.microsoft.com/en-us/library/windowsazure/hh974418.aspx编写脚本。

它处理提到的许多问题,例如能够处理 Azure 回收等

于 2014-01-21T17:10:39.033 回答
3

刚刚遇到关于错误类型 183 的问题,我找到了解决方案。因此,如果其他人在这里遇到这种情况:

这是我得到的错误:

用户程序“F:\approot\bin\EnableCompression.cmd”以非零退出代码 183 退出。工作目录为 F:\approot\bin。

这是为我修复它的代码:

REM   *** Add a compression section to the Web.config file. ***
%windir%\system32\inetsrv\appcmd set config /section:urlCompression /doDynamicCompression:True /commit:apphost >> "%TEMP%\StartupLog.txt" 2>&1

REM   ERRORLEVEL 183 occurs when trying to add a section that already exists. This error is expected if this
REM   batch file were executed twice. This can occur and must be accounted for in a Windows Azure startup
REM   task. To handle this situation, set the ERRORLEVEL to zero by using the Verify command. The Verify
REM   command will safely set the ERRORLEVEL to zero.
IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL

REM   If the ERRORLEVEL is not zero at this point, some other error occurred.
IF %ERRORLEVEL% NEQ 0 (
   ECHO Error adding a compression section to the Web.config file. >> "%TEMP%\StartupLog.txt" 2>&1
   GOTO ErrorExit
)

REM   *** Add compression for json. ***
%windir%\system32\inetsrv\appcmd set config  -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost >> "%TEMP%\StartupLog.txt" 2>&1
IF %ERRORLEVEL% EQU 183 VERIFY > NUL
IF %ERRORLEVEL% NEQ 0 (
   ECHO Error adding the JSON compression type to the Web.config file. >> "%TEMP%\StartupLog.txt" 2>&1
   GOTO ErrorExit
)

REM   *** Exit batch file. ***
EXIT /b 0

REM   *** Log error and exit ***
:ErrorExit
REM   Report the date, time, and ERRORLEVEL of the error.
DATE /T >> "%TEMP%\StartupLog.txt" 2>&1
TIME /T >> "%TEMP%\StartupLog.txt" 2>&1
ECHO An error occurred during startup. ERRORLEVEL = %ERRORLEVEL% >> "%TEMP%\StartupLog.txt" 2>&1
EXIT %ERRORLEVEL%

在http://msdn.microsoft.com/en-us/library/azure/hh974418.aspx找到的解决方案

于 2014-11-25T03:15:11.510 回答
0

是的,你可以选择你想要的操作系统,但默认情况下,你会得到最新的。

压缩很棘手。有很多事情可能会出错。您是否偶然在代理服务器后面进行此测试?我相信默认情况下 IIS 不会将压缩内容发送到代理。我找到了一个方便的工具来测试我在玩这个时压缩是否有效:http: //www.whatsmyip.org/http_compression/

看起来你有 doDynamicCompression="false"... 这只是一个错字吗?如果您要对从 Web 服务返回的 JSON 进行压缩,您希望启用它。

于 2010-05-05T20:31:27.620 回答