.net下使用cap实现消息异步处理

news2025/1/19 3:00:29

介绍

github地址
CAP 是一个基于 .NET Standard 的 C# 库,它是一种处理分布式事务的解决方案,同样具有 EventBus 的功能,它具有轻量级、易使用、高性能等特点。

新建项目

新建.net7web项目
在这里插入图片描述

安装依赖包

在这里插入图片描述

安装软件

安装redis和Sql Server

修改代码

新建RedisConfigModel

namespace CAPStu01.Models;

public class RedisConfigModel
{
    /// <summary>
    /// 服务器地址
    /// </summary>
    public string Host { get; set; }

    /// <summary>
    /// 端口号
    /// </summary>
    public int Port { get; set; }

    /// <summary>
    /// 密码
    /// </summary>
    public string Pwd { get; set; }
}

修改appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "SQlServer": "server=127.0.0.1;User ID=sa;Password=xxxx;database=capstu;Encrypt=True;TrustServerCertificate=True;connection timeout=600;"
  },
  "RedisConfig": {
    "Host": "127.0.0.1",
    "Port": 6379,
    "Pwd": ""
  }
}

修改Program.cs

using CAPStu01.Models;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var redisConfig = builder.Configuration.GetSection("RedisConfig").Get<RedisConfigModel>();
var connectionStr = builder.Configuration.GetConnectionString("SQlServer") ?? "";
builder.Services.AddCap(x =>
{
    x.UseRedis(options =>
    {
        if (options.Configuration != null && redisConfig != null)
        {
            options.Configuration.EndPoints.Add(redisConfig.Host, redisConfig.Port);
            options.Configuration.Password = redisConfig?.Pwd ?? "";
        }
    });
    x.UseSqlServer(sqlServerOptions =>
    {
        sqlServerOptions.Schema = "dbo";
        sqlServerOptions.ConnectionString = connectionStr;
    });
    //开启面板
    x.UseDashboard(d =>
    {
        //允许匿名访问
        d.AllowAnonymousExplicit = true;
    });
});
var app = builder.Build();

app.UseRouting();
app.MapControllers();
app.Run();

新建HomeController

using DotNetCore.CAP;
using Microsoft.AspNetCore.Mvc;

namespace CAPStu01.Controllers;

