SignalR.Orleans 7.2.0

dotnet add package SignalR.Orleans --version 7.2.0                
NuGet\Install-Package SignalR.Orleans -Version 7.2.0                
此命令旨在在 Visual Studio 的包管理器控制台中使用,因为它使用 NuGet 模块的 Install-Package 版本。
<PackageReference Include="SignalR.Orleans" Version="7.2.0" />                
对于支持 PackageReference 的项目,请将此 XML 节点复制到项目文件中以引用该包。
paket add SignalR.Orleans --version 7.2.0                
#r "nuget: SignalR.Orleans, 7.2.0"                
#r 指令可用于 F# Interactive 和 Polyglot Notebooks。将此复制到交互式工具或脚本的源代码中,以引用该包。
// Install SignalR.Orleans as a Cake Addin
#addin nuget:?package=SignalR.Orleans&version=7.2.0

// Install SignalR.Orleans as a Cake Tool
#tool nuget:?package=SignalR.Orleans&version=7.2.0                

Build Package Version NuGet Downloads License Discord

Orleans 是一个跨平台框架,用于构建强大、可扩展的分布式应用程序。分布式应用程序是指跨越多个进程的应用程序,通常通过点对点通信超越硬件边界。Orleans 可扩展从单个内部服务器到数百个甚至数千个在云中高度可用的分布式应用程序。 在 Github 上查看 Orleans 源代码

ASP.NET Core SignalR 是一个开源库,它简化了向应用程序添加实时 Web 功能。实时 Web 功能允许服务器端代码立即将内容推送到客户端。

SignalR.Orleans 是一个包,它给您两种能力

  1. 使用您的 Orleans 集群作为 SignalR 的后端。(了解如何在多个服务器上扩展 SignalR 的< a href="https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-7.0" rel="noopener noreferrer nofollow">知识)。

对于SignalR,您有多种可选的底版(backplane)可以选择,您可以在上面的链接中看到。如果您已经在使用Orleans,那么您可能会想使用Orleans作为底版来减少应用程序使用的依赖项数量,并减少调用外部服务时所需的网络跳跃(以及延迟)数量。

  1. 从Orleans颗粒向SignalR客户端发送消息。

如果您的应用程序中的SignalR组件与Orleans共同托管(同一服务器、同一进程,并且Microsoft.AspNetCore.SignalR.IHubContext<MyHub>可以注入到Orleans颗粒中),那么您已经具备这项功能,无需安装此包。

然而,如果应用程序中的SignalR组件与颗粒“远程”分离,此包将提供一种通过注入SignalR.Orleans.Core.HubContext<MyHub>的方式让颗粒向SignalR客户端发送消息。

TODO:这两个能力应该独立提供。遗憾的是,在这个阶段,能力 #2 只有在使用能力 #1 时才会提供。

安装

安装通过NuGet完成。

版本 7.x.x 的包与Orleans v7.x.x 及以上版本兼容。如果仍在使用早期版本的Orleans,则需要使用该包的早期版本。

包管理器

PS> Install-Package SignalR.Orleans

.Net CLI

# dotnet add package SignalR.Orleans

Paket

# paket add SignalR.Orleans


版本 7.0.0 文档

向下滚动以查看早期版本的文档。

以下是一个协同托管aspnetcore应用程序与SignalR和Orleans的完整入门示例。

using Microsoft.AspNetCore.SignalR;
using Orleans.Hosting;
using SignalR.Orleans;

// Create a host that can cohost aspnetcore AND orleans together in a single process.
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseOrleans(siloBuilder => 
{
    siloBuilder.UseLocalhostClustering();
    siloBuilder.UseSignalR(); // Adds ability #1 and #2 to Orleans.
    siloBuilder.RegisterHub<MyHub>(); // Required for each hub type if the backplane ability #1 is being used.
});

