Siddhi

1, Siddhi是什么?

Siddhi是一个开源的流处理和复杂事件处理引擎,由WSO2公司开发。它提供了一个强大而灵活的框架,用于处理实时流数据和复杂事件。官网

2, Siddhi特点和功能

Siddhi具有以下特点和功能:
1),实时流处理:Siddhi可以处理连续的实时数据流,并在数据上执行计算、转换和聚合操作。
2) 复杂事件处理:Siddhi允许您基于特定的模式或条件在数据流中检测和关联感兴趣的事件。
3) 时间处理:Siddhi支持事件时间处理,可以处理事件的无序到达并在事件数据上执行基于时间的操作。
4) 查询语言:Siddhi提供了一种类似SQL的查询语言,称为Siddhi Query Language(SiddhiQL),可以以简洁直观的方式表达复杂事件处理逻辑。
5) 窗口操作:Siddhi支持滑动窗口、滚动窗口和基于时间的窗口等多种窗口操作机制,可以在特定的时间间隔内分析数据。
6) 可扩展性:Siddhi可以通过自定义函数、数据源、数据接收器和传输机制进行扩展,可以与各种数据源、处理引擎和输出系统集成。

3, Siddhi缺点

1)学习曲线较陡峭:Siddhi的查询语言相对复杂,需要一定的学习和理解成本,特别是对于没有经验的用户来说。
2)配置和部署复杂性:Siddhi的配置和部署可能需要一些复杂的步骤,特别是在分布式环境中使用时。
3)可视化和监控工具的缺乏:Siddhi缺乏一些成熟的可视化和监控工具,使得在开发和调试过程中可能需要额外的努力。
4)对硬件资源的要求较高:由于Siddhi需要处理大规模的实时数据流,对硬件资源(如内存和处理能力)的要求较高。

4, 架构

±---------------------------------+
| Siddhi Engine |
±---------------------------------+
| |
| ±----------------------------+ |
| | Input Sources | |
| ±----------------------------+ |
| |
| ±----------------------------+ |
| | Siddhi Queries | |
| ±----------------------------+ |
| |
| ±----------------------------+ |
| | Output Sinks | |
| ±----------------------------+ |
| |
±---------------------------------+
在这个架构中,Siddhi Engine是整个平台的核心组件,负责处理实时数据流和执行复杂事件处理逻辑。
1)输入源(Input Sources)是数据流的来源,可以是各种数据源,如消息队列、传感器、数据库等。Siddhi Engine从这些输入源中接收数据流,并将其传递给Siddhi Queries进行处理。
2)Siddhi Queries是用户定义的查询逻辑,使用Siddhi Query Language(SiddhiQL)编写。这些查询可以包括事件关联、窗口操作、过滤条件等,用于处理和分析数据流。
3)输出接收器(Output Sinks)是数据流的目标,可以是消息队列、数据库、实时仪表板等。Siddhi Engine将处理后的数据流发送到这些输出接收器,供后续的处理和展示使用。
4)整个架构的核心是Siddhi Engine,它负责协调输入源、Siddhi Queries和输出接收器之间的数据流动和处理。

5, 应用场景

1)物联网(IoT):Siddhi可以用于处理大规模的传感器数据流,进行实时监测、分析和决策。例如,监测智能家居设备的状态、分析工厂生产线的传感器数据等。
2)金融交易监控:Siddhi可以用于实时监控金融交易数据,检测异常交易、欺诈行为和市场波动。它可以帮助金融机构及时发现和应对风险。
3)实时分析和智能监控:Siddhi可以用于实时分析大规模数据流,提取有价值的信息和洞察,并进行实时决策。例如,实时分析社交媒体数据、监控网络流量等。
4)实时报警和通知:Siddhi可以用于实时监测事件流,并根据预定义的规则和条件触发报警和通知。例如,监测系统日志、网络安全事件等。
5)实时仪表板和可视化:Siddhi可以将处理后的数据流发送到实时仪表板和可视化工具,用于实时展示和监控。例如,实时展示销售数据、监控设备状态等。
6)数据流集成和处理:Siddhi可以用于将不同数据源的数据流进行集成和处理,进行数据清洗、转换和聚合。例如,将传感器数据与外部数据源进行关联和分析。

