使用 Azure 队列时 Web API 不启动

Posted

技术标签:

【中文标题】使用 Azure 队列时 Web API 不启动【英文标题】:Web API does not start when consume Azure queue 【发布时间】:2021-10-27 04:14:32 【问题描述】:

当我使用下面的代码时,Web API 没有启动,我没有看到 swagger 页面。你知道为什么吗?当我在 ConfigurationServices 中注释代码时,Swagger 正常启动。我想要正常的行为(意味着从控制器查看所有端点)+订阅队列的方法。

public class Startup

    static QueueClient queueClient;

    public void ConfigureServices(IServiceCollection services)
    
        try
        
            queueClient = new QueueClient("BusConnectionString","QueueName");
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            
                MaxConcurrentCalls = 1,
                AutoComplete = false
            ;
            queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        
        catch (Exception ex)
        
            Console.WriteLine(ex.Message);
        
        finally
        
            Console.ReadKey();
            queueClient.CloseAsync();
        
    

    static async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    
        Console.WriteLine($"Received message: Encoding.UTF8.GetString(message.Body)");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    

    static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    

在更新的代码下方,我每 5 秒点击一次 DoWork 方法,但在 ReceiveMessagesAsync 中没有收到任何消息,也不例外

更新 1:

public class TimedHostedService : IHostedService, IDisposable

    static QueueClient queueClient;

    Timer timer;

    readonly IConfiguration configuration;

    public TimedHostedService(IConfiguration configuration)
    
        this.configuration = configuration;
    

    public Task StartAsync(CancellationToken stoppingToken)
    
        timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    

    void DoWork(object state)
    
        try
        
            queueClient = new QueueClient("QueueConnectionString", "QueueName"]);
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            
                MaxConcurrentCalls = 1,
                AutoComplete = false
            ;
            queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        
        catch(Exception ex)
        
            Console.WriteLine(ex.Message);
        
        finally
        
            queueClient.CloseAsync();
        

    

    public Task StopAsync(CancellationToken stoppingToken)
    

        return Task.CompletedTask;
    

    public void Dispose()
    
        timer?.Dispose();
    

    static async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    
        Console.WriteLine($"Received message: Encoding.UTF8.GetString(message.Body)");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    

    static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    


【问题讨论】:

有什么例外吗?如果应用程序崩溃,就会发生这种情况。坦率地说,这里没有任何信息,所以只能猜测。也许 URL 是错误的。也许凭据是错误的。或者可能是应用程序阻塞。 这似乎是应该在托管服务中的代码,而不是在 ConfigureServices 中。 Grrrr 我删除了 Console.ReadKey(); Swagger 已启动,但是当我创建消息时,我在“ReceiveMessagesAsync”中没有收到任何内容 将队列代码移动到后台进程,见docs.microsoft.com/en-us/dotnet/architecture/microservices/… @PeterBons 方法 'ReceiveMessagesAsync' 不是 Azure 配置队列? 【参考方案1】:

您不应该在启动阶段进行长时间运行的工作。在启动阶段执行Console.ReadKey()的初始代码块。

应该在the background 中完成长时间运行的工作。但不要使用计时器,因为现在您会在每个滴答声上启动一个新的侦听器,然后几乎直接关闭它。试试这个:

public class QueueProcessorService : IHostedService

    private QueueClient queueClient;
    
    public Task StartAsync(CancellationToken cancellationToken)
    
        queueClient = new QueueClient("BusConnectionString", "QueueName");
        var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
        
            MaxConcurrentCalls = 1,
            AutoComplete = false
        ;
        queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        
        return Task.CompletedTask;
    

    public async Task StopAsync(CancellationToken cancellationToken)
    
        await queueClient.CloseAsync();
    

    async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    
        Console.WriteLine($"Received message: Encoding.UTF8.GetString(message.Body)");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    

    Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    

顺便说一句,您似乎使用的是相当过时的软件包Microsoft.Azure.ServiceBus,而不是推荐的软件包 (Azure.Messaging.ServiceBus)。

【讨论】:

当我在构造函数中作为上下文(当然在 startup.cs 中配置)传递时,我得到这个异常“ServiceType:Microsoft.Extensions.Hosting.IHostedService Lifetime:Singleton ImplementationType”我想我试过了在网上找到的所有解决方案:( 可以发一下Context的配置吗? 这里是:services.AddDbContext( options => options.UseSqlServer( Configuration.GetConnectionString("MyConnectionName"))); 事情是,它被注册为一个范围服务。我建议在this answer 点个赞

以上是关于使用 Azure 队列时 Web API 不启动的主要内容,如果未能解决你的问题,请参考以下文章

Azure - 使 API 应用程序可用于逻辑应用程序

在 web api 中接收服务总线消息队列/主题

通过 SendGrid 发送电子邮件时,Azure Web 应用程序是不是必须使用消息队列

将 ASP.NET Core 5 Web API 发布到 Azure 应用服务

Azure机器学习Web服务未使用Passed .learner模型

Azure WebJobs 在监控多个队列时如何对消息进行优先级排序?