你如何在 service fabric (azure) 中注册一个监听器

How do you register a listener in service fabric (azure)

我正在服务结构中编写一个可靠的参与者,他的工作是监听 Firebase DB and run logic based on those changes. I have it functioning, but not correctly. What I've done so far is write the actor code with a method called MonitorRules() which is what is listening to Firebase using a C# Firebase client wrapper called FireSharp 中的变化。 MonitorRules() 看起来像这样:

public async Task MonitorRules()
{
    FireSharp.FirebaseClient client = new FireSharp.FirebaseClient(new FireSharp.Config.FirebaseConfig
    {
        AuthSecret = "My5up3rS3cr3tAu7h53cr37",
        BasePath = "https://myapp.firebaseio.com/"
    });

    await client.OnAsync("businessRules",
        added: (sender, args) =>
        {
            ActorEventSource.Current.ActorMessage(this, $"{args.Data} added at {args.Path}");
        },
        changed: (sender, args) =>
        {
            ActorEventSource.Current.ActorMessage(this, $"{args.OldData} changed to {args.Data} at {args.Path}");
        }
    );            
}

然后我在服务注册后调用 MonitorRules(),就像在服务的 Main() 方法中一样:

fabricRuntime.RegisterActor<RuleMonitor>();
var serviceUri = new Uri("fabric:/MyApp.RuleEngine/RuleMonitorActorService");
var actorId = ActorId.NewId();
var ruleMonitor = ActorProxy.Create<IRuleMonitor>(actorId, serviceUri);

ruleMonitor.MonitorRules();

这 "works" 在于该服务打开与 Firebase 的连接并响应数据更改。问题在于,由于该服务在五节点集群的三个节点上 运行,它实际上监听了三次并处理了每条消息三次。另外,如果有一段时间没有 activity,该服务将被停用,不再响应 Firebase 中的更改。总而言之,我敢肯定,这不是设置此类内容的正确方法,但我找不到任何有关如何在服务结构中设置此类轮询客户端的文档。有没有一种方法可以按照 Azure Service Fabric 的精神进行设置?

是的,这里有几件事你需要熟悉一下。第一个是Actor lifecycle and garbage collection。 Tl;dr:如果 Actor 在一段时间内没有收到客户端请求(通过 ActorProxy)或提醒,则 Actor 将被停用,这是可配置的。

其次,Actor 有 Timers and Reminders 可用于执行周期性工作,例如轮询数据库以获取更改。计时器和提醒之间的区别是计时器不计为 "being used",这意味着 actor 仍然可以停用从而关闭计时器,但提醒计为 "being used" 并且也可以 re-activate 一个停用的演员。考虑计时器和提醒的方式是,您正在进行轮询,而不是像您在此处使用 FireSharp 那样等待来自其他东西的回调。

最后,从 Main() 调用 MonitorRules 并不是最好的主意。原因是 Main() 实际上是您的 actor 服务 主机进程的入口点, 它只是一个用于托管您的 actor 实例的 EXE。在 Main() 中应该发生的 only 事情是注册你的 actor 类型,没有别的。让我们更详细地看看这里发生了什么:

因此,您将 actor 服务部署到集群。发生的第一件事是我们在 运行 actor 服务所需的尽可能多的节点上启动主机进程(在您的情况下为 3)。我们进入注册演员服务类型的 Main() ,这就是我们 应该 做的所有事情,因为一旦演员服务注册到主机进程,我们就会创建服务的一个实例(或多个实例或副本,如果它是有状态的),然后服务可以开始工作。对于参与者,这意味着当客户端应用程序使用 ActorProxy 进行调用时,参与者服务已准备好开始激活参与者。但是对于 Main() 中的 ActorProxy 调用,您基本上是在说 "activate an actor on every node where this host is when the host starts",这就是您要听三次的原因。

考虑到所有这些,要问自己的第一个问题是演员是否适合您。如果您只是想要一个简单的地方来使用 FireSharp 客户端监控 Firebase,那么使用 reliable service 可能会更容易,因为您可以将监控放在 RunAsync 中,它在服务启动时自动启动,不像 actor 需要一个客户端来激活它们。