6, 与flink区别

1)编程模型:Siddhi使用Siddhi Query Language(SiddhiQL)作为查询语言,类似于SQL,用于定义复杂事件处理逻辑。而Flink使用基于Java或Scala的编程API,允许开发人员以编程方式定义数据流处理逻辑。
2) 数据处理模型:Siddhi是基于事件的处理模型,它将连续的事件流作为输入,并在事件上执行计算和操作。Flink是基于数据流的处理模型,它将连续的数据流作为输入,并在数据上执行计算和操作。
3) 窗口操作:Siddhi提供了丰富的窗口操作机制,如滑动窗口、滚动窗口和基于时间的窗口,用于在特定的时间间隔内分析数据。Flink也提供了窗口操作,但它的窗口操作更加灵活和可定制。
4) 扩展性和生态系统:Flink具有更广泛的生态系统和更强大的扩展性。它支持各种数据源和数据接收器,并提供了丰富的库和工具,用于处理不同类型的数据和场景。Siddhi的生态系统相对较小,但也提供了一些扩展点和可定制性。
5) 集群部署和容错性:Flink具有强大的集群部署和容错性能力,可以在分布式环境中处理大规模的数据流。它提供了故障恢复机制和容错保证。Siddhi也支持分布式部署,但在这方面相对较弱。

7,SiddhiQL

一 简单操作

1)定义输入流
语法

define stream <stream_name> (<attribute1> <type1>, <attribute2> <type2>, ...);

举例

define stream SensorStream (sensorId string, temperature double, humidity float);

2)定义输出流

语法

define stream <stream_name> (<attribute1> <type1>, <attribute2> <type2>, ...);

举例

define stream AlertStream (sensorId string, temperature double, humidity float);

3)插入事件到输入流
语法

insert into <stream_name> values (<value1>, <value2>, ...);

举例

insert into SensorStream values ('sensor001', 25.5, 60.2);

4)查询事件
语法

from <stream_name> [<condition>]
select <attribute1>, <attribute2>, ...
insert into <output_stream_name>;

示例

from SensorStream[temperature > 30]
select sensorId, temperature, humidity
insert into AlertStream;

5) 定义窗口

语法

define window <window_name> <window_type> [parameters];

示例

define window TemperatureWindow length(10);

6) 使用窗口查询

语法

from <stream_name>
[<condition>]
insert into <window_name>;


示例

from SensorStream
select *
insert into TemperatureWindow;

7)定义查询的输出频率
语法

@info(name = 'query_name', outputRateLimit = '<rate_limit>')
from <stream_name>
select ...
insert into ...



示例

@info(name = 'AlertQuery', outputRateLimit = '10 events per second')
from SensorStream[temperature > 30]
select sensorId, temperature, humidity
insert into AlertStream;


二注解

1)@source注解:
@source注解用于定义输入数据源。
通过type属性指定数据源的类型,例如inMemory、kafka、mqtt等。
可以使用其他属性来配置特定类型的数据源,例如topic、bootstrap.servers等。
通过@map注解可以指定数据源的映射类型,例如passThrough、json、xml等。
示例:@source(type=‘inMemory’, topic=‘SensorEventStream’, @map(type=‘passThrough’))定义了一个名为SensorEventStream的输入流,使用inMemory类型的数据源,并使用passThrough映射类型。

@source(type='<source_type>', <source_properties>)

