共用方式為


教學課程:使用 Azure Functions 和 Azure Web PubSub 服務建立無伺服器通知應用程式

Azure Web PubSub 服務可協助您使用 WebSocket 建置即時傳訊 Web 應用程式。 Azure Functions 是無伺服器平台,可讓您在不需要管理任何基礎結構的情況下執行您的程式碼。 在本教學課程中,您會了解如何使用 Azure Web PubSub 服務和 Azure Functions,在通知案例下建置具有即時傳訊的無伺服器應用程式。

在本教學課程中,您會了解如何:

  • 建置無伺服器通知應用程式
  • 使用 Web PubSub 函式輸入和輸出繫結
  • 在本機執行範例函式
  • 將函式部署至 Azure 函數應用程式

重要

原始 連接字串 只會針對示範目的出現在本文中。

連接字串包含應用程式存取 Azure Web PubSub 服務所需的授權資訊。 連接字串內的存取金鑰類似於服務的根密碼。 在生產環境中,請一律保護您的存取金鑰。 使用 Azure 金鑰保存庫,安全地管理和輪替密鑰,並使用保護連線WebPubSubServiceClient

避免將存取金鑰散發給其他使用者、寫入程式碼,或將其以純文字儲存在他人可以存取的位置。 如果您認為金鑰可能已遭盜用,請輪替金鑰。

必要條件

如果您沒有 Azure 訂用帳戶,請在開始之前先建立 Azure 免費帳戶

登入 Azure