[ApiController]
public class HomeController:ControllerBase
{
    public HomeController()
    {
        
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <returns></returns>
    [HttpGet("/")]
    public IActionResult Index([FromServices]ICapPublisher capBus)
    {
        capBus.Publish("test.show.time","你好,CAP");
        return Content("发送消息成功");
    }
    
    /// <summary>
    /// 接受消息
    /// </summary>
    /// <param name="data"></param>
    [NonAction]
    [CapSubscribe("test.show.time")]
    public void ReceiveMessage(string data)
    {
        Console.WriteLine("message data is:" + data);
    }
}

结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果使用redis需要定期清理streams内容

安装freeredis,修改Program.cs

builder.Services.AddSingleton<IRedisClient>(new RedisClient($"{redisConfig.Host}:{redisConfig.Port},password={redisConfig.Pwd},defaultDatabase=0"));

新增清除方法

private readonly IRedisClient _redisClient;

public HomeController(IRedisClient redisClient)
{
    _redisClient = redisClient;
}

/// <summary>
/// 清除已处理的redis数据
/// </summary>
/// <returns></returns>
[HttpGet("/clear")]
public IActionResult ClearAckStream()
{
    var groups = _redisClient.XInfoGroups("test.show.time");
    var unreandMsgs = new List<string>();
    //获取所有的未读消息
    foreach (var group in groups)
    {
        if (group.pending > 0)
        {
            //有未读消息
            var unReadList = _redisClient.XPending("test.show.time", group.name);
            if (unReadList.count > 0)
            {
                var groupInfo = _redisClient.XPending("test.show.time", group.name);
                var unreandList = _redisClient.XPending("test.show.time", group.name, groupInfo.minId, groupInfo.maxId,
                    groupInfo.count);
                foreach (var unre in unreandList)
                {
                    unreandMsgs.Add(unre.id);
                }
            }
        }
    }
    //获取全部的消息
    var allMsgs = _redisClient.XRange("test.show.time", "-", "+");
    foreach (var msg in allMsgs)
    {
        if (unreandMsgs.Contains(msg.id))
        {
            //这个消息未读则跳过
            continue;
        }
        //删除已处理的消息
        _redisClient.XDel("test.show.time", msg.id);
    }

    return Content($"共处理未读消息:{unreandMsgs.Count}个,已读消息{allMsgs.Length}个");
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1682360.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【免费Web系列】大家好 ,今天是Web课程的第一天点赞收藏关注,持续更新作品 !

开干,开干!!! 1. 前端开发介绍 我们介绍Web网站工作流程的时候提到&#xff0c;前端开发&#xff0c;主要的职责就是将数据以好看的样式呈现出来。说白了&#xff0c;就是开发网页程序&#xff0c;如下图所示&#xff1a; 那在讲解web前端开发之前&#xff0c;我们先需要对we…

如何加密电脑文件夹?重要文件夹怎么加密?

文件夹可以帮助我们管理电脑数据&#xff0c;而文件夹并不具有安全保护功能&#xff0c;很容易导致数据泄露。因此&#xff0c;我们需要加密保护电脑文件夹。那么&#xff0c;如何加密电脑文件夹呢&#xff1f;下面我们就来了解一下。 EFS加密 EFS加密是Windows提供的数据加密…

【2024】最新微信小程序商城源码开源版 多用户无限多开+15大功能模块

随着微信小程序市场的蓬勃发展&#xff0c;越来越多的商家和企业意识到了微信小程序作为线上销售平台的重要性。为了满足广大用户的需求&#xff0c;分享一款2024年最新微信小程序商城源码开源版&#xff0c;该版本不仅支持多用户无限多开&#xff0c;还集成了15大功能模块&…

Vue的学习 —— <vue事件处理>

前言 事件指的就是用户和网页交互的行为&#xff0c;这些行为&#xff0c;包括&#xff1a;鼠标单击、鼠标双击、键盘按下、抬起等。为了简化开发&#xff0c;Vue为开发者提供了事件修饰符&#xff0c;它可以与v-on配合使用&#xff0c;以便于对事件进行控制和处理&#xff0c…

单体测试Junit

本来是想要查找关于junit 的知识&#xff0c;查找了依赖注入方式不同对junit测试也有影响。 正好备注下。 依赖注入三种方式&#xff1a; 字段注入&#xff08;Autowird&#xff09; 优点&#xff1a; 操作简单 代码简洁 缺点&#xff1a; 不支持…

Java面试八股之HashMap和HashTable有什么区别

Java中HashMap和HashTable有什么区别 线程安全性&#xff1a; HashMap&#xff1a;非线程安全。在多线程环境下&#xff0c;如果没有采取适当的同步措施&#xff0c;直接并发访问可能会导致数据不一致、死锁等问题。如果需要在多线程环境中安全地使用HashMap&#xff0c;通常…

【FFmpeg】Filter 过滤器 ② ( 裁剪过滤器 Crop Filter | 裁剪过滤器语法 | 裁剪过滤器内置变量 | 裁剪过滤器常用用法 )

文章目录 一、裁剪过滤器1、裁剪过滤器简介2、裁剪过滤器语法3、裁剪过滤器内置变量4、裁剪过滤器示例5、裁剪过滤器应用6、裁剪过滤器图示 二、裁剪过滤器常用用法1、裁剪指定像素的视频区域2、裁剪视频区域中心正方形 - 默认裁剪3、裁剪视频区域中心正方形 - 手动计算4、裁剪…

STM32程序下载电路设计

一、背景介绍 使用STM32F103RCT6作为单片机主控芯片&#xff0c;在进行电路板设计过程中&#xff0c;需要预留程序下载接口&#xff0c;可以选择使用JLINK下载器下载程序。 二、设计过程 1、查看STM32F103RCT6的芯片手册&#xff0c;找到下载程序的引脚端口PA13和PA14&#x…

使用WPF中的Trigger实现按钮样式动态更改

使用WPF中的Trigger实现按钮样式动态更改 在Windows Presentation Foundation (WPF)中&#xff0c;Trigger 是一种强大的机制&#xff0c;它可以基于控件的属性值来动态更改控件的样式。这篇博客将介绍如何使用Trigger实现按钮在鼠标悬停时样式动态更改的效果。我们将详细讨论为…

自然语言处理通用框架BERT原理解读

相关代码见文末 1.概述 问题背景: 传统Seq2Seq模型的局限性: 早期的机器翻译和文本生成任务常采用基于循环神经网络(RNN)的序列到序列(Seq2Seq)模型,这类模型在处理长序列时容易遇到梯度消失/爆炸问题,导致训练效率低,难以捕捉长期依赖。 RNN网络的问题: RNN及其变…

基于vs和C#的WPF应用之动画4---跳跳球

一、画布和图形 <Canvas x:Name"canvas4" Grid.Row"1" Grid.Column"1" Width"200" Height"200"><Canvas.Triggers><EventTrigger RoutedEvent"Loaded"><BeginStoryboard Storyboard"…

牛客热题:合并二叉树

牛客热题&#xff1a;二叉树与双向链表> &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题…

TypeScript基础知识:TypeScript是什么?为什么会出现TypeScript?TypeScript相较于javascript有那些优势?

TypeScript(简称:TS)是JavaScript的超集(JS有的TS 都有)。 图解就是&#xff1a; TypeScriptType javaScript(在JS 基础之上&#xff0c;为JS 添加了类型支持)。 TypeScript 是微软开发的开源编程语言&#xff0c;可以在任何运行JavaScript的地方运行。 那么为什么要出现type…

CPT7数据保存详细步骤

一、连接设备、打开NovAtelConnect 软件 (1)点击1,并在2中输入如下命令: LOG RANGEB ONTIME 1 // 输出原始数据记录在板卡LOG RAWEPHEMB ONTIME 1 // 输出 GPS 原始星历记录在板卡LOG bdsephemerisb ONTIME 1 // 输出

VMware17.5与Ubuntu22.04虚拟机环境搭建

VMware17.5安装教程也有参考此链接 简介 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设…

一文读懂deepSpeed:深度学习训练的并行化

引言 在深度学习领域&#xff0c;模型训练的过程不仅资源密集&#xff0c;而且技术复杂。近年来&#xff0c;随着模型规模和数据量的不断增长&#xff0c;深度学习训练面临着越来越多的挑战。这些挑战主要体现在计算资源的需求、训练效率、模型复杂度以及内存管理等多个方面。…

32位处理的寻址方式

32位处理器兼容16位处理器的寻址方式&#xff0c;可以运行传统的16位代码。但是由于32位的处理器都拥有32位的寄存器和算数逻辑部件&#xff0c;而且同内存芯片之间的数据通路至少是32位的&#xff0c;因此&#xff0c;所有需要从寄存器或者内存地址处取得操作数的指令都被扩充…

直播卖券有妙招:实景ai无人直播系统帮助商家自动化团购直播!

在数字化浪潮席卷的今天&#xff0c;直播卖券已成为商家推广和营销的重要手段。然而&#xff0c;如何高效、精准地利用直播卖券&#xff0c;让每一位观众都能沉浸在购物的乐趣中&#xff0c;成为商家们迫切需要解决的问题。幸运的是&#xff0c;实景AI无人直播系统应运而生&…

升级GPT 4.0 会员,到底值不值?

对于这个问题&#xff0c;我的回答是&#xff1a;不太值得&#xff01;并不是4.0不好用&#xff0c;这价格稍微贵了点儿。 这么贵&#xff0c;这谁顶的住啊&#xff1f;好用是好用&#xff0c;但是没必要。 我的使用心得 我是怎么用的呢&#xff1f;我先用3.5版本问问题&…

使用 ONNX Runtime 在 iPhone 上运行 Phi-3-mini

更多科技分享&#xff0c;请关注公众号&#xff1a;ONE生产力 之前我们介绍了微软最新开源的小规模模型Phi-3-mini&#xff0c;其计算资源占用极少&#xff0c;非常适合嵌入式应用和移动智能终端。今天我们将探讨在iPhone上&#xff0c;通过ONNX Runtime运行Phi-3-mini模型。 …