::$data数据流
上周,我们研究了流处理如何帮助我们使用Hazelcast Jet进行数学近似计算 。 我们描述了Pipeline API,并提到它从源 “读取”并“写入”到接收器 。 本周,我想详细介绍一下这些概念,Jet中可用的现成的接收器和源,以及在需要时如何创建自己的接收器和源。
这是在流处理重点series.Other职位包括第三职位:
源和汇
我认为我们大多数人都熟悉批处理模型。 在大公司中,使用它来读取数据库,转换数据并写入另一个数据库已有很长时间了:这被称为ETL 。
但是,数据库不是唯一的读写对象。 另一个遗留但广泛的用例是为其他方提供FTP服务器来存储文件。 然后, 守护程序进程监视是否存在与特定模式匹配的文件:如果找到至少一个文件,它将读取并处理数据,然后继续重命名/移动/删除文件。
在Java EE环境中,还可以从JMS队列中读取/写入数据。 在这方面,Hazelcast IMDG也是一种选择。
源和汇是足以涵盖可能的各种组成部分的术语。 这些术语适用于批处理模型和流模型。
喷射源和汇
开箱即用的Jet提供了一组源和接收器。 它们分别在com.hazelcast.jet.pipeline.Sources
和com.hazelcast.jet.pipeline.Sinks
类中可用。
其中一些与Hazelcast IMDG有关,大多数与以下无关:
资源 | 水槽 | ||
---|---|---|---|
JMS | Queue |
|
|
Topic |
|
| |
SQL Database | Query |
|
|
Statement |
|
| |
Hazelcast | Local/remote |
|
|
Local/remote |
|
| |
Local/remote |
|
| |
Folder |
|
| |
Socket |
|
| |
Standard out |
|
|
自订来源
一个不仅限于现成提供的源和接收器。 如果缺少所需的源/接收器,则可以使用提供的抽象来创建自己的源/接收器。
这是与设计自定义源有关的模型:
![Jet的自定义来源构建器类图”](https://i-blog.csdnimg.cn/blog_migrate/9e3162cf3c46e3a83679c3a845bf8a59.png)
batch()
用于项的有界集合, stream()
用于无项。
样本自定义源
网络上有很多数据,大多数数据可以通过网络服务获得。 人们经常向同一端点重复发送请求以获取数据的情况。 让我们使用Fuel(一个用于REST调用的Kotlin库)创建这样的自定义Source
。
REST电话
funremoteService(url:String)=SourceBuilder
.stream("http-source",DummyContext()) (1)
.fillBufferFn(RestSource(url))
.build()
classRestSource(privatevalurl:String):BiConsumerEx<Unit,SourceBuffer<String>>{
overridefunacceptEx(unit:Unit,buffer:SourceBuffer<String>){ (2)
val(_,_,result)=Fuel.get(url).header().responseString() (3)
when(result){
isResult.Failure->println(result.getException())
isResult.Success->buffer.add(result.get()) (4)
}
}
}
classDummyContext:FunctionEx<Processor.Context,Unit>{ (1)
overridefunapplyEx(ctx:Processor.Context){}
}
- 使用上下文创建流。 上下文可以是可变的,以便在迭代期间存储状态。 在这里,我们不需要传递任何东西,所以我们有一个虚拟的上下文
- 该函数接受两个参数:第一个是上下文,第二个是要附加到的
SourceBuffer
。 Jet将使用该缓冲区从以下位置获取数据 - 执行请求并将结果分配给多个变量-这是Kotlin正在进行的解构声明
- 如果调用成功执行,则将结果添加到缓冲区
使用延迟
许多公共可用的Web服务都实施某种访问限制:它可能与身份验证,速率限制等有关。
想象一下,我们需要限制呼叫以遵守速率限制策略:为避免获得429个HTTP状态响应,我们应该等到一定时间后再执行下一个请求。 这是存储状态的对象变得必要的时间。 因为Java 8 Date / Time API仅提供不可变的对象,所以让我们围绕它设计一个可变的对象:
classTimeHolder:Serializable{
varvalue:Instant=Instant.now() (1)
privateset (2)
funreset(){
value=Instant.now() (3)
}
}
- 初始时刻设置为现在
- 强制执行封装,以便只有类本身才能设置
value
- 重置
value
到现在
上下文创建功能需要相应地更新:
classCreateContext:FunctionEx<Processor.Context,TimeHolder>{
overridefunapplyEx(ctx:Processor.Context)=TimeHolder()
}
此时,可以在RestSource
使用wait逻辑:
classRestSource(privatevalurl:String):
BiConsumerEx<TimeHolder,SourceBuilder.SourceBuffer<String>>{
overridefunacceptEx(time:TimeHolder,buffer:SourceBuilder.SourceBuffer<String>){
if(Instant.now().isAfter(time.value.plusSeconds(30))){ (1)
val(_,_,result)=Fuel.get(url).header().responseString()
when(result){
isResult.Failure->println(result.getException())
isResult.Success->buffer.add(result.get())
}
time.reset() (2)
}
}
}
- 创建防护以检查经过的时间是否在上一个请求之后至少30秒
- 存储当前时间以供下次检查
结论
Hazelcast Jet为大多数常见用例提供了一些现成的源和接收器。 此外,它还提供了一个低级API,可以在没有人需要的情况下创建自己的API。
::$data数据流