如何从数据库中轮询缓慢移动的数据以用作StreamInsight参考流?

时间:2015-01-11 07:35:42

标签: streaminsight

如何定期轮询相对静态源(如数据库)在Microsoft StreamInsight中创建引用流?

这是我尝试过的。我将用户元数据数据库表示为一个简单的List<UserMetaData>

var referenceData = new List<UserMetaData>()
    {
        new UserMetaData() { UserId = 1, Name = "Fred Jones", Location = "Seattle" },
        new UserMetaData() { UserId = 2, Name = "Bob Murphy", Location = "Portland" }
    };

这是UserMetaData类

public class UserMetaData
{
    public int UserId { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }

    public override string ToString()
    {
        return string.Format(
            "Name: {0}, ID: {1}, Location: {2}",
            this.Name,
            this.UserId,
            this.Location);
    }
}

其余的示例代码替换了标准StreamInsight嵌入式部署设置中的省略号。

using (var server = Server.Create("default"))
{
    var app = server.CreateApplication("app");
    // ...
}

首先,我创建一个这样的心跳:

var heartbeat = app.DefineObservable(
                        () => Observable.Interval(TimeSpan.FromSeconds(2)));

在实际应用程序中,我可能会将此心跳间隔设为五分钟而不是两秒钟。无论如何,接下来我希望热点触发数据库查找新用户元数据:

var newUserMeta = app.DefineObservable(
                        () => heartbeat.SelectMany(_ => referenceData))
                    .ToPointStreamable(
                        c => PointEvent.CreateInsert(DateTime.Now, c),
                        AdvanceTimeSettings.IncreasingStartTime);

IQbservable.SelectMany扩展应该展平我期望的referenceData IEnumerable<UserMetaData>_参数会抛弃心跳发出的长整数。然后ToPointStreamableIObservable<UserMetaData>转换为IQStreamable点事件,其开始时间为现在。 (DateTime.Now可能不是非常StreamInsight-y)

然后我将其转换为信号,通过简单查询运行,定义控制台接收器并进行部署。

// Convert to signal
var metaDataSignal = refStream
                    .AlterEventDuration(e => TimeSpan.MaxValue)
                    .ClipEventDuration(refStream, (e1, e2) => e1.Name == e2.Name);

// Query
var result = from t in metaDataSignal
                 select t;

// Define & deploy sink.
var sink = app.DefineObserver(
                    () => Observer.Create<UserMetaData>(c => Console.WriteLine(c)));
sink.Deploy("sink");

我的最后一步是Bind接收器。我还将等待几秒钟观察我的元数据轮询心跳打印到屏幕的输出,然后将新的UserMetaData记录添加到我的数据库并等待以查看是否反映了这些更改。

using (var process = result.Bind(sink).Run("process"))
{
    Thread.Sleep(4000);

    referenceData.Add(new UserMetaData() 
                            {
                                UserId = 3, 
                                Name = "Voqk", 
                                Location = "Houston" 
                            });

    Console.ReadLine();
}

新的UserMetaData记录永远不会反映在输出

Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland

(... forever)

我假设发生的事情是我的UserMetaData列表正在SI服务器上被序列化并重新创建,因此不会反映对本地副本所做的任何更改。我不知道如何克服这个问题。

Mark Simms在2010年写了一篇blog posts about using reference streams in StreamInsight,解释了如何使用静态数据源,并说他的下一篇文章将描述如何使用SQL Server。

不幸的是,该帖子从未发生过。

编辑:我已经将这篇文章中的课程改为马克西姆斯的帖子中的课程,并试图消除杂乱并详细说明我的过程。

2 个答案:

答案 0 :(得分:0)

你的假设是正确的。 .NET类不会进入StreamInsight引擎;您的类仅用于架构(有效负载的形状)。 那么......你如何处理更改参考数据?首先,您的源需要定期刷新。这段时间取决于您期望数据发生变化的频率。 然后,对于参考流,您需要使用计时器将CTI排入队列(以保持其移动),无论数据是什么 - 或者您需要一种方法从数据流中引入CTI。第一种方法最简单,但第二种方法更灵活,因为它将参考流与您在数据流中使用的任何时间戳联系起来,并且可以在重放场景中工作,而不仅仅是实时场景。 最后,您需要允许参考事件过期,并在添加新参考数据时进行替换。这是使用“To Signal”模式(Alter / Clip)完成的。同样,你有选择。如果您的参考源足够“智能”以仅将更改排入队列,则可以将参考事件的生命周期更改为TimeSpan.MaxValue,然后引用数据在被取消之前有效。但是,如果您只想重新加载所有参考事件,则可以将事件持续时间更改为比刷新率稍长一些,然后进行剪辑。此方法还允许从流中删除引用事件(在删除等情况下) 参考数据的最后一个挑战是如何处理时间戳。在大多数示例场景中,数据时间线基于系统时钟......但情况并非总是如此。而且,即使在这些情况下,由于参考事件中的竞争条件仍在排队,而数据事件已经过去,因此您可以“错过”启动时的某些连接。在这种情况下,使用荒谬的早期开始日期(1970年1月1日)作为参考数据和荒谬的晚结束日期(2100年1月1日)并将其作为间隔排队,效果很好。但是,在这种情况下,您绝对需要从数据流导入CTI,修改参考事件的开始日期,以便它们不会违反导入的CTI和其他同步任务......您自己。适配器/查询模型很好地处理了这个问题,但是Reactive模型没有...但是,使用Reactive模型,您可以使用主题来精确调整所有这些工作方式,以便它变得更加灵活。

答案 1 :(得分:0)

作为测试,我将var referenceData = List<UserMetaData>()...移出main,并声明它是静态成员而不是局部变量。

class Program
{
    // *NOW STATIC*
    private static List<UserMetaData> referenceData = new List<UserMetaData>()
    {
        new UserMetaData() {UserId = 1, Name = "Fred Jones", Location = "Seattle"},
        new UserMetaData() {UserId = 2, Name = "Bob Murphy", Location = "Portland"}
    };

    public static void Main(string[] args)
    {
        // ...

现在数据库中的更改会反映在输出中......

Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Voqk, ID: 3, Location: Houston
Name: Fred Jones, ID: 1, Location: Seattle
Name: Bob Murphy, ID: 2, Location: Portland
Name: Voqk, ID: 3, Location: Houston
相关问题