Azure,存储和部署静态内容(例如图像/ CSS)的最佳方法是什么?

31
我们即将部署我们的.NET Web应用程序到Azure Web角色。我只是想知道其他人如何处理静态内容,特别是图像和CSS?目前,我们的应用程序包大约有25mb,但其中18mb纯粹来自于图像,例如导航按钮、图标和模板组件,这些东西很少会被更新。把它们从部署包中分离出来并移到Blob存储中是否明智?
我对这种方法有一些疑虑,我想知道这些疑虑是否有效...
  1. 我们网站的80%在HTTPS环境下运行。在Blob存储中访问图像是否会引入跨脚本问题?
  2. 如果有人试图恶意攻击我们的图像(大多数都小于20kb),是否存在资金泄漏的风险?
  3. 我不知道如何使用目录命名约定将文件上传到Blob容器(从VS2010 + Azure SDK)。我欣赏目录在Blob容器中是一个抽象概念,但我可以使用斜杠将文件写入代码中以模仿它。显然,在我上传到Visual Studio之前,Windows不允许我这样做。
Any thoughts or alternative strategies would be welcome. The goal really is to shrink our deployment package to speed up the deploy time. Also I quite like the idea of offloading the image serving to a dedicated node to improve the performance on the web server, maybe my image collection is so small that it's hardly worth bothering?
Update 16th May Here's what I did in the end: 1.将所有图像和CSS转移到Blob存储容器中。我保留了图像和CSS文件夹中任何子目录的结构。 2.在我们的web.config文件中应用URL Rewrite规则,如下所示...
  <rewrite>
    <rules>
      <rule name="imagestoazure">
      <match url="images/(.*)" />
      <action type="Redirect" url="https://xxxxx.vo.msecnd.net/images/{R:1}" />
    </rule>
  </rules>
  </rewrite>

3. 排除应用程序中的图像和css文件夹并进行部署。

现在我的部署更小了,图像正在运行CDN上,释放了带宽,提高了下载速度,并减轻了Web服务器的负载。

更新:2015年9月

最近在审查时,我发现了来自Microsoft的以下指南。 它详细介绍了如何自动化部署您的资产并使用查询字符串进行缓存破坏。

在Web应用程序中从Azure CDN提供内容


URL 重写将重定向客户端到对应的 Blob,但请求仍然会到达 Web 服务器并消耗网络资源。是否有任何方法,如果我们可以在运行时将静态内容 URL 从相对路径更改为 Blob URI? - Surender Singh Malik
关于您的更新,您是如何将资产上传/同步到 Blob 存储的呢?这是部署过程的一部分吗?另外,您是否在静态文件的路径上进行了缓存破坏?谢谢。 - user600314
最终,我们只是使用Azure管理工具手动将图像移入CDN,解决了带宽问题。我们所有的按钮都是基于gif的,但是随着时间的推移,我们已经转向使用CSS按钮和矢量图标。现在每个月可能只有一个新的/修改后的图像,因此不需要自动化程序。我想你可以自动化部署,请看这里的“自动化内容上传”https://azure.microsoft.com/en-us/documentation/articles/cdn-serve-content-from-cdn-in-your-web-application/。 - QFDev
3个回答

15

一些评论:

将其从部署包中分离出来并移动到 Blob 存储中是否明智?

绝对是的。我可以看到这样做的许多好处:

  1. 正如您所提到的,这将大大减小您的包大小,从而使部署变得更快。
  2. 再次如您所提到的,它会卸载您的 Web 服务器负载,从而使您的站点更加响应。
  3. 如果您需要更新图像、js、css 文件,您只需在 Blob 存储中替换这些文件。如果它们留在您的包中,您将需要重新部署您的包。
  4. 您还可以利用基于 Blob 存储工作的 Windows Azure CDN。

我们网站的 80% 在 HTTPS 环境下运行。在 Blob 存储中访问图像会引入跨脚本问题吗?

只要您不通过AJAX阅读内容,我认为您不会遇到跨脚本问题 (如何从Azure Blob访问托管的XML)。但是,如果您的页面通过https提供,并且您通过http引用静态资源,则用户可能会收到混合内容(安全和非安全)消息。

如果有人试图恶意攻击我们的图像(大多数图像小于20kb),是否容易出现资金泄漏漏洞?

请查看此处的出站带宽定价:http://www.windowsazure.com/en-us/pricing/details/#header-11。目前,Windows Azure正在运行一项促销活动,可免费传输5 GB的数据,每GB 0.12美元,价格相当便宜。您还需要考虑存储事务,这也非常便宜。我不会太担心这个问题。在最坏的情况下,您可以始终回到共享访问签名并保护资源。
我很难想象如何使用目录命名约定将文件上传到blob容器(从VS2010 + Azure SDK),以便我不需要重写数千个路径引用?我知道目录在blob容器中是一个抽象的概念,但我可以使用正斜杠在代码中模拟这个。显然,在Visual Studio中上传之前,Windows不允许我这样做。
有许多第三方工具可供您使用,这些工具在上传到blob存储时将保留本地计算机的文件夹结构。请查看Windows Azure Storage团队的此博客文章:http://blogs.msdn.com/b/windowsazurestorage/archive/2010/04/17/windows-azure-storage-explorers.aspx。显然,我的个人最爱是来自Cerebrata的Cloud Storage Studio :) [我是该产品的开发人员]