其中,<source_type>是数据源的类型,可以是内置的数据源类型(如kafka、http、tcp等),也可以是自定义的数据源类型。
<source_properties>是数据源的属性,用于配置数据源的详细信息。属性的具体内容取决于数据源的类型。以下是一些常见的属性示例:
topic:指定数据源的主题或队列名称。
bootstrap.servers:指定Kafka或其他消息队列的引导服务器地址。
host:指定数据源的主机名。
port:指定数据源的端口号。
username和password:指定用于身份验证的用户名和密码。
@map:指定数据源的映射类型,用于将输入数据映射到Siddhi流中的属性。

2)@sink注解:
@sink注解用于定义输出数据接收器。
通过type属性指定数据接收器的类型,例如log、http、kafka等。
可以使用其他属性来配置特定类型的数据接收器,例如topic、url等。
通过@map注解可以指定数据接收器的映射类型,例如passThrough、json、xml等。
示例:@sink(type=‘log’)定义了一个名为OutputStream的输出流,使用log类型的数据接收器。

3)@App:name注解:
@App:name注解用于为Siddhi应用程序指定一个名称。
该名称在Siddhi应用程序中必须是唯一的。
示例:@App:name(‘MySiddhiApp’)为Siddhi应用程序指定了名称为MySiddhiApp。

4)@info注解:
@info注解用于提供有关查询的信息,例如查询的名称或描述。
这些信息可以在Siddhi应用程序的运行时环境中使用,例如在日志中显示。
示例:@info(name=‘query1’)为查询指定了名称为query1的信息。

5)@map注解:
@map注解用于定义数据源和数据接收器的映射类型。
映射类型指定了如何将输入数据转换为Siddhi事件或将Siddhi事件转换为输出数据。
Siddhi提供了多种映射类型,例如passThrough、json、xml等。
示例:@map(type=‘json’)指定了使用JSON映射类型。

6)@function注解:
@function注解用于定义自定义函数。
通过name属性指定函数的名称。
可以使用其他属性来配置函数的参数和返回类型。
示例:@function(name=‘customFunction’)定义了一个名为customFunction的自定义函数。

7)@trigger注解:
@trigger注解用于定义触发器。
通过cron属性指定触发器的时间表达式。
可以使用其他属性来配置触发器的行为,例如start、end等。
示例:@trigger(cron=‘0/5 * * * * ?’)定义了一个每5秒触发一次的触发器。

8)@distribution注解:
@distribution注解用于定义分布式部署的相关信息。
可以使用strategy属性指定分布式部署的策略,例如partitioned、replicated等。
示例:@distribution(strategy = ‘partitioned’)定义了一个分布式部署策略为partitioned。

三 函数

1) 普通函数
a)数学函数(Math Functions):

  • math:sin(x):计算参数x的正弦值。
  • math:cos(x):计算参数x的余弦值。
  • math:tan(x):计算参数x的正切值。
  • math:abs(x):计算参数x的绝对值。
  • math:round(x):将参数x四舍五入为最接近的整数。
    b)字符串函数(String Functions):
  • str:length(s):计算字符串s的长度。
  • str:concat(s1, s2):将字符串s1和s2连接起来。
  • str:substring(s, startIndex, endIndex):从字符串s中提取子字符串,从startIndex到endIndex。
    c)时间函数(Time Functions):
  • time:currentTimeMillis():返回当前时间的毫秒数。
  • time:timestamp():返回当前时间的时间戳。
    d)类型转换函数(Type Conversion Functions):
  • cast(x, targetType):将参数x转换为目标类型。

2)聚合函数
a)数值聚合函数(Numeric Aggregate Functions):

  • avg(attribute):计算指定属性的平均值。
  • sum(attribute):计算指定属性的总和。
  • min(attribute):计算指定属性的最小值。
  • max(attribute):计算指定属性的最大值。
  • count(attribute):计算指定属性的计数。
    b)字符串聚合函数(String Aggregate Functions):
  • str:concat(attribute):将指定属性的所有值连接成一个字符串。
  • str:collect(attribute):将指定属性的所有值收集到一个列表中。
    c)时间聚合函数(Time Aggregate Functions):
  • time:timestampInMilliseconds(attribute):计算指定属性的时间戳的毫秒数。
  • time:timestampInSeconds(attribute):计算指定属性的时间戳的秒数。
    d)自定义聚合函数(Custom Aggregate Functions):
  • Siddhi还允许您定义自定义的聚合函数,以满足特定的需求。您可以使用Java或脚本语言编写自定义聚合函数的逻辑,并在Siddhi查询中使用它们。

