Как включить HTTP-сжатие gzip для динамического содержимого Windows Azure
Я безуспешно пытался включить HTTP-сжатие gzip на моей службе WCF Restful на Windows Azure, которая возвращает JSON только из запросов GET и POST.
Я перепробовал так много вещей, что мне было бы трудно перечислить их все, и теперь я понимаю, что я работаю с противоречивой информацией (касающейся старой версии лазури и т. Д.), Поэтому думаю, что лучше начать с чистого листа!
Я работаю с Visual Studio 2008, используя инструменты февраля 2010 для Visual Studio.
Итак, по следующей ссылке..
.. Сжатие 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 вы хотите использовать при публикации... но я не знаю, так ли это, и если это так, я не могу найти, где выбирать. Могу ли я использовать версию с предварительным http?
Я также попробовал полноценный http-модуль сжатия, но безрезультатно.
Есть ли у кого-нибудь актуальный совет о том, как этого добиться? т.е. совет, который относится к текущей версии ОС Azure.
Ура!
Стивен
Обновление: я отредактировал приведенный выше код, чтобы исправить тип во фрагменте web.config.
Обновление 2: тестирование ответов с использованием URL-адреса whatsmyip, показанного в ответе ниже, показывает, что мои ответы JSON от my service.svc возвращаются без какого-либо сжатия, но статические HTML-страницы возвращаются со сжатием gzip. Любые советы о том, как получить ответы JSON для сжатия, будут с благодарностью приняты!
Обновление 3. Попытка ответа JSON размером более 256 КБ, чтобы выяснить, не связана ли проблема с тем, что ответ JSON был меньше указанного в комментариях ниже. К сожалению, ответ по-прежнему не сжат.
6 ответов
Ну, это заняло очень много времени... но я наконец-то решил это, и я хочу опубликовать ответ для всех, кто борется. Решение очень простое, и я убедился, что оно определенно работает!!
Отредактируйте файл 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
.. и это все! Готово! Это включает динамическое сжатие для json, возвращаемого веб-ролью, которая, как мне кажется, я где-то читал, имеет довольно странный тип MIME, поэтому убедитесь, что вы точно скопировали код.
Ну, по крайней мере, я не одинок в этом - и это все еще глупая 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";
Кроме того, вы можете изменить файл applicationHost.config, используя appcmd и задачу запуска. Это обсуждается (среди прочего) в этой теме. Обратите внимание, что если вы добавите эту задачу запуска и запустите ее в структуре разработки, она будет работать один раз. Во второй раз это не удастся, потому что вы уже добавили элемент конфигурации. В итоге я создал второй облачный проект с отдельным файлом csdef, чтобы мой devfabric не запускал этот сценарий запуска. Хотя, возможно, есть и другие решения.
Обновить
Мое предложение для отдельных проектов в предыдущем абзаце не очень хорошая идея. Неидемпотентные задачи запуска - очень плохая идея, потому что однажды структура Azure решит перезапустить ваши роли для вас, задача запуска завершится неудачей и перейдет в цикл повторного запуска. Скорее всего, среди ночи. Вместо этого сделайте ваши задачи запуска идемпотентными, как обсуждалось в этой теме.
Чтобы справиться с локальной структурой разработки, имеющей проблемы после первого развертывания, я добавил соответствующие команды в файл 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
Эта статья MS посвящена тому, как писать сценарии для JSON http://msdn.microsoft.com/en-us/library/windowsazure/hh974418.aspx.
В нем рассматриваются многие из упомянутых проблем, например, возможность обработки корзины Azure и т. Д.
Просто возникла проблема с этим типом ошибки 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
Да, вы можете выбрать желаемую ОС, но по умолчанию вы получите самую последнюю версию.
Сжатие сложно. Есть много вещей, которые могут пойти не так. Вы случайно проводите это тестирование за прокси-сервером? Я считаю, что IIS по умолчанию не отправляет сжатый контент на прокси. Я нашел удобный инструмент, чтобы проверить, работает ли сжатие, когда я играл с этим: http://www.whatsmyip.org/http_compression/.
Похоже, у вас есть doDynamicCompression="false"... это просто опечатка? Вы хотите, чтобы это было включено, если вы собираетесь получить сжатие в JSON, которое вы возвращаете из веб-службы.