在连接上调用InvokeAsync挂起。
我引用以下文档来配置Azure SignalR中的组连接。
注:
我只能在不依赖组配置的情况下建立连接。
客户端:
var negotiateJson = await _client.GetStringAsync($"{host}{"negotiatefn"}");
var negotiate = JsonConvert.DeserializeObject<NegotiateInfo>(negotiateJson);
var connection = new HubConnectionBuilder()
.AddNewtonsoftJsonProtocol()
.WithUrl(negotiate.Url, options => options.AccessTokenProvider = async () => negotiate.AccessToken)
.Build();
connection.Closed -= Connection_Closed;
connection.Closed += Connection_Closed;
connection.On<JObject>(hubMethodName, OnCourierUpdate);
await connection.StartAsync();
await connection.InvokeAsync("JoinGroup", sessionId); // HANGS APP HERE !!!
服务器:Azure功能
public static class LocationFn
{
[FunctionName(nameof(LocationFn))]
public static async Task<IActionResult> Run(
[HttpTrigger(
AuthorizationLevel.Anonymous,
"post",
Route = nameof(LocationFn))]
HttpRequest req,
[SignalR(HubName = "LocationHub")]
IAsyncCollector<SignalRMessage> signalRMessages,
ILogger log)
{
log.LogInformation($"{nameof(LocationFn)} has been invoked.");
try
{
using (var streamReader = new StreamReader(req.Body))
{
var json = await streamReader.ReadToEndAsync();
var subjectLocation = JsonConvert.DeserializeObject<SubjectLocation>(json);
await signalRMessages.AddAsync(
new SignalRMessage
{
Target = "LocationUpdate",
GroupName = subjectLocation.SessionId,
Arguments = new[] { subjectLocation }
});
var message = Log(log, subjectLocation);
return new OkObjectResult(message);
}
}
catch (Exception ex)
{
return new BadRequestObjectResult("There was an error: " + ex.Message);
}
}
}
public static class JoinGroupFn
{
[FunctionName(nameof(JoinGroupFn))]
public static async Task<IActionResult> Run(
[HttpTrigger(
AuthorizationLevel.Anonymous,
"post",
Route = nameof(JoinGroupFn))]
HttpRequest req,
[SignalR(HubName = "LocationHub")]
IAsyncCollector<SignalRMessage> signalRMessages,
ILogger log)
{
log.LogInformation($"{nameof(JoinGroupFn)} has been invoked.");
try
{
var groupId = await req.ReadAsStringAsync();
await signalRMessages.AddAsync(
new SignalRMessage
{
Target = "JoinGroup",
GroupName = groupId,
Arguments = new[] { groupId }
});
log.LogInformation($"{nameof(JoinGroupFn)} {groupId}");
return new OkObjectResult(groupId);
}
catch (Exception ex)
{
return new BadRequestObjectResult("There was an error: " + ex.Message);
}
}
}
服务器:集线器
type LocationHub() as x =
inherit Hub()
let this = (x :> Hub)
member x.LocationUpdate(v:SubjectLocation) =
async { do! this.Clients.Group(v.SessionId).SendAsync("LocationUpdate", v) |> Async.AwaitTask
} |> Async.StartAsTask
member x.JoinGroup(groupId:string) =
async { do! this.Groups.AddToGroupAsync(this.Context.ConnectionId, groupId) |> Async.AwaitTask
} |> Async.StartAsTask
我来自Azure SignalR团队,您的服务正在Serverless
模式下运行,它不允许任何服务器连接,您的F#集线器如何运行?
在客户端,connection.InvokeAsync
需要服务器ack,由于服务器连接无法连接,因此无法从服务中获得任何ack。
如果您需要集线器服务器,请将服务切换到Default
模式,然后使用Azure SignalR SDK运行集线器,并验证服务器是否已连接(通过服务指标中的日志或连接计数(。
如果您想要无服务器,请删除集线器,您可以在函数端添加无服务器集线器,请参阅:https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-concept-serverless-development-config#class-基于模型。并且不要忘记设置上游,请参阅:https://learn.microsoft.com/en-us/azure/azure-signalr/concept-upstream#rule-设置。