SignalR+Hangfire 实现后台任务队列和实时通讯

这篇具有很好参考价值的文章主要介绍了SignalR+Hangfire 实现后台任务队列和实时通讯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SignalR+Hangfire 实现后台任务队列和实时通讯

1.简介:

SignalR是一个.NET的开源框架,SignalR可使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式实现服务端和客户端的实时数据交互。

Hangfire是一个.NET的开源后台任务框架 提供统一的编程模型,以可靠的方式处理后台任务

2.目的:

通过SignalR+Hangfire,我们可以实现一些需要较长时间处理的任务,并在完成及时的通知前端处理结果。

3.以下是我使用SignalR+Hangfire的开发需求:

在net6 webapi的情况下,前端是vue+ts,我现在有个需要就是,我写了一个接口,是对接stable diffusion webui 文生图的接口,前端第一个人请求,返回图没有问题,
但是,此时在生成图的过程中,第二个人请求,我希望加入到一个队列或者别的方式 ,把这个请求放着,我处理完第一个请求之后继续处理第二个,并且告诉用户,前面有多少个任务需要等待?

我的开发环境,后端是.net7 前端vue3.0,下面是对应安装和使用教程:

1.Hangfire使用

1.安装nuget包

由于我使用的mysql,对应包为Hangfire.MySqlStorage,大家根据自己的数据库选择安装对应的包

<PackageReference Include="Hangfire" Version="1.8.2" />
<PackageReference Include="Hangfire.MySqlStorage" Version="2.0.3" />

2.添加Hangfire配置

Hangfire的数据是存在数据库中的,所以在添加配置时候要使用对应的数据库连接字符串。同时,在UseHangfireServer时,我使用了自定义的队列名称,并将同时执行的任务数设置为1,以实现任务队列中的任务唯一,且任务依次执行。

在program.cs中添加以下配置

1.添加Hangfire

代码内容:

var connectionString = configuration.GetValue<string>("ConnStr");//数据库连接配置
// Add Hangfire services.
services.AddHangfire(config =>
{
    config.UseStorage(new MySqlStorage(connectionString, new MySqlStorageOptions
    {
        TablesPrefix = "hangfire_", // 指定表前缀
        PrepareSchemaIfNecessary = true // 允许安装 MySQL 表格(如果不存在的话)
        // 其他存储选项
    }));
});

2.应用Hangfire

代码内容:

// Use Hangfire server and dashboard.
app.UseHangfireServer(new BackgroundJobServerOptions
{
    Queues = new[] { "default", "img-queue" },
    WorkerCount = 1
});
app.UseHangfireDashboard();// 使用 Hangfire 控制面板

3.数据库配置

配置完成,在使用时,数据库会生成Hangfire的工作表,如下:

4.Hangfire 控制面板

对应Hangfire 控制面板为 /hangfire

http://localhost:5122/hangfire

1.仪表盘

2.队列

5.代码中的应用

1.发起一个后台任务

//添加后台任务
BackgroundJob.Enqueue(() => BackServiceCreateImg(request));

2.后台任务方法

/// <summary>
/// 后台任务生成图片(DisableConcurrentExecution 设置超时时间 Queue设置任务类型)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[DisableConcurrentExecution(timeoutInSeconds: 180)]
[Queue("img-queue")]
public async Task BackServiceCreateImg(GraphGenerationRequest request)
{
    //...代码逻辑省略
}

3.查询队列等待任务数

var queueLength = JobStorage.Current.GetMonitoringApi()
                            .EnqueuedCount("img-queue");//指定的队列类型的队列等待任务数

2.SignalR使用

1.后端SignalR使用

由于我使用的.net7,微软自带SignalR,我们使用时只需要添加引用

using Microsoft.AspNetCore.SignalR;

1.添加SignalR配置

在program.cs中添加以下配置

1.添加SignalR

代码内容:

// SignalR
services.AddSignalR();

2.配置SignalR hub

代码内容:

// SignalR hub
app.MapHub<GraphGenerationHub>("/graphhub");

2.创建SignalR hub类

using Hangfire;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.SignalR;

namespace ChatGptWebApi.Hubs
{
    [EnableCors("MyPolicy")]
    public class GraphGenerationHub : Hub
    {

        public GraphGenerationHub()
        {
        }

        public long GetWaitingCount()
        {
            return  JobStorage.Current.GetMonitoringApi()
                .EnqueuedCount("img-queue");
        }
    }
}

3.代码中的应用

1.依赖注入

通过依赖注入,在要使用的类中注入

private readonly IHubContext<GraphGenerationHub> _hubContext;

4.发送消息

向全体发送

_hubContext.Clients.All.SendAsync("updateWaitingCount", "消息内容.....");

向指定客户端发送

_hubContext.Clients.Client(request.ConnectionId).SendAsync("updateImgUrl", $"生成图片失败:{ex.Message}");

2.前端SignalR使用

前端我用的是VUE+TS

1.安装SignalR包

通过命令使用 pnpm 安装 @microsoft/signalr

