Akka.net日记阅读器缺少事件

时间:2018-08-30 08:38:09

标签: c# akka.net akka.net-persistence akka.net-streams

在我们的应用程序中,我们使用Akka.net和事件源。持久性参与者将其事件保存在SQL Server数据库中。 我们还有视图参与者,这些参与者使用日记阅读器/持久性查询来订阅这些事件,以创建实例化视图。我们在数据库中有一个表,每个视图参与者都有一行。该行包含视图参与者的名称和上次处理的事件的偏移量。 乍一看,这工作顺利。但是有时候,当我们运行导致数千个事件的测试时,期刊阅读器会丢失一些事件。

视图参与者是ReceiveActor。启动后,它将从数据库中检索上次处理的事件偏移量(从actor的构造函数中调用)。偏移量通过OffsetMessage通过管道传递给self。 接收到OffsetMessage时,视图参与者会初始化日记阅读器。在接收事件时(在EventEnvelope消息中),视图将更新。

从日志阅读器运行的操作首先在日志中写入一行。该行包含事件偏移量。 EventEnvelope接收处理程序还会在日志中写入一行。该行还包含事件偏移量。

我们进行了一项测试,结果将9635事件插入到日志中。有时日志阅读器和EventEnvelope接收处理程序记录的事件少于9635个。 它们都记录了相同的数字,因此看来期刊读者错过了这些事件。日志中丢失的事件与视图中的丢失项相对应。 我们在一个空的数据库上运行测试。日志记录处于调试级别,并且不显示异常。丢失的事件(我们看到的数字为1到4)可以在第一个,中间或最后一个事件中。每次都不一样。

到目前为止,我们不知道是什么导致了此问题,或者如何解决该问题。

以下是我们代码的片段。视图参与者都继承自基类:ViewActorBase。

internal abstract class ViewActorBase : ReceiveActor, ILogReceive
{
    public ViewActorBase()
    {
        // Some initialisation code
        ....

        this.Receive<OffsetMessage>(this.HandleOffsetMessage);
        this.ReceiveAsync<EventEnvelope>(this.UpdateState);

        var sender = this.Sender;
        var self = this.Self;
        this.GetViewActorOffset(self, sender);
    }

    private void HandleOffsetMessage(OffsetMessage offsetMessage)
    {
        this.InitialiseJournalReader(offsetMessage.Offset);
    }

    private void InitialiseJournalReader(long offset)
    {
        // obtain read journal by plugin id
        var readJournal = PersistenceQuery.Get(Context.System).ReadJournalFor<SqlReadJournal>($"akka.persistence.query");

        // materialize stream, consuming events
        var materializer = ActorMaterializer.Create(Context.System);

        // issue query to journal
        Source<EventEnvelope, NotUsed> source = readJournal.EventsByTag(this.QueryEventTag, new Sequence(offset));

        var self = this.Self;
        source.RunForeach(envelope => { this.Logger.Debug("{Date:HH:mm:ss.fffff} JournalReader.Tell {Offset}", DateTime.Now, (envelope.Offset as Sequence).Value); self.Tell(envelope); }, materializer);
    }

    private void GetViewActorOffset(IActorRef self, IActorRef sender)
    {
        // Initialise repository
        ....

        repository.GetViewActorOffset(this.GetViewName()).PipeTo(self, sender, offset => new OffsetMessage(offset));
    }
}

internal class MyViewActor : ViewActorBase
{
    protected override async Task UpdateState(EventEnvelope envelope)
    {
        var offset = (envelope.Offset as Sequence).Value;

        this.Logger.Debug("{Date:HH:mm:ss.fffff} {MethodName} {Offset}", DateTime.Now, $"{this.GetType().Name}.UpdateState", offset);

        // Update views
        ....
    }
}

我们的代码或体系结构中有问题吗?有更好的解决方案吗?

其他信息 我们已经使用SQL Server事件探查器运行了一些测试,以监视对数据库的查询。

在事件日志上执行了一个查询,要求100个事件,从偏移204743开始。结果包含61行。

<Event id="10" name="RPC:Completed">
  <Column id="1" name="TextData">exec sp_executesql N'
        SELECT TOP (@Take)
        e.PersistenceId as PersistenceId, 
        e.SequenceNr as SequenceNr, 
        e.Timestamp as Timestamp, 
        e.IsDeleted as IsDeleted, 
        e.Manifest as Manifest, 
        e.Payload as Payload,
        e.SerializerId as SerializerId,
        e.Ordering as Ordering
        FROM dbo.EventJournal e
        WHERE e.Ordering &gt; @Ordering AND e.Tags LIKE @Tag
        ORDER BY Ordering ASC
        ',N'@Tag nvarchar(10),@Ordering bigint,@Take bigint',@Tag=N'%;Module;%',@Ordering=204743,@Take=100</Column>
  <Column id="9" name="ClientProcessID">1169425116</Column>
  <Column id="10" name="ApplicationName">Core .Net SqlClient Data Provider</Column>
  <Column id="12" name="SPID">82</Column>
  <Column id="13" name="Duration">353890</Column>
  <Column id="14" name="StartTime">2018-08-30T16:32:32.927+02:00</Column>
  <Column id="15" name="EndTime">2018-08-30T16:32:33.28+02:00</Column>
  <Column id="16" name="Reads">326</Column>
  <Column id="17" name="Writes">0</Column>
  <Column id="18" name="CPU">0</Column>
  <Column id="48" name="RowCounts">61</Column>
</Event>

我们扩展了下一个查询,以204804(204743 + 61)开始。但是,它始于204810。为什么它跳过(或丢失)了6个事件?

0 个答案:

没有答案