Java中实现自定义聚合函数
i1)创建一个类来实现Siddhi的org.wso2.siddhi.core.aggregation.AggregationProcessor接口。这个接口定义了自定义聚合函数的方法。

import org.wso2.siddhi.core.aggregation.AggregationProcessor;
import org.wso2.siddhi.core.event.ComplexEventChunk;
import org.wso2.siddhi.core.event.state.StateEvent;
import org.wso2.siddhi.core.event.stream.StreamEvent;
import org.wso2.siddhi.core.event.stream.StreamEventFactory;
import org.wso2.siddhi.core.event.stream.StreamEventPool;
import org.wso2.siddhi.core.event.stream.StreamEventPoolManager;
import org.wso2.siddhi.core.util.collection.operator.CompiledCondition;
import org.wso2.siddhi.core.util.collection.operator.CompiledSelection;
import org.wso2.siddhi.core.util.collection.operator.MatchingMetaInfoHolder;
import org.wso2.siddhi.query.api.aggregation.TimePeriod;

public class CustomAggregationFunction implements AggregationProcessor {
    // 实现聚合函数的逻辑

    @Override
    public CompiledCondition compileCondition(Expression expression, MatchingMetaInfoHolder matchingMetaInfoHolder,
            SiddhiAppContext siddhiAppContext, List<VariableExpressionExecutor> list,
            Map<String, Table> map, String s) {
        // 实现编译条件的逻辑
        return null;
    }

    @Override
    public CompiledSelection compileSelection(Expression expression, MatchingMetaInfoHolder matchingMetaInfoHolder,
            SiddhiAppContext siddhiAppContext, List<VariableExpressionExecutor> list,
            Map<String, Table> map, String s) {
        // 实现编译选择的逻辑
        return null;
    }

    @Override
    public void start() {
        // 实现聚合函数的启动逻辑
    }

    @Override
    public void stop() {
        // 实现聚合函数的停止逻辑
    }

    @Override
    public Map<String, Object> currentState() {
        // 实现聚合函数的当前状态逻辑
        return null;
    }

    @Override
    public void restoreState(Map<String, Object> map) {
        // 实现聚合函数的状态恢复逻辑
    }
}

i2)在自定义聚合函数类中实现聚合函数的逻辑。您可以根据需要自定义聚合函数的计算逻辑、初始化逻辑、状态管理等。
i3) 在Siddhi查询中使用自定义聚合函数。在查询中,使用aggregate关键字指定自定义聚合函数,并将其与输入流和输出流关联起来。

String siddhiApp = "@App:name('CustomAggregationExample')\n" +
        "define stream Input (value double);\n" +
        "\n" +
        "@info(name = 'query1')\n" +
        "from Input#window.time(10 sec)\n" +
        "select custom:myAggregation(value) as result\n" +
        "insert into Output;";

在上述示例中,我们定义了一个输入流Input,包含一个属性value。然后,我们使用自定义聚合函数custom:myAggregation()计算输入流中每个窗口的聚合结果,并将结果插入到输出流Output中。
i4)在Siddhi应用程序中注册自定义聚合函数。
怎么注册?
o1)创建一个类来实现Siddhi的org.wso2.siddhi.core.extension.EternalReferencedHolder接口。这个接口定义了自定义聚合函数的注册方法。

import org.wso2.siddhi.core.config.SiddhiAppContext;
import org.wso2.siddhi.core.extension.EternalReferencedHolder;
import org.wso2.siddhi.core.util.config.ConfigReader;

