C# 学习者在这里。我希望这个问题有道理,但如果没有,请继续阅读!
我有一个现有的 Azure 函数设置 (.NET 6),当它接收到一个 http 触发器时,将触发一个协调器函数,该函数使用一个活动触发器来启动一个将所有消息从 Azure 存储队列复制到 Cosmos DB 的函数(下面的 QueueStore 函数)。我还想通过现有的 SignalR 服务和集线器(也在 Azure 中)使用 SignalR 将每条消息发送到客户端。
有很多关于创建 SignalR 和协商函数的文档,但是我如何从我已经调用的函数中发送消息?
复制功能的代码如下。我相信那些更有经验的开发人员会发现很多我可以优化的方法,但老实说,我很高兴让它在这个阶段工作。目前,该功能按预期和要求工作,但我想在代码的注释位置添加 SignalR 功能。
我怎样才能最好地解决这个问题?
[FunctionName(nameof(QueueStore))]
public static async Task<string> QueueStore([ActivityTrigger] QueueName queue, ILogger log)
{
// Get the connection string
string connectionString = Environment.GetEnvironmentVariable("QueueStorage");
try
{
CosmosClient client = new CosmosClient("some info here");
Database database = client.GetDatabase("database");
bool databaseExists = true;
try
{
var response = await database.ReadAsync();
}
catch (CosmosException ex)
{
if (ex.StatusCode.Equals(HttpStatusCode.NotFound))
{
// Does not exist
databaseExists = false;
}
}
//Instantiate a QueueClient which will be used to manipulate the queue
QueueClient queueClient = new QueueClient(connectionString, queue.Name);
QueueProperties properties = await queueClient.GetPropertiesAsync();
bool appDisconnected = false;
//string message = "Stored messages ";
if (queueClient.Exists() && databaseExists)
{
Container container = await database.CreateContainerIfNotExistsAsync(id: queue.Name,
partitionKeyPath: "/partKey", //name of the json var we want as partition key
throughput: 400
);
while (appDisconnected == false)
{
if (queueClient.GetProperties().Value.ApproximateMessagesCount == 0)
{
Thread.Sleep(100);
}
else
{
QueueMessage[] retrievedMessage = await queueClient.ReceiveMessagesAsync(1);
var fd = JsonConvert.DeserializeObject<JObject(retrievedMessage[0].Body.ToString());
if (!fd.ContainsKey("disconnected"))
{
PartitionKey partKey = new PartitionKey(queue.PartKey);
// save to db
var createdItem = await container.CreateItemAsync<JObject>(
item: fd,
partitionKey: partKey);
//######## HERE IS WHERE I WANT TO SEND THE fd Object via SignalR
//######## I have tried many different things but nothing works
await queueClient.DeleteMessageAsync(retrievedMessage[0].MessageId,
retrievedMessage[0].PopReceipt);
}
else
{
appDisconnected = true;
}
}
}
return "Copied all Items";
}
else
{
return $"The queue peek didn't work because I can't find the queue:-(";
}
}
catch (Exception ex)
{
return ex.Message;
}
}
我曾尝试从协调器调用 SignalR 函数,但这是在复制函数进程之外添加一个函数,这意味着将调用复制到队列中,并没有真正帮助。我还没有看到任何方法可以从代码中指示的位置发送 SignalR 消息。我也尝试过标准的 .Net SignalR 代码,但找不到对我有用的示例。任何指示和建议都会收到。
这能做到吗?我应该创建一个全新的功能应用程序并对其进行 http 调用吗?
试图制作我想要的版本给我带来了很多问题,并且没有找到任何关于它的文档,我可能在构建错误的东西但我想在重写所有内容之前我会在这里询问任何建议在这个应用程序上工作是有时间限制的。
提前感谢您的帮助!
我尝试添加一个示例 Azure SignalR Function,由协调器调用,也从代码的注释区域调用,我尝试了 .NET 文档和 SignalR Azure Functions 示例中的示例。我希望有这样的例子或我可以在某个地方学习的教程,但似乎我正在尝试做其他人没有做过的事情,这可能意味着我完全在咆哮错误的树...... :- (
非常感谢彼得让我三思而后行。
我过度复杂的事情。广播消息所需的全部是添加到代码的输出绑定(具有正确的集线器名称)、Azure Signalr 服务的连接字符串和 CLIENT 方法名称。
因为我有一个现有的 Web 应用程序作为中心,所以我在“默认”模式下使用了 Azure SignalR 服务。
添加行
[SignalR(HubName = "NameOfYourHub")]IAsyncCollector<SignalRMessage> signalRMessages
任何其他绑定(例如触发器绑定)。然后确保
"AzureSignalRConnectionString":"<your SignalR connection string>"
在“值”类别下的 local.settings.json 和/或 Azure 中的应用程序设置中。
最后,在我的例子中,因为我只是向客户广播,所以我添加了在指定位置处理和显示数据的客户端方法的名称:
signalRMessages.AddAsync(
new SignalRMessage
{
Target = "nameOfClientMethod",
Arguments = new [] { messageAsString }
});
我能够使用 Azure SignalR 服务的 LiveTrace 功能来确保所有客户端都连接到正确的集线器名称并跟踪发送到客户端的消息。我推荐它来解决 SignalR 问题。