請使用您的 Azure 帳戶登入 Azure 入口網站 (https://portal.azure.com/)。

建立 Azure Web PubSub 服務執行個體

您的應用程式將會連線至 Azure 中的 Web PubSub 服務執行個體。

  1. 選取 Azure 入口網站左上角的 [新增] 按鈕。 在 [新增] 畫面的搜尋方塊中輸入 Web PubSub 並按 Enter。 (您也可以從 Web 類別搜尋 Azure Web PubSub。)

    在入口網站中搜尋 Azure Web PubSub 的螢幕擷取畫面。

  2. 從搜尋結果中選取 [Web PubSub],然後選取 [建立]

  3. 輸入下列設定。

    設定 建議的值 描述
    資源名稱 全域唯一的名稱 識別新 Web PubSub 服務執行個體的全域唯一名稱。 有效字元:a-zA-Z0-9-
    訂用帳戶 您的訂用帳戶 將在其下建立這個新 Web PubSub 服務執行個體的 Azure 訂用帳戶。
    資源群組 myResourceGroup 要在其中建立 Web PubSub 服務執行個體之新資源群組的名稱。
    地點 美國西部 選擇您附近的區域
    定價層 免費 您可以先免費試用 Azure Web PubSub 服務。 深入了解 Azure Web PubSub 服務定價層
    單位計數 - 單位計數會指出您的 Web PubSub 服務執行個體可接受的連線數目。 每個單位支援最多 1,000 個同時連線。 它只能在標準層中設定。

    在入口網站中建立 Azure Web PubSub 執行個體的螢幕擷取畫面。

  4. 選取 [建立] 以開始部署 Web PubSub 服務執行個體。

在本機建立及執行函式

  1. 請確定您已安裝 Azure Functions Core Tools。 現在,請為專案建立空的目錄。 在此工作目錄下執行命令。 使用下列其中一個指定選項。

    func init --worker-runtime javascript --model V4
    
  2. 請遵循步驟來安裝 Microsoft.Azure.WebJobs.Extensions.WebPubSub

    確認或將 host.json 的 extensionBundle 更新為 4.* 版或更新版本,以取得 Web PubSub 支援。 若要更新 host.json,請在編輯器中開啟檔案,然後將現有的版本 extensionBundle 取代為 4.* 版或更新版本。

    {
        "extensionBundle": {
            "id": "Microsoft.Azure.Functions.ExtensionBundle",
            "version": "[4.*, 5.0.0)"
        }
    }
    
  3. 建立 index 函式,以讀取和裝載用戶端的靜態網頁。

    func new -n index -t HttpTrigger
    
    • 更新 src/functions/index.js 並複製下列程式碼。
      const { app } = require('@azure/functions');
      const { readFile } = require('fs/promises');
      
      app.http('index', {
          methods: ['GET', 'POST'],
          authLevel: 'anonymous',
          handler: async (context) => {
              const content = await readFile('index.html', 'utf8', (err, data) => {
                  if (err) {
                      context.err(err)
                      return
                  }
              });
      
              return { 
                  status: 200,
                  headers: { 
                      'Content-Type': 'text/html'
                  }, 
                  body: content, 
              };
          }
      });
      
  4. 建立 negotiate 函式,協助用戶端使用存取權杖取得服務連線 URL。

    func new -n negotiate -t HttpTrigger
    
    • 更新 src/functions/negotiate.js 並複製下列程式碼。
      const { app, input } = require('@azure/functions');
      
      const connection = input.generic({
          type: 'webPubSubConnection',
          name: 'connection',
          hub: 'notification'
      });
      
      app.http('negotiate', {
          methods: ['GET', 'POST'],
          authLevel: 'anonymous',
          extraInputs: [connection],
          handler: async (request, context) => {
              return { body: JSON.stringify(context.extraInputs.get('connection')) };
          },
      });
      
  5. 使用 TimerTrigger 建立 notification 函式來產生通知。

    func new -n notification -t TimerTrigger
    
    • 更新 src/functions/notification.js 並複製下列程式碼。
      const { app, output } = require('@azure/functions');
      
      const wpsAction = output.generic({
          type: 'webPubSub',
          name: 'action',
          hub: 'notification'
      });
      
      app.timer('notification', {
          schedule: "*/10 * * * * *",
          extraOutputs: [wpsAction],
          handler: (myTimer, context) => {
              context.extraOutputs.set(wpsAction, {
                  actionName: 'sendToAll',
                  data: `[DateTime: ${new Date()}] Temperature: ${getValue(22, 1)}\xB0C, Humidity: ${getValue(40, 2)}%`,
                  dataType: 'text',
              });
          },
      });
      
      function getValue(baseNum, floatNum) {
          return (baseNum + 2 * floatNum * (Math.random() - 0.5)).toFixed(3);
      }
      
  6. 在專案根資料夾中新增用戶端單一頁面 index.html 並複製內容。

    <html>
        <body>
        <h1>Azure Web PubSub Notification</h1>
        <div id="messages"></div>
        <script>
            (async function () {
                let messages = document.querySelector('#messages');
                let res = await fetch(`${window.location.origin}/api/negotiate`);
                let url = await res.json();
                let ws = new WebSocket(url.url);
                ws.onopen = () => console.log('connected');
    
                ws.onmessage = event => {
                    let m = document.createElement('p');
                    m.innerText = event.data;
                    messages.appendChild(m);
                };
            })();
        </script>
        </body>
    </html>
    
  7. 設定及執行 Azure Function 應用程式

    原始 連接字串 只會出現在本文中,僅供示範之用。 在生產環境中,請一律保護您的存取金鑰。 使用 Azure 金鑰保存庫,安全地管理和輪替密鑰,並使用保護連線WebPubSubServiceClient

    • 在瀏覽器中,開啟 Azure 入口網站,並確認您稍早部署的 Web PubSub 服務執行個體已成功建立。 瀏覽至執行個體。
    • 選取 [金鑰] 並複製連接字串。

    複製 Web PubSub 連接字串 的螢幕快照。

    在函式資料夾中執行命令,以設定服務連接字串。 視需要使用您的值取代 <connection-string>

    func settings add WebPubSubConnectionString "<connection-string>"
    

    注意

    範例中使用的 TimerTrigger 函式相依於 Azure 儲存體,但您可以在函式於本機執行時使用本機儲存體模擬器。 如果您收到 There was an error performing a read operation on the Blob Storage Secret Repository. Please ensure the 'AzureWebJobsStorage' connection string is valid. 之類的錯誤,您必須下載並啟用儲存體模擬器

    現在您可以透過命令執行本機函式。

    func start --port 7071
    

    若要檢查正在執行的記錄,可以透過造訪 http://localhost:7071/api/index 頁面來造訪本機主機靜態頁面。

    注意

    某些瀏覽器會自動重新導向至 https ,導致 URL 錯誤。 建議使用 Edge,並在轉譯不成功時再次檢查 URL。

將函數應用程式部署至 Azure

若要將函式程式碼部署至 Azure,您必須先建立三個資源:

  • 資源群組,其為相關資源的邏輯容器。
  • 儲存體帳戶,用來維護函式的狀態和其他資訊。
  • 函數應用程式,其提供執行函式程式碼的環境。 函式應用程式可對應至您的本機函式專案,並可讓您將函式分組為邏輯單位,以便管理、部署和共用資源。

請使用下列命令來建立這些項目。

  1. 登入 Azure:

    az login
    
  2. 建立資源群組,或者您可以重複使用其中一個 Azure Web PubSub 服務來略過:

    az group create -n WebPubSubFunction -l <REGION>
    
  3. 在您的資源群組和區域中建立一般用途的儲存體帳戶:

    az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
    
  4. 在 Azure 中建立函式應用程式:

    az functionapp create --resource-group WebPubSubFunction --consumption-plan-location <REGION> --runtime node --runtime-version 18 --functions-version 4 --name <FUNCIONAPP_NAME> --storage-account <STORAGE_NAME>
    

    注意

    請參閱 Azure Functions 執行階段版本文件,將 --runtime-version 參數設定為支援的值。

  5. 將函式專案部署至 Azure

    在 Azure 中建立函數應用程式之後,您就可以開始使用 func azure functionapp publish 命令來部署本機函式專案。

    func azure functionapp publish <FUNCIONAPP_NAME> --publish-local-settings
    

    注意

    在這裡,我們會將本機設定 local.settings.json 與命令參數 --publish-local-settings 一起進行部署。 如果您使用 Microsoft Azure 儲存體模擬器,則您可以輸入 no 以略過在 Azure 上覆寫此值的提示訊息:App setting AzureWebJobsStorage is different between azure and local.settings.json, Would you like to overwrite value in azure? [yes/no/show]。 此外,您也可以在 Azure 入口網站 -> [設定] -> [組態] 中更新函數應用程式設定。

  6. 現在,您可以透過瀏覽至 URL,從 Azure 函數應用程式檢查您的網站: https://<FUNCIONAPP_NAME>.azurewebsites.net/api/index

清除資源

如果您不會繼續使用此應用程式,請使用下列步驟來刪除本文件所建立的全部資源,這樣才不會產生任何費用:

  1. 在 Azure 入口網站中選取最左側的 [資源群組],然後選取您所建立的資源群組。 使用搜尋方塊,改為依資源群組的名稱尋找。

  2. 在開啟的視窗中選取資源群組,然後選取 [刪除資源群組]

  3. 在新視窗中輸入要刪除的資源群組名稱,然後選取 [刪除]

下一步

在本快速入門中,您已了解如何執行無伺服器聊天應用程式。 現在,您可以開始建置自己的應用程式。