public class CustomAggregationExtensionHolder implements EternalReferencedHolder {
    @Override
    public void init(SiddhiAppContext siddhiAppContext, ConfigReader configReader) {
        // 在这里初始化自定义聚合函数
        siddhiAppContext.getSiddhiContext().getSiddhiExtensions().addExtension("custom:myAggregation",
                CustomAggregationFunction.class);
    }

    @Override
    public void destroy() {
        // 在这里销毁自定义聚合函数
    }
}

o2)在自定义聚合函数注册类中实现init()方法。在该方法中,使用addExtension()方法将自定义聚合函数注册到Siddhi上下文中。
o3)在Siddhi应用程序中使用自定义聚合函数注册类。在Siddhi应用程序的配置文件中,使用@Extension注解将自定义聚合函数注册类与应用程序关联起来。

@App:name("CustomAggregationExample")
@Extension(name = "custom:myAggregation", namespace = "custom",
        description = "Custom Aggregation Function")
define stream Input (value double);

在上述示例中,我们使用@Extension注解将自定义聚合函数注册类CustomAggregationExtensionHolder与Siddhi应用程序关联起来。这样,当Siddhi应用程序启动时,自定义聚合函数将被注册到Siddhi上下文中。

3) 窗口函数:
length():返回窗口中事件的数量。
timeBatch():将事件按时间批量处理。
time():将事件按时间滑动窗口处理。

   from SensorStream#window.timeBatch(10 sec)
   select count() as eventCount
   insert into BatchCountStream;

4) 序列函数
序列函数用于检测事件的模式和序列

o1)sequence函数:
sequence函数用于定义事件的顺序。它接受多个参数,每个参数表示一个事件类型。
该函数返回一个布尔值,指示事件是否按照指定的顺序出现。
示例:sequence(A, B, C)表示事件A、B和C必须按照给定的顺序出现。
o2)lengthBatch函数:
lengthBatch函数用于定义事件的批处理操作。它接受一个整数参数,表示每个批次中的事件数量。
该函数返回一个布尔值,指示是否达到了指定数量的事件批次。
示例:lengthBatch(3)表示每当有3个事件时,将触发批处理操作。
o3)every函数:
every函数用于定义事件的连续出现。它接受一个时间间隔参数,表示事件之间的最大时间间隔。
该函数返回一个布尔值,指示事件是否连续出现在指定的时间间隔内。
示例:every(10 sec)表示事件必须在指定的时间间隔内连续出现。
o4)within函数:
within函数用于定义事件的时间限制。它接受一个时间间隔参数,表示事件必须在指定的时间范围内出现。
该函数返回一个布尔值,指示事件是否在指定的时间范围内出现。
示例:within(30 sec)表示事件必须在指定的时间范围内出现。

   from every (e1=SensorStream[sensorId == 'sensor001'] -> e2=SensorStream[sensorId == 'sensor002'])
   within 10 sec
   select e1.sensorId as sensor1, e2.sensorId as sensor2
   insert into PatternMatchStream;

序列函数复杂实践
假设我们有一个事件流SensorEventStream,其中包含传感器数据的事件。我们希望检测以下模式:事件A后跟事件B,然后是事件C,并且事件B和C之间的时间间隔不超过5秒。
首先,我们需要创建一个Siddhi应用程序,并定义输入流和输出流:

import org.wso2.siddhi.core.SiddhiManager;
import org.wso2.siddhi.core.stream.input.InputHandler;
import org.wso2.siddhi.core.stream.output.StreamCallback;
import org.wso2.siddhi.core.util.EventPrinter;