pnpm install @microsoft/signalr

2.页面中引用@microsoft/signalr

import * as signalR from "@microsoft/signalr";

3.创建一个useSignalR.ts

创建一个useSignalR.ts来专门处理SignalR消息,然后在需要用到的页面中引用即可。

代码内容:

import { onUnmounted, ref } from 'vue';
import { useMessage } from 'naive-ui'
import { HubConnectionBuilder, HubConnection } from '@microsoft/signalr';

export  function useSignalR(
  hubUrl: string,
  hubName: string
) {
  const connection = ref<HubConnection | null>(null);
  const waitingCount = ref(0);
  const imgUrl = ref([]);
  const ms = useMessage();
  const start = async () => {
    if (connection.value && connection.value.state === 'Connected') return;
    connection.value = getConnection(hubUrl);
    if (connection.value) {
     // 连接 SignalR
     connection.value.start()
     .then(() => {
       console.log('SignalR Connected.');
       // 调用 GraphGenerationHub 的 GetWaitingCount 方法获取队列等待数
       connection.value?.invoke('GetWaitingCount')
         .then(count => {
           console.log('Waiting Count:', count);
           waitingCount.value = count;
         });
       // 注册 signalR 接收方法
       connection.value?.on('updateWaitingCount', count => {
         console.log('Waiting Count:', count);
         waitingCount.value = count;
       });
       connection.value?.on('updateImgUrl', newImgUrl => {
        console.log('Waiting imgUrl:', newImgUrl);
        if(typeof newImgUrl === 'string'){
          ms.error(newImgUrl);
        }else{
          ms.success('图片生成成功。');
        imgUrl.value = newImgUrl;
        }
      });
     })
     .catch(error => {
       console.log('SignalR Connection Error:', error);
     });
    }
  };
  

  const stop = () => {
    connection.value!.stop();
    connection.value = null;
  };

  const getConnection = (
    hubUrl: string
  ): HubConnection => {
    return new HubConnectionBuilder()
      .withUrl(hubUrl)
      .withAutomaticReconnect().build();
  };

  start();

  onUnmounted(() => {
    if (connection.value?.state === 'Connected') connection.value!.stop();
  });

  return {
    connection,
    waitingCount,
    imgUrl,
    start,
    stop
  };
}

4.页面中的使用

在需要使用signalR的页面引用useSignalR

 import {useSignalR} from '@/views/chat/hooks/useSignalR';
setup() {
//signalR
const { waitingCount,connection,imgUrl } = useSignalR(apiBaseUrl+'/graphhub');
}

3.案例:SignalR+Hangfire+StableDiffusionAPI 生成图片

Hangfire实现后台调用StableDiffusion web接口,然后通过SignalR将结果返回给前端。这样,对StableDiffusion web的性能要求很低。不会因为生成图片慢,导致http请求超时的情况。大大改善了前后端交互。

1.前端建立SignalR

入上述页面中使用介绍的一样,当添加了

const { waitingCount,connection,imgUrl } = useSignalR(apiBaseUrl+'/graphhub');

打开对应页面时,就创建了SignalR的连接了。

2.前端发起请求

前端的提交按钮对应的方法,使用的是axios发送http请求生成图片。

代码如下:

const submit = async () => {
        const params = {
          Prompt: description.value,
          connectionId:connection.value?.connectionId //SignalR的客户端连接ID
        };
      try {
      //signalR
      const response = await axios.post(apiUrl+'/GenerateGraph', params);
      if(response.data.status ==='Fail'){
        ms.error(response.data.message ?? 'error')
      return
      }
      usedCount.value=response.data.data;
      ms.success(response.data.message);

    } catch (error) {
      ms.error('报错拉!:'+error);
    }
    console.log("提交的参数:", params); // 在控制台输出提交的参数
  };

3.后端接口和实现

后端接口和实现方法完成定时任务的发起和signalR的消息推送

后端接口如下:

/// <summary>
/// signalR+hangfire生成图片
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<int?>> GenerateGraph(GraphGenerationRequest request)
{
    var res=await _iGptImage.GenerateGraph(request);
    return res;
}

方法实现:

/// <summary>
/// 生成图片,返回队列信息和剩余次数
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ApiResult<int?>> GenerateGraph(Form.GraphGenerationRequest request)
{
    //添加后台任务
    BackgroundJob.Enqueue(() => BackServiceCreateImg(request));
    string message = await SendWaitingCount("img-queue");
    return new ApiResult<int?>(HttpResultTypeEnum.Success, count - 1, message);
}
 /// <summary>
/// 推送队列的等待信息
/// </summary>
/// <param name="enqueue">任务类型</param>
/// <returns></returns>
private async Task<string> SendWaitingCount(string enqueue)
{
    var queueLength = JobStorage.Current.GetMonitoringApi()
        .EnqueuedCount(enqueue);
    string message = $"任务已提交,您前面还有 {queueLength} 个任务正在等待。";
    await _hubContext.Clients.All.SendAsync("updateWaitingCount", queueLength);
    return message;
}

