创建事件类型
本主题为创建事件类型提供一些指导原则。事件类型定义事件源发布的事件或事件接收器使用的事件。在开发过程中,事件类型或者被指定为单个基元类型,或者被指定为 .NET Framework 类或结构,并且用于定义与事件流中每个事件相关的数据(负载)。事件类型用在以下各个开发阶段中:
编写类型化适配器。类型化适配器将事件类型用作通用参数,这样创建要排队的新事件对象时,就可以初始化正确的结构。
编写查询模板。在 CepStream 对象(该对象的定义基于某种事件类型)之上采用 LINQ 指定查询模板。
有关事件和事件流的详细信息,请参阅 StreamInsight 服务器概念。
确定事件结构
事件负载(即负载中的字段的数量及其类型)固定并且事先已知时,可以创建类型化适配器。对于类型化适配器,适配器的所有实例都会生成相同的固定负载格式。具有固定数据结构的事件源通常都属于这类情况。
创建类型化适配器时,需要定义一个表示固定负载的 .NET 类或结构,或者使用一个基元类型(如果您的事件负载可由单个字段表示)。在使用结构或类时,只能将公共字段和属性用作负载字段。私有字段和属性以及类方法将被忽略,并且无法用在事件类型中。使用此事件类型声明填充输入适配器中的事件类型,并且获取输出适配器中的类型化事件类型的结果。以下示例定义了一个简单的事件类型,该事件类型具有两个类型为 int 的负载字段 V1 和 V2。
public class MyPayload
{
public int V1 { get; set; }
public int V2 { get; set; }
}
另一个示例说明如何使用嵌套事件类型:
public class ComplexPayload
{
public ValueType Value { get; set; }
public bool Status { get; set; }
}
public class ValueType
{
public double Value { get; set; }
public int Quality { get; set; }
}
如果希望特定源或接收器的相同适配器可配置,以便该适配器可处理多个事件类型,则非类型化适配器很有用。将适配器绑定到查询时,将为该适配器提供上述事件类型的事件负载格式,作为配置规范的一部分。此类情况的一个示例是包含不定数量字段的 .csv 文件。只有在绑定和实例化查询时,构成负载的这组字段才能由查询设计者(而不是构建适配器的开发人员)确定。另一个示例为 SQL 表的适配器,其中生成的事件的类型取决于表的架构或针对该表发出的查询。有关详细信息,请参阅创建输入和输出适配器。
指定查询模板时需要基于具有特定事件类型(在设计时必须已知)的 CepStream 对象。查询模板指定过程中的中间 CepStream 对象可以使用成员 init 表达式包含在投影子句(LINQ 中的“select”)中隐式定义的新类型。
负载字段要求
创建事件类型时,请考虑以下负载字段要求和功能。
事件结构不能具有空负载结构。至少需要一个字段。
标量和基本的 .NET Framework 类型以及嵌套类型可用于负载字段。请参阅下面的“支持的数据类型”一节。
不能使用自定义属性修改字段。
StreamInsight 服务器中的事件类型是字段的有序列表,而不是 .NET 结构(不对其字段强制排序)的列表。事件字段的顺序对非类型化适配器非常重要。这些适配器按 ordinal 访问字段,因为这些字段在适配器设计时是未知的。作为默认约定,用作事件类型的 .NET 结构根据其字段名称的词典顺序确定这些字段的顺序。
字段的空性可推断。例如,int? 可为 Null,但 int 不可为 Null。String 和 byte[] 类型始终可为 Null。
byte[] 的默认大小为 512。
字符串字段的最大长度仅受到整个事件的页大小(为 16k 字节)的约束。
事件大小
对于可以在事件类型中定义的字段数量没有显式限制。字段数量取决于各个字段的类型、字段大小以及为 Null 性。
StreamInsight 服务器中的事件页大小为 16K。由于一个事件不能跨多页,16K 减去一些开销是事件的有效最大大小(包括负载和时间戳字段)。在页眉、事件标题和系统字段(如时间戳)所导致的固定开销之外,为 Null 性增加了可变开销(按调整为上限的 N/8 的秩数)。
要充分利用事件页,我们建议遵循以下准则:
避免可以为 Null 的字段。
尽量不使用 string 和 byte[] 字段。
只有在相应方案的语义要求时才保留事件生存期,以便可以在引擎中更有效地释放事件状态所需的内存。
事件类型的可发现性
一旦创建某个事件类型,下一步就是确保依赖项目可发现该事件类型。请注意,.NET 环境支持开发人员以松散耦合的分布方式生成模块,并且以程序集的方式发布这些模块。随后可以将这些程序集组合起来生成集成的应用程序,在对应用程序进行测试后将其部署到生产环境中。
回想一下:可运行的 StreamInsight 查询是基于在查询输入和输出时对事件类型进行匹配,将查询模板成功绑定到输入和输出适配器实例的结果。根据开发环境的不同,您可能需要向其他人提供对事件类型的访问权限。例如,适配器开发人员和查询开发人员可能必须相对独立地开发他们各自的模块。请考虑以下针对事件类型可发现性的应用场景:
如果适配器开发人员为事件类型的发布者,则适配器开发人员可以使用 StreamInsight 托管 API 编写适配器,并发布 .NET 程序集。其他开发人员可通过使用 ildasm.exe 或从 Visual Studio 项目内引用 DLL 对该 .NET 程序集做出反映,并确定事件类型。使用此方法,无需访问 StreamInsight 服务器即可访问该事件类型。
如果 StreamInsight 服务器管理员为事件类型的发布者,则管理员或开发人员都可以在 StreamInsight 服务器中部署该事件类型。随后,有权访问 StreamInsight 服务器的查询开发人员可以使用适用的对象模型 API 调用来检查元数据项并确定事件类型。适配器开发人员还可以编写支持此事件类型的类型化适配器。
如果适配器开发人员和查询开发人员实际上是分离的(每个人均处理自己的通用事件类型表示形式),则会在查询绑定时验证其各自的事件类型是否匹配。如果匹配,则绑定会成功。
如果查询开发人员无权访问适配器程序集或在其中注册该适配器的 StreamInsight 服务器,则开发人员可以通过参考该适配器的产品资料,或者通过对于该领域(例如,金融贸易领域中的“金融信息交换 (FIX)”或“路透社市场数据系统 (RMDS)”)专有的数据传输协议的常识性了解,来确定事件类型。
支持的数据类型
在 StreamInsight 中,每个事件字段和表达式都具有特定的事件类型。StreamInsight 支持以下数据类型。事件负载也可以包含由这些数据类型构成的嵌套类型。
短名称 |
.NET 类 |
类型 |
宽度(位) |
范围 |
字节 |
Byte |
无符号的整数 |
8 |
0 到 255 |
sbyte |
Sbyte |
带符号的整数 |
8 |
-128 到 127 |
byte[] |
Byte[]1 |
字节 |
|
|
int |
int32 |
带符号的整数 |
32 |
-2,147,483,648 到 2,147,483,647 |
uint |
uint32 |
无符号的整数 |
32 |
0 到 4294967295 |
short |
int16 |
带符号的整数 |
16 |
-32,768 到 32,767 |
ushort |
uint16 |
无符号的整数 |
16 |
0 到 65535 |
long |
int64 |
带符号的整数 |
64 |
-9223372036854775808 到 9223372036854775807 |
ulong |
uint64 |
无符号的整数 |
64 |
0 到 18446744073709551615 |
float |
Single |
单精度浮点类型 |
32 |
-3.4 × 1038 到 +3.4 × 1038 |
double |
Double |
双精度浮点类型 |
64 |
±5.0 × 10−324 到 ±1.7 × 10308 |
decimal |
Decimal |
可以表示具有 29 个有效位数的小数的准确小数或整数类型 |
128 |
±1.0 × 10e−28 到 ±7.9 × 10e28 |
bool |
Boolean |
逻辑布尔值类型 |
8 |
true 或 false |
datetime |
DateTime |
具有从公元 0001 年 1 月 1 日午夜 12:00:00 起到公元 9999 年 12 月 31 日午夜 11:59:59 止的值的日期和时间 |
|
|
timespan |
TimeSpan |
等于所表示的时间间隔的时钟周期数。一个时钟周期等于 100 纳秒 |
|
Int64.MinValue 时钟周期到 Int64.MaxValue 时钟周期 |
guid |
guid |
全局唯一标识符 |
128 |
|
char |
Char |
一个 Unicode 字符 |
16 |
U+0000 到 U+ffff |
文字列 (string) |
String1 |
Unicode 字符序列 |
|
. |
1 不包括可以为 Null 的类型。
在适配器开发过程中,使用 DataTimeOffset 类型来指定事件时间戳。不过,事件类型负载字段的定义中仅支持 DateTime 类型。在将 DateTimeOffset 类型的数据导入事件字段的情况下,必须将该数据转换为 UTC 类型的 DateTime。例如,可以从 SQL Server 数据库填充负载字段,也可以将事件时间戳字段复制到负载字段中进行计算。