public class SiddhiApp {
    public static void main(String[] args) throws InterruptedException {
        SiddhiManager siddhiManager = new SiddhiManager();

        String siddhiApp = "@App:name('SequenceFunctionExample')" +
                "@source(type='inMemory', topic='SensorEventStream', @map(type='passThrough'))" +
                "define stream SensorEventStream (sensorId int, value double, timestamp long);" +
                "@sink(type='log')" +
                "define stream OutputStream (sensorId int, value double, timestamp long);" +
                "@info(name='query1')" +
                "from SensorEventStream#window.time(10 sec) " +
                "sequence(sensorId == 1) -> " +
                "every(1 sec) " +
                "sequence(sensorId == 2) -> " +
                "every(1 sec) " +
                "sequence(sensorId == 3) " +
                "select sensorId, value, timestamp " +
                "insert into OutputStream;";

        SiddhiAppRuntime siddhiAppRuntime = siddhiManager.createSiddhiAppRuntime(siddhiApp);
        siddhiAppRuntime.start();

        InputHandler inputHandler = siddhiAppRuntime.getInputHandler("SensorEventStream");
        inputHandler.send(new Object[]{1, 10.5, System.currentTimeMillis()});
        inputHandler.send(new Object[]{2, 20.3, System.currentTimeMillis()});
        inputHandler.send(new Object[]{3, 30.2, System.currentTimeMillis()});

        Thread.sleep(1000);

        siddhiAppRuntime.shutdown();
        siddhiManager.shutdown();
    }
}

在上述示例中,我们定义了一个名为SensorEventStream的输入流,其中包含传感器数据的事件。然后,我们定义了一个名为OutputStream的输出流,用于输出满足我们定义的模式的事件。

在Siddhi查询中,我们使用了sequence函数和every函数来定义事件的顺序和时间限制。具体来说,我们使用了三个sequence函数来定义事件A、B和C的顺序,并使用了两个every函数来定义事件B和C之间的时间间隔。

最后,我们通过创建SiddhiAppRuntime并发送事件到输入流来执行Siddhi应用程序。满足定义的模式的事件将被输出到OutputStream流中。

这只是一个复杂实践的示例,您可以根据具体需求调整和扩展查询语句和事件流定义。

5)表格函数:
lookup():从外部表格中检索数据。
insertInto():将事件插入到外部表格中。
deleteFrom():从外部表格中删除数据。

   from SensorStream
   select sensorId, temperature, humidity
   insert into SensorTable;
   
   from SensorStream
   select sensorId, temperature, humidity
   insertInto SensorTable;
   
   from SensorStream
   delete from SensorTable
   on SensorStream.sensorId == SensorTable.sensorId;

6)脚本函数
o1)创建一个脚本文件,例如customScript.js,并在其中编写自定义函数的逻辑。例如,以下是一个使用JavaScript编写的脚本函数示例:

function customScriptFunction(input) {
    // 在这里编写自定义函数的逻辑
    var result = input * 2;
    return result;
}

o2)在Java代码中使用脚本函数。使用Siddhi的ScriptFunction类来执行脚本函数的逻辑。

import org.wso2.siddhi.core.function.Script;

public class ScriptFunctionExample {
    public static void main(String[] args) {
        // 创建ScriptFunction对象
        ScriptFunction scriptFunction = new ScriptFunction("customScript.js");

        // 调用脚本函数
        Object result = scriptFunction.call("customScriptFunction", 10);

        // 打印结果
        System.out.println("Result: " + result);
    }
}

在上述示例中,我们创建了一个ScriptFunction对象,并指定了脚本文件的路径。然后,我们使用call()方法调用脚本函数,并传递参数。最后,我们打印出脚本函数的结果。

三 复杂操作

1)聚合计算
计算每个传感器的平均温度和湿度。

   from SensorStream
   select sensorId, avg(temperature) as avgTemperature, avg(humidity) as avgHumidity
   group by sensorId
   insert into AggregatedStream;

2) 模式匹配和复杂事件处理
检测连续三个温度超过30度的事件。

   from every (e1=SensorStream[temperature > 30] -> e2=SensorStream[temperature > 30] -> e3=SensorStream[temperature > 30])
   select e1.sensorId, e1.temperature, e2.temperature, e3.temperature
   insert into HighTemperaturePatternStream;

