如何在Windows Azure动态内容上启用gzip HTTP压缩

时间:2010-05-05 17:02:58

标签: json gzip azure http-compression

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

我已经尝试了很多东西,我很难列出所有这些东西,我现在意识到我一直在处理相互矛盾的信息(关于旧版本的天蓝色等),所以最好从干净的石板开始!

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

所以,根据以下link ..

..现在已启用HTTP压缩。我已经使用了以下页面中的建议(仅限URL压缩建议)..

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

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

..但我没有压缩。我不知道 urlCompression httpCompression 之间有什么区别。我试图找出但无济于事!

可能,Visual Studio的工具是在支持压缩的Azure版本之前发布的,这是一个问题吗?我已经阅读过某些地方,使用最新的工具,您可以选择在发布时使用哪个版本的Azure OS ...但我不知道这是否属实,如果是,我找不到哪里选择。我可以使用预启用http的版本吗?

我也试过了吹嘘的http压缩模块,但没有结果。

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

干杯!

史蒂芬

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

更新2:使用下面的答案中显示的whatsmyip URL测试响应,显示我的service.svc的JSON响应在没有任何压缩的情况下被返回,但是静态HTML页面使用gzip压缩返回。任何有关如何获得压缩的JSON响应的建议都将非常感激!

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

6 个答案:

答案 0 :(得分:73)

好吧,非常很长一段时间......但我终于解决了这个问题,我想为其他任何正在挣扎的人发布答案。解决方案非常简单,我已经确认它确实有效!!

编辑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类型,所以请确保你完全复制代码。

答案 1 :(得分:13)

至少我不是一个人 - 而且差不多一年之后它仍然是一个愚蠢的PITA。

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

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

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

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

更新

我对前一段中单独项目的建议并不是一个好主意。非幂等启动任务是一个非常糟糕的主意,因为有一天Azure结构将决定为您重新启动角色,启动任务将失败,并且它将进入循环循环。最有可能是在半夜。相反,请按照this SO thread中的讨论,使您的启动任务具有幂等性。

答案 2 :(得分: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

答案 3 :(得分:3)

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

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

答案 4 :(得分:3)

关于错误类型183,我遇到了一个问题,我找到了解决方案。所以,如果有人在这里遇到这个问题,那就去了:

这是我得到的错误:

  

用户程序&#34; F:\ approot \ bin \ EnableCompression.cmd&#34;以非零退出代码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

找到解决方案

答案 5 :(得分:0)

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

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

看起来你有doDynamicCompression =“false”......这只是一个错字吗?如果您要从Web服务返回的JSON上获得压缩,则希望打开它。