我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户。对我来说,只要能获得用户的认可,就是我最大的动力。
最近客服系统成功经受住了客户现场组织的压力测试,获得了客户的认可。
客户组织多名客服上线后,所有员工同一时间打开访客页面疯狂不停的给在线客服发消息,系统稳定无异常无掉线,客服回复消息正常。消息实时到达无任何延迟。
https://kf.shengxunwei.com/
我会通过一系列的文章详细分析升讯威在线客服系统的并发高性能技术是如何实现的,使用了哪些方案以及具体的做法。
本篇介绍超强的 SignalR 技术。
ASP.NET Core SignalR 是一个开放源代码库,可用于简化向应用添加实时 Web 功能。 实时 Web 功能使服务器端代码能够将内容推送到客户端。
适合 SignalR 的候选项:
以下是 ASP.NET Core SignalR 的一些功能:
SignalR 支持以下用于处理实时通信的技术(按正常回退的顺序):
SignalR 自动选择服务器和客户端能力范围内的最佳传输方法。
SignalR 使用中心在客户端和服务器之间进行通信。
Hub 是一种高级管道,允许客户端和服务器相互调用方法。 SignalR 自动处理跨计算机边界的调度,并允许客户端调用服务器上的方法,反之亦然。 可以将强类型参数传递给方法,从而支持模型绑定。 SignalR 提供两种内置中心协议:基于 JSON 的文本协议和基于 MessagePack 的二进制协议。 与 JSON 相比,MessagePack 通常会创建更小的消息。 旧版浏览器必须支持 XHR 级别 2 才能提供 MessagePack 协议支持。
中心通过发送包含客户端方法的名称和参数的消息来调用客户端代码。 作为方法参数发送的对象使用配置的协议进行反序列化。 客户端尝试将名称与客户端代码中的方法匹配。 当客户端找到匹配项时,它会调用该方法并将反序列化的参数数据传递给它。
中心是一个类,用作处理客户端 - 服务器通信的高级管道。
在 SignalRChat 项目文件夹中,创建 Hubs 文件夹。
在 Hubs 文件夹中,使用以下代码创建 ChatHub 类:
using Microsoft.AspNetCore.SignalR;
namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
ChatHub 类继承自 SignalRHub。 Hub 类管理连接、组和消息。
可通过已连接客户端调用 SendMessage,以向所有客户端发送消息。 本教程后面部分将显示调用该方法的 JavaScript 客户端代码。 SignalR 代码是异步模式,可提供最大的可伸缩性。
必须将 SignalR 服务器配置为将 SignalR 请求传递给 SignalR。 将以下突出显示的代码添加到 Program.cs 文件。
using SignalRChat.Hubs;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapHub<ChatHub>("/chatHub");
app.Run();
以上突出显示的代码将 SignalR 添加到 ASP.NET Core 依赖关系注入和路由系统。
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//Disable the send button until connection is established.
document.getElementById("sendButton").disabled = true;
connection.on("ReceiveMessage", function (user, message) {
var li = document.createElement("li");
document.getElementById("messagesList").appendChild(li);
// We can assign user-supplied strings to an element's textContent because it
// is not interpreted as markup. If you're assigning in any other way, you
// should be aware of possible script injection concerns.
li.textContent = `${user} says ${message}`;
});
connection.start().then(function () {
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});
document.getElementById("sendButton").addEventListener("click", function (event) {
var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
当从 Hub 类外部调用客户端方法时,没有与该调用关联的调用方。 因此,无法访问 ConnectionId、Caller 和 Others 属性。
需要将用户映射到连接 ID 并保留该映射的应用可以执行以下操作之一:
从 Web 主机访问 IHubContext 对于与 ASP.NET Core 之外的区域集成很有用,例如,使用第三方依赖项注入框架:
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var hubContext = host.Services.GetService(typeof(IHubContext<ChatHub>));
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup<Startup>();
});
}
SignalR 中的单个用户可以与一个应用建立多个连接。 例如,用户可以在桌面和手机上进行连接。 每台设备都有一个单独的 SignalR 连接,但它们都与同一个用户关联。 如果向用户发送消息,则与该用户关联的所有连接都会收到消息。 可以通过中心内的 Context.UserIdentifier 属性访问连接的用户标识符。
默认情况下,SignalR 使用与连接关联的 ClaimsPrincipal 中的 ClaimTypes.NameIdentifier 作为用户标识符。 若要自定义此行为,请参阅使用声明自定义标识处理。
重新连接时不会保留组成员身份。 重新建立连接后,需要重新加入组。 无法计算组的成员数,因为如果将应用程序扩展到多台服务器,则无法获取此信息。
若要在使用组时保护对资源的访问,请使用 ASP.NET Core 中的身份验证和授权功能。 如果仅当凭据对组有效时才将用户添加到该组,则发送到该组的消息将仅发送给授权用户。 但是,组不是一项安全功能。 身份验证声明具有组不具备的功能,例如到期和撤销。 如果撤销用户对组的访问权限,应用必须从组中显式删除该用户。
升讯威在线客服与营销系统是一款客服软件,但更重要的是一款营销利器。
https://kf.shengxunwei.com/