因此,我有一个本地 API,可以写入 Azure 服务总线队列,该队列已经运行了几个月,没有出现任何问题。适当的防火墙条目已就位,并且所需的端口已打开。然而,我们最近发生了一次网络中断,导致我们的 API 无法写入队列,但 ServiceBusSender SendMessageAsync 没有抛出异常或以任何方式失败。我们最终在 App Insights 中发现了一个异常:“System.Net.WebSockets.WebSocketException (0x80004005): 无法连接到远程服务器”。
我们有一个非常标准的 Controller => Service => ServiceBusService 结构:
账户控制器:
public ActionResult<SuccessOkResponse> VerifyRedemption
(
[FromQuery, Required] string username,
[FromBody, Required] RedemptionVerificationRequest request
)
{
try
{
Service.VerifyRedemption(username, request, HttpContext.User.Identity?.Name);
return Ok(new SuccessOkResponse { Success = true });
}
catch (Exception exc)
{
ProblemDetails problemDetails;
var exceptionType = exc.GetType();
// etc.
}
}
账户服务:
public void VerifyRedemption
(
string username,
RedemptionVerificationRequest request,
string apiConsumerName
)
{
// Validation code etc.
// ...
if (AppSettings.ServiceBusRepayReinvest.ServiceBusEnabled)
{
// Write to service bus queue
ServiceBusService.SendMessage(redemptionRequest);
}
// update db etc.
// ...
}
服务巴士服务:
public async Task SendMessage(HoldingRedemptionRequest payload)
{
var clientOptions = new ServiceBusClientOptions()
{
TransportType = ServiceBusTransportType.AmqpWebSockets
};
var connectionString = _appSettings.ServiceBusRepayReinvest.ServiceBusRepayReinvestConnectionString;
queueName = _appSettings.ServiceBusRepayReinvest.ServiceBusRepayReinvestQueue;
await using var client = new ServiceBusClient(connectionString, clientOptions);
ServiceBusSender sender = client.CreateSender(queueName);
try
{
string messagePayload = JsonSerializer.Serialize(payload.RequestId);
ServiceBusMessage message = new ServiceBusMessage(messagePayload)
{
CorrelationId = payload.SSCorrelationId
};
await sender.SendMessageAsync(message).ConfigureAwait(false);
Logger?.LogInformation($"A message ({payload}) has been published to the queue.");
}
finally
{
// Calling DisposeAsync on client types is required to ensure that network
// resources and other unmanaged objects are properly cleaned up.
await sender.DisposeAsync();
await client.DisposeAsync();
}
}
为了复制这个问题,我在 Azure 中禁用了队列,当我在 VS 中本地运行代码时,代码正常运行 wait sender.SendMessageAsync(message).ConfigureAwait(false) 行,没有抛出异常,并完成其余部分的代码。我可以在 App Insights 中看到异常,但如果禁用队列,我预计代码会失败。
就异步等待而言,调用 sender.SendMessageAsync 的方式是否有问题,或者其他可能导致此问题的原因?
预先感谢。
您的代码中没有出现异常的原因是您在“即发即忘”模式下完成了发送。对异步方法的调用将比消息发送任务完成的速度更快地返回,控制器将完成其工作并在发送仍在进行时进行处理。根据各种因素,发送操作会随机成功或失败。
这是通过同步代码路径进行异步方法调用的典型问题。从
ServiceBusService.SendMessage()
调用时需要等待 VerifyRedemption()
。当从 AccountController
控制器调用时,需要等待后者。使控制器的 VerifyRedemption
为异步并等待调用来修复此问题。