我目前正在测试我的应用程序的扩展,但遇到了一些我没有预料到的问题。
该应用程序在一个 5 节点集群上运行,它有多个服务/actortypes 并使用共享进程模型。对于某些组件,它使用 actor 事件作为尽力而为的 pubsub 系统(有回退,因此如果删除通知,则没有问题)。当参与者的数量增加(又名订阅主题)时,问题就会出现。目前,actorservice 被划分为 100 个分区。此时的主题数量约为 160.000,其中每个主题订阅了 1-5 次(需要它的节点),平均订阅量为 2.5 个(大约 40 万个订阅)。
那时集群中的通信开始中断,不会创建新订阅,取消订阅超时。但它也影响其他服务,对诊断服务的内部调用超时(询问 5 个副本中的每一个),这可能是由于分区/副本端点的解析,因为对网页的外部调用很好(这些端点使用相同的技术/代码堆栈)。
事件查看器充满了警告和错误,例如:
EventName: ReplicatorFaulted Category: Health EventInstanceId {c4b35124-4997-4de2-9e58-2359665f2fe7} PartitionId {a8b49c25-8a5f-442e-8284-9ebccc7be746} ReplicaId 132580461505725813 FaultType: Transient, Reason: Cancelling update epoch on secondary while waiting for dispatch queues to drain will result in an invalid state, ErrorCode: -2147017731
10.3.0.9:20034-10.3.0.13:62297 send failed at state Connected: 0x80072745
Error While Receiving Connect Reply : CannotConnect , Message : 4ba737e2-4733-4af9-82ab-73f2afd2793b:382722511 from Service 15a5fb45-3ed0-4aba-a54f-212587823cde-132580461224314284-8c2b070b-dbb7-4b78-9698-96e4f7fdcbfc
Run Code Online (Sandbox Code Playgroud)
我试过扩展应用程序,但没有激活此订阅模型,我很容易达到两倍大的工作负载,没有任何问题。
所以有几个问题
我正在创建一个可靠,有状态的服务演员.
题:
有没有办法在actor代理创建(ActorProxy.Create())期间传递初始化数据?基本上相当于我的演员的构造函数.
目前的想法:
我可以通过使用负责初始化状态的actor方法调用来跟进代理创建调用来实现这一点.
例如
//Danger, the following calls are not atomic
ITokenManager tokenActor = ActorProxy.Create<IMyActor>(actorId, "AppName");
//Something could happen here and leave my actor in an unknown state
await tokenActor.InitializeAsync(desiredInitialState);
Run Code Online (Sandbox Code Playgroud)
我对这种方法的关注:
有没有办法要求系统在启动时产生某些actor.
目前我Program.cs在演员注册后激活了我需要的演员集.
这工作正常,但我偶尔会得到一个,ReminderLoadInProgressException因为正在激活的演员需要注册一个提醒,但并非所有提醒都在尝试这样做时被加载.
是否有种子集群的标准方法?
我试图理解为什么我们的演员服务使用的磁盘空间比预期的多。我们的服务目前包含分布在 10 个分区上的大约 80,000 个参与者。每个参与者存储大约 150Kb 的状态。
查看我们集群中的一个(10 个)节点,我希望看到:
R_S_。这些副本 ID 与 Service Fabric Explorer 中“应用程序”节点下列出的任何值都不匹配。ActorStateStore,其大小为 5.66Gb 我试图理解的另一件事如下:
所以我的问题是:
azure-service-fabric service-fabric-stateful service-fabric-actor
我有一个使用WCF的Actor服务:
[assembly: WcfActorRemotingProvider(RemotingListener = RemotingListener.V2Listener, RemotingClient = RemotingClient.V2Client)]
namespace Player.Interfaces
{
/// <summary>
/// This interface defines the methods exposed by an actor.
/// Clients use this interface to interact with the actor that implements it.
/// </summary>
public interface IPlayer : IActor
{
Task<bool> JoinGameAsync(ActorId gameId, string playerName);
Task<bool> MakeMoveAsync(ActorId gameId, int x, int y);
}
}
Run Code Online (Sandbox Code Playgroud)
使用Service Remoting V2,我可以编写客户端代码并访问方法:
var player1 = ActorProxy.Create<IPlayer>(new ActorId("Player 1"), "fabric:/ActorWCFApplication");
Run Code Online (Sandbox Code Playgroud)
如何实现相同的使用WcfActorRemotingClientFactory或WCF?
var wcfRemotingClient = new WcfActorRemotingClientFactory(WcfUtility.CreateTcpClientBinding(), null,
servicePartitionResolver: partitionResolver);
Run Code Online (Sandbox Code Playgroud)
用于Actor的WCF客户端代码的任何代码片段?
当参与者服务启动时,我想自动订阅文档中描述的任何事件。手动订阅事件是有效的。但是,当实例化服务时,是否有一种方法可以自动订阅参与者服务,就像在 OnActivateAsync() 中一样?
我试图做的是通过依赖注入解决这个问题,在实例化 MyActor 类时,它传入一个接口,OnActivateAsync 调用该接口来为客户端订阅事件。但是我在依赖注入方面遇到了问题。
使用 Microsoft.ServiceFabric.Actors.2.2.207 应该支持对 Actor 服务的依赖项注入。现在,在实现 Microsoft.ServiceFabric.Actors.Runtime.Actor 时,会创建一个带有 ActorService 和 ActorId 参数的默认构造函数。
我想添加我自己的构造函数,该构造函数具有传入的附加接口。如何编写参与者服务的注册以添加依赖项?在默认的 Program.cs Main 中它提供了这个
IMyInjectedInterface myInjectedInterface = null;
// inject interface instance to the UserActor
ActorRuntime.RegisterActorAsync<MyActor>(
(context, actorType) => new ActorService(context, actorType, () => new MyActor(myInjectedInterface))).GetAwaiter().GetResult();
Run Code Online (Sandbox Code Playgroud)
但是,在显示“() => new MyActor(myInjectedInterface)”的行上,它告诉我一个错误
委托“Func”不接受 0 个参数
查看 Actor 类的构造函数,它具有以下内容
MyActor.Cs
internal class MyActor : Microsoft.ServiceFabric.Actors.Runtime.Actor, IMyActor
{
private ActorService _actorService;
private ActorId _actorId;
private IMyInjectedInterface _myInjectedInterface;
public SystemUserActor(IMyInjectedInterface myInjectedInterface, ActorService actorService = null, ActorId …Run Code Online (Sandbox Code Playgroud) c# dependency-injection azure-service-fabric service-fabric-actor
我的一个用例要求从单个事件产生器存储“开始”和“停止”事件之间的所有事件。我们将使用可靠的参与者来处理此数据,并在收到“停止”事件后进行汇总。在列表类型中,直接存储开始和停止之间的所有事件的简单方法。
// Init
var evts = new List<DataEvent>();
this.StateManager.TryAddStateAsync("events", evts);
// Fetch, add and save
var evts = this.StateManager.TryGetStateAsync<List<DataEvent>>("events");
evts.Add(newEvent);
this.StateManager.TrySaveStateAsync("events", evts);
Run Code Online (Sandbox Code Playgroud)
根据我的理解,每次获取现有列表时,添加一个新项目并存储新的更新列表,StateManager将序列化/反序列化整个数组。我的理解正确吗?
什么是该解决方案的好选择?
c# azure-service-fabric service-fabric-stateful service-fabric-actor
这有点描述性,所以请耐心等待。:)
在我尝试构建的应用程序中,产品具有不同的功能。用户可以选择加入功能 A、B、D 但不是 C。我构建这个的方式是,每个不同的功能都是一个服务(无状态,我正在考虑将数据存储在 Azure SQL 中数据库和从每个服务公开 REST API)。将所有服务捆绑在一起是一个 ApplicationType。对于创建的每个客户租户(将其视为一组用户的共享帐户),我正在考虑使用 TenantManagementService 创建注册 ApplicationType 的新具体实例并调用client.ApplicationManager.CreateApplicationAsync()在FabricClient实例,以便我可以在我的节点上为该租户运行一个专用的应用程序实例。但是,正如我所提到的,租户可以选择仅针对映射到服务子集的特定功能选择加入。如果租户仅选择我的应用程序的服务 A,则对应于功能 B、C、D 的其余服务实例不应在节点上空闲运行。
我想为每个服务创建参与者,但我创建的服务是无状态的,我希望它们的多个实例在多个节点上积极运行以平衡负载,而不是有状态服务的空闲副本。
与我对应用程序类型所做的类似,即在新租户注册时生成应用程序类型,我可以在租户想要选择加入/退出产品功能时生成/删除服务吗?
这是我尝试过的:InstanceCount在打包应用程序时,我尝试将服务设置为0。在我的ApplicationParametersXML 文件中:
<Parameters>
<Parameter Name="FeatureAService_InstanceCount" Value="0" />
<Parameter Name="FeatureBService_InstanceCount" Value="0" />
</Parameters>
Run Code Online (Sandbox Code Playgroud)
但是,Service Fabric Explorer 在从此类应用程序类型实例化应用程序时会出现问题。错误是这样的:

但另一方面,当一个服务部署在结构上时,它给了我一个专门删除它的选项,所以这个场景应该是有效的。

欢迎任何建议!
编辑:我的要求类似于这里的 anderso 提到的方法 - /sf/answers/2467384461/,但是,我特别想解决的问题是上传创建一个应用程序实例或更多具有零实例计数的打包服务!
azure azure-service-fabric service-fabric-actor service-fabric-stateless