builder.Services
    .AddSignalR()  // Adds SignalR hubs to the web application
    .AddOrleans(); // Tells the SignalR hubs in the web application to use Orleans as a backplane (ability #1)

var app = builder.Build();
app.MapHub<MyHub>("/myhub");
await app.RunAsync();

// A SignalR Hub. https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-7.0
class MyHub : Hub
{
}

SILO配置 - 颗粒存储

SignalR.Orleans底板(能力 #1)底层使用颗粒,利用存储来追踪各个SignalR客户端的连接位置和所属的组。默认使用的存储是MemoryStorage

使用提供的存储名称常量来配置正确的存储提供程序。

// **************************************************************************
// Use memory storage ONLY when your app is not clustered, otherwise you'll
// need to use proper external storage providers
// **************************************************************************
          
// Customize the storage used by the SignalR Orleans backplane grains.
siloBuilder.AddSomeOtherGrainStorage(SignalROrleansConstants.SIGNALR_ORLEANS_STORAGE_PROVIDER);

// THEN
siloBuilder.UseSignalR();

SILO配置 - 流类型和流存储

SignalR.Orleans在底层使用流来提供底板(能力 #1)。默认流类型是MemoryStream。给定Orleans实例中的所有流都必须使用相同的存储提供程序,名称为PubSubStore,目前默认为MemoryStorage

// FIRST customize the storage used by ALL stream providers in the entire Orleans host:
// Remember, memory storage won't work if you're using a cluster.
siloBuilder.AddSomeOtherGrainStorage("PubSubStore");

// THEN customize the type of stream used for the backplane, using the correct stream provider name
siloBuilder.AddPersistentStreams(SignalROrleansConstants.SIGNALR_ORLEANS_STREAM_PROVIDER, adapterFactory, configureStream);

// THEN
siloBuilder.UseSignalR();

从Orleans颗粒发送消息

如果SignalR应用程序如上所述进行共同托管,您不需要此包从Orleans颗粒发送消息。只需将IHubContext<MyHub>注入到颗粒的构造函数中,并调用其方法来发送消息。了解更多信息。

然而,如果SignalR应用程序没有进行共同托管,并且如果它使用Orleans作为底板,则可以使用此包通过Orleans的底板流(作为导流),向SignalR客户端发送消息(能力 #2)。

class SampleGrain : Grain, ISampleGrain
{
  private readonly SignalR.Orleans.Core.HubContext<MyHub> _hubContext;

  public SampleGrain(SignalR.Orleans.Core.HubContext<MyHub> hubContext)
  {
    _hubContext = hubContext;
  }

  public async Task SendMessageToClients()
  {
    // Create an invocation message
    var msg = new InvocationMessage("method", new object?[]{ 1, 2, 3 }).ToImmutable();

    // Send a message to a single client
    await _hubContext.Client("someConnectionId").Send(msg);

    // Send a message to a group
    await _hubContext.Group("someGroupName").Send(msg);

    // Send a message to all connections made by a particular authenticated user
    await _hubContext.Group("someUserId").Send(msg);

    // TODO: We have not implemented ability to send a message to ALL clients yet.
  }
}

配置IClusterClient

如果SignalR应用程序与Orleans共同托管,它将自动从服务提供程序中获取一个IClusterClient并连接到Orleans底板。

但是,如果未共同托管,您需要提供一个可用的IClusterClient

using Microsoft.AspNetCore.SignalR;
using Orleans.Hosting;
using SignalR.Orleans;

// Create a web application that will connect to a remote Orleans cluster
var builder = WebApplication.CreateBuilder(args);
builder.Services
    // Adds an IClusterClient to the service provider.
    .AddOrleansClient(clientBuilder =>
    {
        // Tell the client how to connect to Orleans (you'll need to customize this for yourself)
        clientBuilder.UseLocalhostClustering();
        // Tells the client how to connect to the SignalR.Orleans backplane.
        clientBuilder.UseSignalR(configure: null);
    })
    .AddSignalR()  // Adds SignalR hubs to the web application
    .AddOrleans(); // Tells SignalR to use Orleans as a backplane (ability #1)

var app = builder.Build();
app.MapHub<MyHub>("/myhub");
await app.RunAsync();

// A SignalR Hub. https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-7.0
class MyHub : Hub
{
}

这是>= 7.0.0版本文档的结束。以下是最早版本的文档。


早期版本文档

配置Silo

我们需要使用以下方式配置Orleans Silo:

  • ISiloHostBuilder上使用.UseSignalR()
  • 请确保调用RegisterHub<THub>(),其中THub是您希望添加到底板中Hub的类型。

示例

var silo = new SiloHostBuilder()
  .UseSignalR()
  .RegisterHub<MyHub>() // You need to call this per `Hub` type.
  .AddMemoryGrainStorage("PubSubStore") // You can use any other storage provider as long as you have one registered as "PubSubStore".
  .Build();

await silo.StartAsync();

配置Silo存储提供程序和颗粒持久化

可选配置以覆盖默认实现,这两个提供程序默认设置为Memory

示例

.UseSignalR(cfg =>
{
  cfg.Configure((builder, config) =>
  {
      builder
          .AddMemoryGrainStorage(config.PubSubProvider)
          .AddMemoryGrainStorage(config.StorageProvider);
  });
})
.RegisterHub<MyHub>()

客户端

现在您的SignalR应用需要通过Orleans客户端连接到Orleans集群。

  • IClientBuilder上使用.UseSignalR()

示例

var client = new ClientBuilder()
  .UseSignalR()
  // optional: .ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(IClientGrain).Assembly).WithReferences())
  .Build();

await client.Connect();

在您的Startup.cs中某个地方

  • 将上面示例中创建的IClusterClient添加到IServiceCollection
  • IServiceCollection上使用.AddSignalR()(这是Microsoft.AspNetCore.SignalR NuGet包的一部分)。
  • .AddSignalR()上使用AddOrleans()

示例

public void ConfigureServices(IServiceCollection services)
{
  ...
  services
    .AddSingleton<IClusterClient>(client)
    .AddSignalR()
    .AddOrleans();
  ...
}

太棒了!现在您已配置了SignalR,并在Orleans中构建了Orleans SignalR后端。

特性

Hub上下文

HubContext让您能够从Orleans grain(Hub外部)与客户端通信。

示例用法:从消息代理、webhooks等接收服务器推送通知。理想情况下,首先更新grain状态,然后向客户端推送SignalR消息。

示例

public class UserNotificationGrain : Grain<UserNotificationState>, IUserNotificationGrain
{
  private HubContext<IUserNotificationHub> _hubContext;

  public override async Task OnActivateAsync()
  {
    _hubContext = GrainFactory.GetHub<IUserNotificationHub>();
    // some code...
    await _hubContext.User(this.GetPrimaryKeyString()).Send("Broadcast", State.UserNotification);
  }
}

完整示例

Cohosting aspnetcore网站和orleans

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Orleans;
using Orleans.Hosting;

// Cohosting aspnetcore website and Orleans with signalR
var host = Host.CreateDefaultBuilder(args)

  // Add the webhost with SignalR configured.
  .ConfigureWebHostDefaults(webBuilder =>
  {
    webBuilder.ConfigureServices((webBuilderContext, services) =>
    {
      // Add response compression used by the SignalR hubs.
      services.AddResponseCompression(opts =>
      {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
      });

      // Adds SignalR hubs to the aspnetcore website 
      services.AddSignalR(options =>
      {
      })
      .AddOrleans(); // Tells SignalR to use Orleans as the backplane.
    });

    webBuilder.Configure((ctx, app) =>
    {
      // Adds response compression for use by the SignalR hubs
      app.UseResponseCompression();
      
      // Map SignalR hub endpoints
      app.UseEndpoints(endpoints =>
      {
        endpoints.MapHub<MyHubType1>("/hub1"); // use your own hub types
        endpoints.MapHub<MyHubType2>("/hub2"); // use your own hub types
        // ... etc
      });
    });
  })

  // Add Orleans with SignalR configured
  .UseOrleans((context, siloBuilder) =>
  {
    siloBuilder
      .UseSignalR(signalRConfig =>
      {
        // Optional.
        signalRConfig.UseFireAndForgetDelivery = true;

        signalRConfig.Configure((siloBuilder, signalRConstants) =>
        {
          // **************************************************************************
          // Use memory storage ONLY when your app is not clustered, otherwise you'll
          // need to use proper external storage providers
          // **************************************************************************

          siloBuilder.AddMemoryGrainStorage(signalRConstants.StorageProvider);
          // This wouldn't be be necessary if you already added "PubSubStore" elsewhere.
          siloBuilder.AddMemoryGrainStorage(signalRConstants.PubSubProvider /*Same as "PubSubStore"*/);
        });
      })

      // Allows Orleans grains to inject IHubContext<HubType>
      .RegisterHub<MyHubType1>()
      .RegisterHub<MyHubType2>();
      // ... etc
  })
  .UseConsoleLifetime()
  .Build();

await host.StartAsync();
await host.WaitForShutdownAsync(default);

贡献

PR和建议非常受欢迎!

产品 兼容和额外的计算目标框架版本。
.NET net7.0兼容。 net7.0-android已计算。 net7.0-ios已计算。 net7.0-maccatalyst已计算。 net7.0-macos已计算。 net7.0-tvos已计算。 net7.0-windows已计算。 net8.0已计算。 net8.0-android已计算。 net8.0-browser已计算。 net8.0-ios已计算。 net8.0-maccatalyst已计算。 net8.0-macos已计算。 net8.0-tvos已计算。 net8.0-windows已计算。
兼容的目标框架
包中包含的目标框架
了解有关目标框架.NET标准的更多信息。

NuGet包

此包没有被任何NuGet包使用。

GitHub存储库

此包没有被任何流行的GitHub存储库使用。

版本 下载 最后更新
7.2.0 8,926 8/28/2023
7.1.0 9,262 2/15/2023
7.0.1 810 2/14/2023
2.2.1 6,314 1/19/2023
2.2.0 10,725 8/8/2022
2.1.0 19,560 10/5/2021
2.0.1 6,490 2/15/2021
1.5.0 20,507 11/1/2019
1.4.4 10,810 11/1/2019
1.4.3 7,483 9/23/2019
1.4.2 2,873 9/8/2019
1.4.0 3,985 7/8/2019
1.3.2 3,617 6/13/2019
1.3.1 1,580 6/10/2019
1.2.0 3,012 3/21/2019
1.1.2 1,424 2/25/2019
1.1.1 1,861 1/24/2019
1.0.6 3,866 10/12/2018
1.0.5 2,115 7/24/2018
1.0.4 1,479 7/24/2018
1.0.3 1,486 7/4/2018
1.0.2 1,643 7/4/2018
1.0.1 1,679 6/23/2018
1.0.0-preview-65 1,703 5/31/2018
1.0.0-preview-63 1,530 5/8/2018
1.0.0-preview-60 1,440 4/25/2018
1.0.0-preview-58 1,363 4/24/2018
1.0.0-preview-52 1,534 3/28/2018
1.0.0-preview-50 1,703 3/28/2018
1.0.0-preview-47 1,485 3/16/2018
1.0.0-preview-44 1,462 3/13/2018
1.0.0-preview-42 1,455 3/5/2018
1.0.0-preview-39 1,463 3/5/2018
1.0.0-preview-37 1,411 3/2/2018
1.0.0-preview-32 1,873 12/21/2017
1.0.0-preview-26 1,370 12/12/2017
1.0.0-preview-22 1,348 11/24/2017
1.0.0-preview-19 1,314 11/22/2017