3) 多流处理和联接操作
将传感器数据与天气数据联接,根据城市和时间进行联接。

   from SensorStream#window.time(1 min) as s join WeatherStream#window.time(1 min) as w
   on s.city == w.city and s.timestamp == w.timestamp
   select s.sensorId, s.temperature, w.weatherCondition
   insert into JoinedStream;

4)复杂条件和过滤操作
过滤出温度大于30度且湿度小于50%的事件

   from SensorStream[temperature > 30 and humidity < 50]
   select sensorId, temperature, humidity
   insert into FilteredStream;

5)时间窗口和滑动窗口操作:
计算最近10秒内的温度平均值。

   from SensorStream#window.time(10 sec)
   select avg(temperature) as avgTemperature
   insert into AverageTemperatureStream;

6)检测每小时的最高温度,并将结果插入到MaxTemperatureStream中

@info(name='query2', description='Detect temperature spikes')
from TemperatureStream#window.time(1 hour)
select max(temperature) as maxTemperature
insert into MaxTemperatureStream;
@info(name='query1', description='Calculate average temperature per hour')
from TemperatureStream#window.time(1 hour)
select avg(temperature) as avgTemperature
insert into AverageTemperatureStream;

8,举例

假设您有一个实时数据流,包含用户的登录信息,您希望使用Siddhi框架对数据进行处理和分析,以检测异常登录行为
1)添加Siddhi依赖项:在您的Java项目的构建配置文件(如pom.xml)中,添加Siddhi的依赖项。确保使用与Siddhi框架版本兼容的依赖项版本。

<dependency>
    <groupId>io.siddhi</groupId>
    <artifactId>siddhi-core</artifactId>
    <version>5.1.2</version>
</dependency>

2)编写Siddhi查询:使用SiddhiQL编写查询逻辑。以下是一个示例查询,用于检测异常登录行为:

String query = "@info(name = 'query') " +
        "from LoginStream#window.time(5 min) " +
        "select userId, count(*) as loginCount " +
        "group by userId " +
        "having loginCount > 10 " +
        "insert into SuspiciousLoginStream;";

这个查询逻辑包括以下步骤:

  • 从名为LoginStream的输入流中获取数据。
  • 使用时间窗口函数window.time(5 min)将数据流限制在过去5分钟的时间范围内。
  • 根据userId分组,并计算每个用户的登录次数。
  • 使用having子句过滤出登录次数大于10的用户。
  • 将结果插入名为SuspiciousLoginStream的输出流中。

3)创建Siddhi运行时:在Java代码中,创建SiddhiManager对象来管理Siddhi运行时环境。

SiddhiManager siddhiManager = new SiddhiManager();

4)部署查询:使用SiddhiManager对象,创建ExecutionPlanRuntime并部署查询。

ExecutionPlanRuntime executionPlanRuntime = siddhiManager.createExecutionPlanRuntime(query);
executionPlanRuntime.start();

5)处理输入和输出:使用ExecutionPlanRuntime对象,获取输入处理器和输出处理器,并使用它们来处理输入数据流和获取查询结果。

InputHandler inputHandler = executionPlanRuntime.getInputHandler("LoginStream");
inputHandler.send(new Object[]{"user1", "2022-01-01T10:00:00"});

OutputHandler outputHandler = executionPlanRuntime.getOutputHandler("SuspiciousLoginStream");
outputHandler.register(new OutputCallback() {
    @Override
    public void send(Event[] events) {
        for (Event event : events) {
            System.out.println("Suspicious Login Detected: " + event.getData()[0]);
        }
    }
});

6)停止和清理:在您的应用程序完成后,确保停止ExecutionPlanRuntime并进行清理。

executionPlanRuntime.shutdown();
siddhiManager.shutdown();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大道至简@EveryDay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值