你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
快速入门:通过 C# 使用 Azure Functions 和 SignalR 服务创建一个可显示 GitHub 星数的应用
在本文中,你会了解如何使用 C# 通过 SignalR 服务和 Azure Functions 生成一个无服务器应用程序,用于将消息广播到客户端。
重要
本文中出现的原始连接字符串仅用于演示目的。
连接字符串包括应用程序访问 Azure SignalR 服务所需的授权信息。 连接字符串中的访问密钥类似于服务的根密码。 在生产环境中,请始终保护访问密钥。 使用 Azure 密钥保管库安全地管理和轮换密钥,使用 Microsoft Entra ID 保护连接字符串,并使用 Microsoft Entra ID 授权访问。
避免将访问密钥分发给其他用户、对其进行硬编码或将其以纯文本形式保存在其他人可以访问的任何位置。 如果你认为访问密钥可能已泄露,请轮换密钥。
先决条件
本快速入门需要满足以下先决条件:
- Visual Studio Code 或其他代码编辑器。 如果尚未安装 Visual Studio Code,请在此处下载 Visual Studio Code。
- Azure 订阅。 如果还没有 Azure 订阅,可以在开始前创建一个免费帐户。
- Azure Functions Core Tools
- .NET Core SDK
创建 Azure SignalR 服务实例
在本部分中,你将创建一个基本 Azure SignalR 实例来用于你的应用。 以下步骤使用 Azure 门户创建新实例,但你也可以使用 Azure CLI。 有关详细信息,请参阅 Azure SignalR 服务 CLI 参考中的 az signalr create 命令。
- 登录 Azure 门户。
- 在页面的左上角,选择“+ 创建资源” 。
- 在“创建资源”页上,在“搜索服务和市场”文本框中,输入“signalr”,然后从列表中选择“SignalR 服务”。
- 在“SignalR 服务”页上,选择“创建”。
- 在“基本信息”选项卡上,输入新 SignalR 服务实例的基本信息。 输入以下值:
字段 | 建议的值 | 描述 |
---|---|---|
订阅 | 选择订阅 | 选择要用于创建新的 SignalR 服务实例的订阅。 |
资源组 | 创建一个名为 SignalRTestResources 的资源组 | 为 SignalR 资源选择或创建资源组。 对于本教程,创建新的资源组比使用现有资源组更为合适。 若要在完成本教程后释放资源,请删除资源组。 删除资源组还会删除属于该组的所有资源。 此操作不能撤消。 删除资源组之前,请确保它不包含你希望保留的资源。 有关详细信息,请参阅 Using resource groups to manage your Azure resources(使用资源组管理 Azure 资源)。 |
资源名称 | testsignalr | 输入用于 SignalR 资源的唯一资源名称。 如果你的区域中已使用了 testsignalr,请添加一个数字或字符,以将名称设为唯一。 该名称必须是包含 1 到 63 个字符的字符串,只能包含数字、字母和连字符 ( - ) 字符。 该名称的开头或末尾不能是连字符字符,并且连续的连字符字符无效。 |
区域 | 选择你的区域 | 为新的 SignalR 服务实例选择合适的区域。 Azure SignalR 服务当前并非在所有区域中都可用。 有关详细信息,请参阅 Azure SignalR 服务区域可用性。 |
定价层 | 选择“更改”,然后选择“免费(仅限开发/测试)”。 选择“选择”以确认你选择的定价层。 | Azure SignalR 服务有三个定价层:免费、标准和高级。 教程使用的是免费层,除非在先决条件中另行说明。 若要详细了解各个层级之间的功能差异以及定价,请参阅 Azure SignalR 服务定价 |
服务模式 | 选择适当的服务模式 | 在 Web 应用中托管 SignalR 中心逻辑并使用 SignalR 服务作为代理时,请使用“默认”。 使用无服务器技术(如 Azure Functions)托管 SignalR 中心逻辑时,请使用“无服务器”。 “经典”模式仅用于向后兼容,不建议使用。 有关详细信息,请参阅 Azure SignalR 服务中的服务模式。 |
对于 SignalR 教程,你不需要更改“网络”和“标记”选项卡上的设置。
- 选择“基本信息”选项卡底部的“查看 + 创建”按钮。
- 在“查看 + 创建”选项卡上检查各个值,然后选择“创建”。 部署需要几分钟时间才能完成。
- 在部署完成后,选择“转到资源组”按钮。
- 在 SignalR 资源页面上,从左侧菜单中选择“设置”下的“密钥”。
- 复制主密钥的连接字符串。 在本教程中,稍后你将需要使用此连接字符串来配置你的应用。
在本地安装和运行 Azure Functions
此步骤需要 Azure Functions Core Tools。
创建一个空目录并使用命令行更改到该目录。
初始化新项目。
使用代码编辑器创建名为 Function.cs 的新文件。 将以下代码添加到 Function.cs:
using System; using System.IO; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Extensions.SignalRService; using Newtonsoft.Json; namespace CSharp { public static class Function { private static HttpClient httpClient = new HttpClient(); private static string Etag = string.Empty; private static string StarCount = "0"; [FunctionName("index")] public static IActionResult GetHomePage([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, ExecutionContext context) { var path = Path.Combine(context.FunctionAppDirectory, "content", "index.html"); return new ContentResult { Content = File.ReadAllText(path), ContentType = "text/html", }; } [FunctionName("negotiate")] public static SignalRConnectionInfo Negotiate( [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req, [SignalRConnectionInfo(HubName = "serverless")] SignalRConnectionInfo connectionInfo) { return connectionInfo; } [FunctionName("broadcast")] public static async Task Broadcast([TimerTrigger("*/5 * * * * *")] TimerInfo myTimer, [SignalR(HubName = "serverless")] IAsyncCollector<SignalRMessage> signalRMessages) { var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/azure/azure-signalr"); request.Headers.UserAgent.ParseAdd("Serverless"); request.Headers.Add("If-None-Match", Etag); var response = await httpClient.SendAsync(request); if (response.Headers.Contains("Etag")) { Etag = response.Headers.GetValues("Etag").First(); } if (response.StatusCode == System.Net.HttpStatusCode.OK) { var result = JsonConvert.DeserializeObject<GitResult>(await response.Content.ReadAsStringAsync()); StarCount = result.StarCount; } await signalRMessages.AddAsync( new SignalRMessage { Target = "newMessage", Arguments = new[] { $"Current star count of https://github.com/Azure/azure-signalr is: {StarCount}" } }); } private class GitResult { [JsonRequired] [JsonProperty("stargazers_count")] public string StarCount { get; set; } } } }
Function.cs 中的代码有三个函数:
GetHomePage
用作客户端来获取网站。Negotiate
由客户端用于获取访问令牌。Broadcast
定期进行调用以从 GitHub 获取星数,然后向所有客户端广播消息。
本示例的客户端界面是网页。 我们通过从文件 content/index.html 读取 HTML 内容,使用
GetHomePage
函数呈现网页。 现在,让我们使用以下内容在content
子目录下创建此 index.html:<html> <body> <h1>Azure SignalR Serverless Sample</h1> <div id="messages"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script> <script> let messages = document.querySelector('#messages'); const apiBaseUrl = window.location.origin; const connection = new signalR.HubConnectionBuilder() .withUrl(apiBaseUrl + '/api') .configureLogging(signalR.LogLevel.Information) .build(); connection.on('newMessage', (message) => { document.getElementById("messages").innerHTML = message; }); connection.start() .catch(console.error); </script> </body> </html>
更新
*.csproj
以在生成输出文件夹中制作内容页面。<ItemGroup> <None Update="content/index.html"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
Azure Functions 需要一个存储帐户才能工作。 可以安装并运行 Azurite 存储模拟器。 或者,可以使用以下命令更新设置以使用实际存储帐户:
func settings add AzureWebJobsStorage "<storage-connection-string>"
现在即将完成了。 最后一步是将 SignalR 服务的连接字符串设置为 Azure Functions 设置。
通过在门户顶部的搜索框中搜索 SignalR 服务实例的名称,确认该实例已成功创建。 选择该实例以将其打开。
选择“密钥”以查看 SignalR 服务实例的连接字符串。
复制主连接字符串,然后运行以下命令。
本文中出现的原始连接字符串仅用于演示目的。 在生产环境中,请始终保护访问密钥。 使用 Azure 密钥保管库安全地管理和轮换密钥,使用 Microsoft Entra ID 保护连接字符串,并使用 Microsoft Entra ID 授权访问。
func settings add AzureSignalRConnectionString "<signalr-connection-string>"
在本地运行 Azure 函数:
func start
在本地运行 Azure 函数后,打开
http://localhost:7071/api/index
,你可以看到当前星数。 如果你在 GitHub 中添加了星标或取消添加了星标,星数会每隔几秒刷新一次。
清理资源
如果不打算继续使用此应用,请按照以下步骤删除本快速入门中创建的所有资源,以免产生任何费用:
在 Azure 门户的最左侧选择“资源组”,,然后选择创建的资源组。 或者,可以使用搜索框按名称查找资源组。
在打开的窗口中选择资源组,然后单击“删除资源组”。
在新窗口中键入要删除的资源组的名称,然后单击“删除”。
后续步骤
在本快速入门中,你在本地生成并运行了一个实时的无服务器应用程序。 接着,详细了解如何通过 Azure SignalR 服务在客户端与 Azure Functions 之间进行双向通信。