4.案例成果

案例地址(AI聊天+图片生成):https://ai.terramours.site/文章来源地址https://www.toymoban.com/news/detail-473751.html

阅读如遇样式问题,请前往个人博客浏览: https://www.raokun.top
拥抱ChatGPT:https://ai.terramours.site
开源项目地址:https://github.com/firstsaofan/TerraMours

到了这里,关于SignalR+Hangfire 实现后台任务队列和实时通讯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 构建实时通信应用:使用.NET和SignalR轻松实现前沿技术

      概述: 学习.NET中使用SignalR实现实时通信功能。从安装库、创建Hub,到客户端基础功能,一步步构建实时聊天室。深入讲解分组功能,使您能够定向广播消息。简洁实用,助您轻松掌握实现创新Web应用的技能。 SignalR 是一个强大的实时通信库,为.NET应用程序提供轻松的实时

    2024年02月04日
    浏览(43)
  • Redis的发布订阅模式:实现消息队列和实时数据推送的利器

    当涉及到实时数据推送和消息队列时,Redis的发布订阅模式是一种非常有用的工具。Redis是一个开源的内存数据库,被广泛用于缓存、队列和实时数据处理等方面。 在本博客中,我们将重点介绍Redis的发布订阅模式,并且提供一些示例代码来帮助读者更好地理解这个模式以及如

    2024年02月12日
    浏览(92)
  • SignalR WebSocket通讯机制

    1、什么是SignalR ASP.NET SignalR 是一个面向 ASP.NET 开发人员的库,可简化向应用程序添加实时 Web 功能的过程。 实时 Web 功能是让服务器代码在可用时立即将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。 SignalR使用的三种底层传输技术分别是Web Socket, Server

    2024年02月06日
    浏览(44)
  • 后端C# .net 前端uni-app 集成SignalR做即时通讯

            后端集成SignalR比较简单,首先要在解决方案中依赖几个SignalR的库,SignalR的库就是做即时通讯的主要库,我们建立连接、收发信息都需要用这个库来进行。         除了这几个库以外,还要还有几个依赖库要一并依赖进来。         Owin库的作用主要是为了在

    2024年04月17日
    浏览(41)
  • ASP.NET Core实时库SignalR简单应用

    SignalR 是用于构建需要实时用户交互或实时数据更新的Web 应用程序的一个开放源代码.NET 库。不仅仅用在Web应用中,后面会讲到它的应用范围。它简化了简化了构建实时应用程序的过程,包括 ASP.NET Server 库和 JavaScript Client 库,以便管理Client与Server连接并将内容更新推送给Cl

    2024年02月11日
    浏览(75)
  • 实时消息传送:WebSocket实现系统后台消息实时通知

    在现代Web应用中,提供实时通知对于改善用户体验至关重要。WebSocket技术允许建立双向通信通道,从系统后台将消息实时传送给系统用户,并在前端以弹窗的形式通知用户。本文将深入探讨如何使用WebSocket来实现这一功能。 WebSocket是一种双向通信协议,与传统的HTTP通信不同

    2024年02月08日
    浏览(45)
  • Mediapipe人体骨架检测和实时3d绘制——Mediapipe实时姿态估计

    大约两年前,基于自己的理解我曾写了几篇关于Mediapipe的文章,似乎帮助到了一些人。这两年,忙于比赛、实习、毕业、工作和考研。上篇文章已经是一年多前发的了。这段时间收到很多私信和评论,请原谅无法一一回复了。我将尝试在这篇文章里回答一些大家经常问到的问

    2024年02月03日
    浏览(53)
  • Go学习圣经:队列削峰+批量写入 超高并发原理和实操

    本文是《Go学习圣经》 的第二部分。 第一部分请参见:Go学习圣经:0基础精通GO开发与高并发架构(1) 现在 拿到offer超级难 ,甚至连面试电话,一个都搞不到。 尼恩的技术社群中(50+),很多小伙伴凭借 “左手云原生+右手大数据”的绝活,拿到了offer,并且是非常优质的

    2024年02月06日
    浏览(39)
  • Vue中利用websocket实现实时通讯

    目录 一、webSocket是什么? 二、WebSocket 原理 三、WebSocket 特点 四、WebSocket 应用场景 五、使用步骤 1.安装相关依赖 2.在Vue组件中创建WebSocket连接 3.向服务器发送消息 4.关闭WebSocket连接 总结         WebSocket 是一种基于 TCP 协议的全双工通信协议,它可以在单个 TCP 连接上实现

    2024年02月08日
    浏览(46)
  • SpringBoot+Vue整合WebSocket实现实时通讯

            在开发过程中,我们经常遇到需要对前台的列表数据,实现实时展示最新的几条数据,或者是调度的任务进度条实现实时的刷新......,而对于这种需求,无状态的http协议显然无法满足我们的需求,于是websocket协议应运而生。websocket协议本质上是一个基于tcp的协议

    2024年02月13日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包