分布式ASP.Net使用SignalR和Reids实现服务端与客户端通讯

        当使用ASP.NET和SignalR实现分布式应用程序时,可以结合Redis来实现服务端和客户端之间的通信。SignalR是一个强大的实时通信库,可帮助构建实时Web应用程序,而Redis则是一个高性能的键值存储数据库,也可以用作消息代理。

一、安装配置SignalR和Redis

        在ASP.NET应用程序中,使用NuGet包管理器安装SignalR和Redis相关的库。SignalR提供了在服务器和客户端之间建立实时连接的功能,而Redis则用于处理消息的传递和分发。

NuGet: Microsoft.AspNetCore.SignalR.StackExchangeRedis

1、配置Redis连接

在应用程序的appsettings.json文件中添加Redis连接配置。示例如下:

{
  "Redis": {
    "ConnectionString": "localhost:6379"
  }
}

2、配置SignalR服务

在Startup.cs或者Program.cs文件中添加SignalR服务配置。示例如下

builder.Services.AddSignalR().AddStackExchangeRedis(Configuration.GetConnectionString("Redis:ConnectionString"), options =>
{
    //添加一个通道前缀,使多个应用可以共享同一 Redis 实例
    options.Configuration.ChannelPrefix = "MyApp";
});
  • 如果为多个 SignalR 应用使用一个 Redis 服务器,请为每个 SignalR 应用使用不同的通道前缀。

    设置一个通道前缀会将一个 SignalR 应用与使用不同通道前缀的其他应用相隔开。 如果未分配不同的前缀,从一个应用发送到其所有客户端的消息则将转到所有将 Redis 服务器用作底板的应用的所有客户端。

 

3、配置SignalR后端端点

YourHub为自定义实现的Hub

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<YourHubClass>("/msghub"); // 这里指定你的 Hub 类型和终端点路径
});

二、创建一个SignalR的Hub类

此类继承自 SignalRHub。 Hub 类管理连接、组和消息,在该类中,可以定义方法,用于处理来自客户端的消息,并将其发送给指定的群组或者用户

using Microsoft.AspNetCore.SignalR;
using System.Net.WebSockets;

namespace YourNameSpace
{
    public class YourHubClass : Hub
    {
        /// <summary>
        /// 加入群组
        /// </summary>
        /// <param name="groupName"></param>
        /// <returns></returns>
        public async Task JoinGroup(string groupName)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
        }

        /// <summary>
        /// 退出群组
        /// </summary>
        /// <param name="groupName"></param>
        /// <returns></returns>
        public async Task LeaveGroup(string groupName)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
        }

        /// <summary>
        /// 给指定群组推送消息
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessageToGroup(string groupName, string message)
        {
            await Clients.Group(groupName).SendAsync("ReceiveMessage", message);

        }

        /// <summary>
        /// 给指定用户推送消息
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessage(string user, string message)
        {
            await Clients.Client(user).SendAsync("ReceiveMessage", user, message);
        }



        public override async Task OnConnectedAsync()
        {
            await base.OnConnectedAsync();

            // 在客户端连接成功后,你可以执行一些初始化操作
            var cid = Context.ConnectionId;

            //向指定用户发送消息
            await Clients.Client(cid).SendAsync("ReceiveMessage", "连接成功");
        }

        public override async Task OnDisconnectedAsync(Exception exception)
        {
            // 在客户端断开连接后,你可以执行一些清理操作
            // ...

            await base.OnDisconnectedAsync(exception);
        }
    }
}

三、实现控制器推送消息

此示例简单实现了推送指定群组和指定用户的接口

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;

namespace Demo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class YourController : ControllerBase
    {
        private readonly IHubContext<YourHubClass> _hubContext;

        public YourController (IHubContext<YourHubClass> hubContext)
        {
            _hubContext = hubContext;
        }

        [HttpPost("SendMessageToGroup")]
        public async Task<IActionResult> SendMessageToGroup([FromBody] MessageModel message)
        {
            await _hubContext.Clients.Group(message.GroupName).SendAsync("ReceiveMessage", message.Content);

            return Ok();
        }

        [HttpPost("SendMessageToUser")]
        public async Task<IActionResult> SendMessageToUser([FromBody] User message)
        {
            await _hubContext.Clients.Client(message.user).SendAsync("ReceiveMessage",message.Content);

            return Ok();
        }

        public class MessageModel
        {
            public string GroupName { get; set; }
            public string Content { get; set; }
        }

        public class User
        {
            public string user { get; set; }
            public string Content { get; set; }
        }
    }

}

四、客户端连接SignalR

此示例为vue3,简单实现了加入群组并接收消息的功能。注意跨域问题,跨域的处理方法,微软官方文档也十分详细,这里不再展开。

需要导入@microsoft/signalr包

pnpm i @microsoft/signalr

<template></template>

<script setup lang="ts">
import * as signalR from "@microsoft/signalr";

const connection = new signalR.HubConnectionBuilder()
  .withUrl("http://localhost:5234/msghub")//跨域需要使用绝对地址
  .build();
connection
  .start()
  .then((msg) => {
    console.log(msg);
    // 连接成功
    connection.invoke("JoinGroup", "dse").catch(function (err) {
      console.error(err);
    });
  })
  .catch(function (err) {
    console.error(err);
  });

// 接收消息
connection.on("ReceiveMessage", function (message) {
  console.log("Received message: " + message);
});

// 发送消息
// function sendMessageToGroup(message) {
//   connection
//     .invoke("SendMessageToGroup", groupName, message)
//     .catch(function (err) {
//       console.error(err);
//     });
// }
</script>

<style scoped></style>

官网文档:ASP.NET Core SignalR 概述 | Microsoft Learn

设置 Redis 底板以实现 ASP.NET Core SignalR 横向扩展

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值