非常好,感谢您的深入回复!我一定会看看Cloud Storage Studio,它似乎对我们在图像文件夹中拥有的目录结构很有用。非常感谢! - QFDev
嗨,Gaurav,我正在测试Cloud Storage Studio,它看起来很棒!我需要小心的一件事是图像路径中的大小写敏感性。幸运的是,你的应用程序似乎保留了这个! - QFDev
嗨,我喜欢将数据迁移到 Blob 存储的想法。但我还有一个问题:如何让我的网站将所有图像 URL 从(例如)~/images/1.jpg 转换为 https://<path-to-blob-container/images/1.jpg? - Mark

4
如果您的软件包大小过大,可能会受益于部署独立文件,而不是一个大的单一软件包文件。至少在Visual Studio 2012中,发布向导现在具有以下部署选项:
- Web Deploy(我鼓励您使用这个) - Web Deploy Package - FTP - 文件系统
据我所知,Web Deploy比较源文件和目标文件,物理传输仅有不同的文件(它可能会比较文件哈希,但我不知道内部情况)。
无论如何,我将尝试提供更多信息来解决您的问题:
我们网站的80%在HTTPS环境下运行。在blob存储中访问图像是否会引入跨脚本问题?
Gaurav Mantri已经回答了这个问题,但为了提供更多最近的信息,现在支持通过HTTPS访问Azure CDN,因此您可以避免混合内容消息。(仍在等待支持自定义域/SSL证书(UserVoice请求与最新信息here)。
顺便提一下,使用无协议约定(://{domain}/{relative path}),浏览器将使用与基础文档完全相同的HTTP或HTTPS协议。

我很难想象如何使用目录命名约定将文件上传到Blob容器(从VS2010 + Azure SDK),以便我不需要重写数千个路径引用? 我知道目录在Blob容器中是一个抽象概念,但我可以在代码中使用正斜杠来编写文件以模仿它。 很明显,在Visual Studio中上传之前,Windows不允许我这样做。

将静态文件同步到Blob

同步静态文件的一个可脚本化选项是AZCopy工具。

另一种选择是这个powershell脚本(更多信息请参见帖子),总结如下:

  1. Does the initial setup:

    $context = New-AzureStorageContext ` 
        -StorageAccountName $StorageAccount ` 
        -StorageAccountKey (Get-AzureStorageKey $StorageAccount).Primary
    
  2. Enumerates all local files on .\Content and .\Scripts:

    $files = (ls -Path $ProjectPath\Content -File -Recurse) + (ls -Path $ProjectPath\Scripts -File -Recurse)
    
  3. ...and uploads each file on a loop:

    foreach ($file in $files)  
        { 
            $blobFileName = (Resolve-Path $file.FullName -Relative).TrimStart('.') 
            $contentType = switch ([System.IO.Path]::GetExtension($file)) 
            { 
                ".png" {"image/png"} 
                ".css" {"text/css"} 
                ".js" {"text/javascript"} 
                default {"application/octet-stream"} 
            } 
    
            Set-AzureStorageBlobContent ` 
                -Container $StorageContainer ` 
                -Context $context ` 
                -File $file.FullName ` 
                -Blob $blobFileName ` 
                -Properties @{ContentType=$contentType} ` 
                -Force 
        } 
    

引用CDN资源

另一个要解决的问题是如何引用CDN上的文件,而不是相对路径的文件。有不同的解决方案,大多数使用辅助函数将适当的前缀注入到相对路径中(以下问题的一些答案可以帮助您:ASP.NET MVC 相对路径)。

我建议采用集中式的方式构建CDN资产URL,甚至可以实现某种缓存清除器(为此,您需要在Azure CDN上启用查询字符串参数):

Razor:

<img src="@Helper.ToCdnUrl("images/asset1.png")">

辅助方法:

public static string ToCdnUrl(string relativePath)
{
    string prefix = ConfigurationManager.AppSettings["CdnUrlBasePath"];
    string sufix = ConfigurationManager.AppSettings["StaticFilesVersion"];
    return String.concat(prefix, relativePath, "?v=", sufix);
}

应用程序设置:

<add key="CdnUrlBasePath" value="://<yourCDNName>.vo.msecnd.net/" />
<add key="StaticFilesVersion" value="1.01" />

渲染的 HTML:

<img src="://<yourCDNName>.vo.msecnd.net/images/asset1.png?v=1.01">

1
一旦此页面无法正常工作,您的答案将变得无用。 - rmuc8

3
如果CDN或Blob存储不是选项,使文件夹在Azure(或标准IIS)中提供文件的简单方法是在文件夹内创建一个Web.config文件,像这样:
<configuration>
    <system.webServer>
        <handlers>
           <clear />
            <add 
                name="StaticFile" 
                path="*" verb="*" 
                modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" 
                resourceType="Either" 
                requireAccess="Read" />
        </handlers>
        <staticContent>
            <mimeMap fileExtension=".*" mimeType="application/octet-stream" />
        </staticContent>
    </system.webServer>
</configuration> 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接