demoshop

demo, trying to be the best_

官方網站
http://azure.microsoft.com/zh-tw/

CDN 內容傳遞網路(Content delivery network)可以有效的利用地理位置加速網站靜態檔案的傳輸,目前市面上有許多公司針對一些常用的元件提供免費的 CDN 服務比如 Microsoft 的 http://www.asp.net/ajax/cdn ,如果把 CDN 的原理用最白話的解釋就是「越近越快」,因為網站的極速是所有網頁開發者所追求的目標,因此即使我們已經把網站全數遷移到 Microsoft Azure 也是建議使用 Microsoft Azure 提供的 CDN 服務讓網站加速的跑起來。

這裡的範例將會使用 Microsoft Azure 的 WebApp 以及使用 ASP.NET MVC 預設範本來做示範。

首先可以看到如果我們選擇了香港的主機靜態檔案的傳輸速度如下

  • JS
  • CSS
  • Image

 

如果讀者朋友有閱讀過雲端的部署建議,應該知道部署於雲端上的靜態檔案並不建議放在網站空間內,會建議改放置為儲存體,因此我們也將範例網站建立一個新的 Blob 空間預備來放置靜態檔案,建立完畢 Blob 空間後就可以將網站中的 Content 和 Scripts 資料夾都往 Blob 丟(本範例將 Images 資料夾建立在 Content 內)

接下來就將是把 Blob 綁到 CDN 上,方式很簡單,建立 CDN 時直接選擇正確的 Blob 路徑即可

 

CDN 需要散佈到全球各端點,所以剛建立的 CDN 是無法使用的(你直接點選CDN位置會一直得到 404 請耐心等待 CDN 散佈)


CDN 散佈完成後將原本的靜態檔案連結修改為 CDN 位置

<p><img src="~/Content/Image/b.jpg" alt=""/></p>@*原本的位置*@
<p><img src="http://xxxxxx.vo.msecnd.net/static/Content/Image/b.jpg" alt="" /></p>@*改成 CDN*@

<p><img src="~/Content/Image/b2.jpg" alt="" /></p>@*原本的位置*@
<p><img src="http://xxxxxx.vo.msecnd.net/static/Content/Image/b2.jpg" alt="" /></p>@*改成 CDN*@

<p><img src="~/Content/Image/b3.jpg" alt="" /></p>@*原本的位置*@
<p><img src="http://xxxxxx.vo.msecnd.net/static/Content/Image/b3.jpg" alt="" /></p>@*改成 CDN*@

當然這樣的修改在實務上比較不合理,建議讀者可以利用 Helper 的方式來處理,但那並不是本篇文章的重點。

 

當我們改成使用 CDN 以後立刻可以看出變化,這時候讀者是否就覺得 CDN 的確是好物呢?

(以上的藍箭頭是把靜態檔案放 WebApp 內,而橘色的則是放到 CDN)


但是靜態檔案需要我們自己使用工具往上丟是非常累的,因此推薦各位使用部署時自動部署靜態檔案的技巧,此技巧使用到 Powershell 腳本,此腳本您可以在這裡下載

https://gallery.technet.microsoft.com/scriptcenter/Upload-Content-Files-from-41c2142a


但 demo 調整過此腳本,建議讀者使用 demo 修改過後的版本

<#
.SYNOPSIS
    Uploads files from an ASP.NET application project folder (Scripts\ and Content\)
    into an Azure storage container.

.EXAMPLE
    .\UploadContentToAzureBlobs -ProjectPath "c:\users\<myUserName>\documents"
        -StorageContainer "myuserdocuments" -Recurse -CreateStorageContainer
#>

[CmdletBinding(SupportsShouldProcess = $true)]
param(
    # The storage account name
    [Parameter(Mandatory = $true)]
    [string]$StorageAccount,

    # The name of the storage container to copy files to.
    [Parameter(Mandatory = $true)]
    [string]$StorageContainer,

    [Parameter(Mandatory = $true)]
    [string]$ProjectPath
    
)

function Get-ScriptDirectory
{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}

# The script has been tested on Powershell 3.0
Set-StrictMode -Version 3

# Following modifies the Write-Verbose behavior to turn the messages on globally for this session
$VerbosePreference = "ContinueSilently"

Import-Module "C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Azure.psd1" -ErrorAction Stop

 Write-Warning "部署至 Blob =>=>=>=>"
# Get a list of files from the project folder
$files = (ls -Path $ProjectPath\Content -File -Recurse) + (ls -Path $ProjectPath\Scripts -File -Recurse)

$context = New-AzureStorageContext `
    -StorageAccountName $StorageAccount `
    -StorageAccountKey (Get-AzureStorageKey $StorageAccount).Primary

if ($files -ne $null -and $files.Count -gt 0)
{
    # Create the storage container.
    $existingContainer = Get-AzureStorageContainer -Context $context |
        Where-Object { $_.Name -like $StorageContainer }

    if (-not $existingContainer -and
        $PSCmdlet.ShouldProcess($StorageContainer, "Create Container"))
    {
        $newContainer = New-AzureStorageContainer `
                            -Context $context `
                            -Name $StorageContainer `
                            -Permission Blob
        "Storage container '" + $newContainer.Name + "' created."
    }

    # Upload the files to storage container.
    $fileCount = $files.Count
    $time = [DateTime]::UtcNow
    if ($files.Count -gt 0)
    {
        foreach ($file in $files)
        {
            $blobFileName = (Resolve-Path $file.FullName.Replace("\obj\Release\Package\PackageTmp","") -Relative).Replace(".\","")
            $contentType = switch ([System.IO.Path]::GetExtension($file))
            {
                ".png" {"image/png"}
                ".css" {"text/css"}
                ".js" {"text/javascript"}
                ".jpg" {"image/jpeg"}
                default {"application/octet-stream"}
            }
            Set-AzureStorageBlobContent `
                -Container $StorageContainer `
                -Context $context `
                -File $file.FullName `
                -Blob $blobFileName `
                -Properties @{ContentType=$contentType; CacheControl="public, max-age=86400"} `
                -Force
        }
    }

    $duration = [DateTime]::UtcNow - $time

    "Uploaded " + $files.Count + " files to blob container '" + $StorageContainer + "'."
    "Total upload time: " + $duration.TotalMinutes + " minutes."
}
else
{
    Write-Warning "No files found."
}

 

當然這個 Powershell 不是手動執行,請開啟雲端的發行設定檔


增加以下的CODE


<Target Name="CustomExlucdeFiles" BeforeTargets="ExcludeFilesFromPackage">
  <Exec Command="PowerShell -NoProfile -c $(OutDir)..\UploadContentToAzureBlobs.ps1 -StorageAccount 'CDN帳號' -StorageContainer '資料夾名稱本範例是static' -ProjectPath '$(OutDir)..\obj\Release\Package\PackageTmp'" IgnoreExitCode="true">
  </Exec>
</Target>

如果一切設定正確在執行「發行」動作時可以看到「輸出」視窗會有顯示

 

這樣的設定就可以讓每次執行「發行」的同時自動將靜態檔案部署至指定的 Blob 中,一切自動化,但你要付出的是每次的部署會變慢。

回應討論