Build Block(转自Git)
一个JetStream Application由一个无循环事件(Event)处理流程构成(DAG),其中的每一个业务处理节点为一个Build Block。基本的Build Block由一个输入通道(Inbound Channel)、处理单元(Event Processor)、输出通道(OutBound Channel)构成。
当事件进入JetStream Application中后,经过一系列的Build Block进行业务处理,最终Appliction输出处理好的结果,并将结果发送给相应的应用。
事件是JetStream中的处理对象,事件通常存在一个事件分发主题,主题可以使得事件被调度到对应的Event Processor。主题可以通过事件的setForwardingTopics方法设置,事件产生时没有进行该设置则会被分发到配置文件中配置的全部主题下。
pulsar中为事件定义了一个可扩展的统一的事件模型Event Model,包含了4个基本要素:地址(ipv4/ipv6)、设备(UA(User Agent))、流ID(si(Stream id,必需))、时间(ct(capture time)),统一的事件模型便于JetStream对不同事件源产生的事件进行统一处理。
自定义的事件产生器需要继承于AbstractInboundChannel,并实现open方法,在该方法中会调用fireSendEvent方法将事件发送出去,fireSendEvent是AbstractEventSource定义的事件分发方法。
InboundChannel是JetStream Build Block的接收事件通道。自定义输入InboundChannel需要继承AbstractInboundChannel(AbstractInboundChannel继承了AbstractEventSource),并实现open、close、resume、pause、shutdown、flush、getPendingEvents、processApplicationEvent等方法。
自定义实现的InboundChannel、OutBoundChannel(输出通道)、Event Proccessor(事件的业务处理器)类需要实现的方法基本一致。
1) open:
通道打开的时候调用,可以做一些初始化操作。需要在此时获取事件接收主题,并且为该通道订阅这些主题。
2) close:
通道的绑定器会通过该方法通知通道关闭。
3) resume:
后续处理环节通过发送一个恢复通知,通知挂起的通道继续向外发送事件。
4) pause:
后续处理环节通过发送一个挂起通知通道不再向外发送事件。
5) shutdown:
当应用接收到终止信号时由JetStream框架调用,在该方法中对该类引用的全部资源进行释放操作。
6) flush:
close调用前调用,可以处理相应的flush操作。
7) getPendingEvents:
当应用接收到终止信号时由JetStream框架调用,该方法返回本方法队列中的事件挂起数,直到返回0框架才会去关闭下一个节点(Build Block)。
8) processApplicationEvent:
AbstractEventSource中的方法,当接收到一个spring框架中应用传来的事件时会被调用,需要在此处对事件类型进行检查,检查通过才应该调用open方法打开通道接收事件。
9) afterPropertiesSet:
bean属性设完后自动调用的方法。
10) onMessage:
接收到事件时调用的方法,在此处对事件进行处理并往后续节点继续发送。
11) fireEvent:
这是AbstractEventSource中的方法,调用该方法可以将事件往后续节点发送。
12) setAuthenticator:
注入一个验证器对通道的调用者进行验证。
13) getAuthenticator:
获取验证器。
14) getAddress:
获取事件通道地址,地址中包含一系列订阅主题。
--配置文件通常为buildsrc/JetStreamConf/##wiring.xml。
输入通道绑定器配置,输入通道InboundMessages和InboundMessageBinder绑定,并依赖MessageService.java完成该通道的事件接收工作。
<bean id="InboundMessageBinder"
class="com.ebay.jetstream.event.support.channel.ChannelBinding"
depends-on="MessageService">
<property name="channel" ref="InboundMessages"/>
</bean>
--输入通道和地址、事件池的配置,接收到的事件将会交由gyProcessor处理。
<bean id="InboundMessages"
class="com.gytest.app.channels.inchannel.GyInboundChannel">
<property name="address" ref="InboundChannelAddress" /><!—绑定地址-->
<property name="waitTimeBeforeShutdown" value="15000"/>
<property name="eventSinks"><!—事件接收到之后存放池-->
<list>
<ref bean="gyProcessor" /><!—事件池,通常为Event Processor-->
</list>
</property>
</bean>
--地址,包含了订阅主题,符合主题列表中的主题的事件会被分发到该通道中,分发由MessageService.java完成。
<bean id="InboundChannelAddress"
class="com.gytest.app.channels.GyChannelAddress">
<property name="channelTopics">
<list>
<value>Jetstream.gyapp/OrderSell</value><!-- 输入的事件Topics必须和上一个输出的事件Topics一致才能得到事件流 -->
</list>
</property>
</bean>
--事件池,处理接收到的事件
<bean id="gyProcessor" class="com.gytest.app.processors.GyProcessor">
</bean>
OutboundChannel是JetStream Build Block的分发事件通道。自定义输入OutboundChannel需要继承AbstractOutboundChannel,并实现open、close、resume、pause、shutdown、flush、getPendingEvents、processApplicationEvent、sendEvent等方法。
OutboundChannel中方法与InboundChannel基本一致,不同在于需要实现sendEvent方法,该方法允许向特定的订阅主题发送事件。
没有通过事件的setForwardingTopics方法设置主题的,会默认向xml配置中的全部主题下面分发。
--输出通道绑定器配置,输出通道OutboundMessages和gyOutboundMessageChanneBinder绑定,并依赖MessageService.java完成该通道的事件分发工作。
<bean id="gyOutboundMessageChanneBinder" class="com.ebay.jetstream.event.support.channel.ChannelBinding"
depends-on="MessageService">
<property name="channel" ref="OutboundMessages" />
</bean>
--设置输出通道、分发地址,默认的输出通道是OutboundMessagingChannel,可实现自定义的输出通道。
<bean id="OutboundMessages" class="com.ebay.jetstream.event.channel.messaging.OutboundMessagingChannel" depends-on="MessageService">
<property name="address" ref="gyOutboundChannelAddress" />
</bean>
--设置输出地址,及事件主题。事件如果没设置主题则会默认使用此处设置的主题并全部发送,否则会向特定的主题发送,分发由MessageService.java完成。
<bean id="gyOutboundChannelAddress" class="com.ebay.jetstream.event.channel.messaging.MessagingChannelAddress">
<property name="channelTopics">
<list>
<value>Jetstream.gyapp/staff</value>
<value>Jetstream.gyapp/staff2</value>
</list>
</property>
</bean>
processor是Build Block的核心,用于对来自输入通道的事件进行业务处理,并且将事件向输出通道发送。需要继承AbstractEventProcessor或AbstractQueuedEventProcessor类,并且通常在sendEvent()中进行业务处理。其中如若对处理的事件存在顺序要求则应该继承AbstractQueuedEventProcessor。
@Override
public void sendEvent(JetstreamEvent event) throws EventException {
//event.setEventType("staff");
lastEvent = event;
super.incrementEventRecievedCounter();
System.out.println(event);
super.fireSendEvent(event);
super.incrementEventSentCounter();
}
MessageService.java负责对JetStream框架中的事件进行分发、接收处理,JstStream中事件的订阅、推送功能就是由该类完成的。MessageService中使用的简单变量为Atomic级变量,复杂变量为java.util.concurrent下支持并发操作的类型,因此可以很好的支持并发处理。
--其中的eventsinks可以不配置,若配置则在该processor处理完事件后会将事件发送到OutboundMessages中。
<bean id="gyProcessor" class="com.gytest.app.processors.GyProcessor">
<property name="eventSinks"><!—可以不配置该属性-->
<list>
<ref bean="OutboundMessages" />
</list>
</property>
</bean
Pulsar使用JetStream框架搭建了实时分析应用,在对事件流的处理上主要增加了统一事件模型(Event Model)、统一的事件输入通道(Collector)、事件分发器(Distributor)
事件模型是Pulsar为了统一处理,而对进入Pulsar的事件制定的一套模板,所有需要Pulsar处理的事件都应该符合事件模型定义。
Collector是pulsar中的事件输入通道。在JetStream的基础上集成了Esper,通过EPL对事件处理。
增加了可插拔验证器,对进入的事件进行验证,如是否存在Stream Id,可以将验证错误返回应用。在使用验证器的情况下,InboundChannel不再使用JetStream的主题订阅配置方式进行配置,而是改用类servlet请求方式进行配置(即将事件封装成HttpRequest,同时定义Servlet对请求进行捕捉并进行验证,此种方式比较复杂)。
Pulsar中的事件输出通道,Distributor在JetStream的基础上集成了Esper,通过Esper的EPL对事件进行分类,然后将事件向配置的主题发送。
在Distributor的Processor配置中增加了Kafka,可以将因网络异常等原因的事件暂时存放在Kafka中以便进行回放处理。
<bean id="DistributorEsperProcessor"
class="com.ebay.jetstream.event.processor.esper.EsperProcessor">
<property name="esperEventListener" ref="EsperEventListener" />
<property name="configuration" ref="EsperConfiguration" />
<property name="epl" ref="EPL" />
<property name="eventSinks">
<list>
<ref bean="OutboundMessageChannel" />
<ref bean="PulsarKafkaChannel" /><!--Kafka-->
</list>
</property>
<property name="adviceListener" ref="DistributorSsnzAdviceProcessor" />
<property name="esperExceptionHandler">
<bean id="esperExceptionHandler"
class="com.ebay.jetstream.event.processor.esper.EsperExceptionHandler"></bean>
</property>
</bean>
1) 灵活
GAP中的Build Block的输入通道、输出通道、事件处理器是通过xml文件配置进行组装的,而该xml文件可以通过mongodb存储,在使用的时候从mongodb中获取。
2) 可定制
JetStream因为是开源的,所以可以根据实际情况对框架的消息传递实现进行定制。
3) 与Spring结合
由于JetStream是基于Spring 的框架,因此除了具备Spring框架的优点外还可以很好的与其他Spring框架结合。