一,介绍

本文使用Oozie的消息通知功能,并根据JMS规范中的消息选择器(Selector)实现 根据作业的ID来过滤消息。

首先搭建好JMS Provider(ActiveMQ) ,并进行相关配置,这样Oozie Server就可以把消息发送给JMS Provider了,我们使用了ActiveMQ作为消息服务器。相关配置可参考:Oozie 使用ActiveMQ实现 JMS通知

在ActiveMQ中配置好Topic,该Topic名称为${username}。即该${username}提交的所有的作业,作业的执行结果都会发送到名为${username}的Topic上。

对于Oozie而言,每提交一个作业会生成一个JobID,而我们的需求是,只对某些JobID感兴趣,并不是对该用户提交的所有作业感兴趣。因此,需要根据JobID来过滤订阅到${username}这个Topic上的消息。

二,实现JMS 消息选择器

根据JMS规范,在创建一个消费者时,可使用消息选择器。这样消费者就只能接收到被消息选择器过滤以后的消息了。而消息选择器使用 消息属性 和 消息头作为条件表达式,这些条件表达式使用boolean逻辑来声明应该将哪一条消息传递给JMS消费者。请注意:消息选择器无法参考消息体内的数据,它只能使用消息头和消息属性。

于是,我们就需要知道Oozie生成的JMS消息的消息头和消息属性是什么?参考官方文档可以看出,Oozie生成的JMS消息的头部由JMSHeaderConstants类来定义。其源代码如下:

 /**
  *
  * Class holding constants used in JMS selectors
  */
 public final class JMSHeaderConstants {
     // JMS Application specific properties for selectors
     public static final String EVENT_STATUS = "eventStatus";
     public static final String SLA_STATUS = "slaStatus";
     public static final String APP_NAME = "appName";
     public static final String USER = "user";
     public static final String MESSAGE_TYPE = "msgType";
     public static final String APP_TYPE = "appType";

     //public static final String JOBID = "jobId";// add for my specific selectors
     // JMS Header property
     public static final String MESSAGE_FORMAT = "msgFormat";

 }

从中可以看出,可以使用EVENT_STATUS、SLA_STATUS、USER……相关属性构造选择器。但是官方JMSHeaderConstants类的源代码中并没有JobID这个属性。

因此,需要修改源代码,添加JobID,以使得我们消费者能够根据JobID进行过滤。(如上,第14行就是我自己添加的代码)

此外,还需要在JobMessage类的构造方法里面添加一行:

        jmsMessageProperties.put(JMSHeaderConstants.JOBID, id);//add for my specific selectors

至此,Oozie端的代码修改完毕。

这两个类在oozie-client这个maven工程中

进入到该工程的文件夹下,使用

mvn clean compile

mvn clean package

生成相关的jar文件

将生成的oozie-client-4.1.0.jar文件替换掉原来的Oozie 安装目录下的lib包下的对应的jar包。重启Oozie即可。

另外,Apache Oozie-4.1.0是不支持Spark作业的。而Cloudera-Oozie-4.1.0则是支持Spark作业的。

Apache oozie-client.jar 与Cloudera的 oozie-client.jar对比如下:

5月 6, 中午12点09:47.473     FATAL     org.apache.oozie.service.Services     

SERVER[datanode1] Runtime Exception during Services Load. Check your list of 'oozie.services' or 'oozie.services.ext'

5月 6, 中午12点09:47.480     FATAL     org.apache.oozie.service.Services     

SERVER[datanode1] E0103: Could not load service classes, resource [spark-action-0.1.xsd] not found
org.apache.oozie.service.ServiceException: E0103: Could not load service classes, resource [spark-action-0.1.xsd] not found
    at org.apache.oozie.service.Services.loadServices(Services.java:309)
    at org.apache.oozie.service.Services.init(Services.java:213)
    at org.apache.oozie.servlet.ServicesLoader.contextInitialized(ServicesLoader.java:46)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4210)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4709)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:802)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:583)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:944)
    at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:779)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:505)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1322)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:325)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1068)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:822)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1060)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:759)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: java.lang.IllegalArgumentException: resource [spark-action-0.1.xsd] not found

这样,Oozie发送给JMS消息服务器的消息,在头部中都会带一个JobID了,而我们就根据这个JobID属性进行消息过滤。

可参考Oozie官方文档中给出的一句话:

JMS messages published are javax.jms.TextMessage . The body contains JSON and the header contains multiple properties that can be used as
 selectors. The header properties are not repeated in the body of the  message to keep the messages small.

由于JobID已经在body里面了,故Oozie并没有把它放到Header中去。

三,使用消息选择器来过滤消息

由于现在Oozie发送给ActiveMQ的每条JMS消息都会在头部带一个JobID,故现在可使用JobID作为消息选择器过滤消息了。

String selector=JMSHeaderConstants.JOBID + "='" + jobid + "'";
MessageConsumer consumer = session.createConsumer(topic, selector);

至此,就可以实现根据作业ID来接收该JobID所对应的作业的执行结果信息了。

Oozie JMS通知消息实现--根据作业ID来过滤消息的更多相关文章

  1. 解决 MySQL 比如我要拉取一个消息表中用户id为1的前10条最新数据

    我们都知道,各种主流的社交应用或者阅读应用,基本都有列表类视图,并且都有滑到底部加载更多这一功能, 对应后端就是分页拉取数据.好处不言而喻,一般来说,这些数据项都是按时间倒序排列的,用户只关心最新的动 ...

  2. [置顶] 手把手教你iOS消息推送证书生成以及Push消息

    iOS推送消息是许多iOS应用都具备的功能,今天在给应用加推送功能,在生成证书的过程中,发生了各种令人蛋痛的事.下面就把步骤拿出来分享下: iOS消息推送的工作机制可以简单的用下图来概括: Provi ...

  3. Windows消息理解(系统消息队列,进程消息队列,非队列消息)

    // ====================Windows消息分类==========================在Windows中,消息分为以下三类:标准消息——除WM_COMMAND之外,所 ...

  4. 【消息队列】kafka是如何保证消息不被重复消费的

    一.kafka自带的消费机制 kafka有个offset的概念,当每个消息被写进去后,都有一个offset,代表他的序号,然后consumer消费该数据之后,隔一段时间,会把自己消费过的消息的offs ...

  5. 分布式事务解决方案(二)消息系统避免分布式事务 & MQ事务消息 & Sagas 事务模型

    参考文档: 如何用消息系统避免分布式事务:http://blog.jobbole.com/89140/ https://www.cnblogs.com/savorboard/p/distributed ...

  6. ZeroMQ接口函数之 :zmq_msg_copy - 把一个消息的内容复制到另一个消息中

    ZeroMQ 官方地址 :http://api.zeromq.org/4-1:zmq_msg_copy zmq_msg_copy(3)   ØMQ Manual - ØMQ/3.2.5 Name zm ...

  7. Mina、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息

    在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次rea ...

  8. 【原创】源码角度分析Android的消息机制系列(一)——Android消息机制概述

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.为什么需要Android的消息机制 因为Android系统不允许在子线程中去访问UI,即Android系统不允许在子线程中更新UI. 为什 ...

  9. RabbitMQ 消息确认机制以及lazy queue+ disk消息持久化

    一:Basic的一些属性,一些方法 1. 消费端的确认 自动确认: message出队列的时候就自动确认[broke] basicget... 手工确认: message出队列之后,要应用程序自己去确 ...

随机推荐

  1. 【转】如何使用PhoneGap打包Web App

    如何使用PhoneGap打包Web App 最近做了一款小游戏,定位是移动端访问,思来想去最后选择了jQuery mobile最为框架,制作差不多以后,是否可以打包成App,恰好以前对PhoneGap ...

  2. Python 数据排序和列表迭代和列表推导应用

    1.In-place sorting 原地排序 data=[6,4,5,2,3,1] print ('before sort', data) data.sort() print ('after sor ...

  3. Force IE to Open Link in New Tab

    1.First, open Internet Explorer and click on Tools and then Internet Options. 2.Now click on the Set ...

  4. HDU3516 树的构造

    题目大意:平面上有n个点,构成一个单调递减的序列.即对于任意的i<j,有xi<xj,yi>yj.现在要用一棵树连接这n个点.树边为有向边,只能向右或向上.求最小的权值. 分析:本题其 ...

  5. purgeIdleCellConnections: found one to purge conn = 0x1e09f7d0

    purgeIdleCellConnections: found one to purge conn = 0x1e09f7d0 你在iOS6下使用3G网络时可能会遇到这条log,不用紧张,这只是苹果的工 ...

  6. 黄聪:Wordpress、PHP使用POST数据过大导致MySQL server has gone away报错原因分析

    错误原因: 当POST的数据超过 max_allowed_packet 就会报 MySQL server has gone away 的错误. 1.查看当前Mysql的 max_allowed_pac ...

  7. ssh整合随笔(注解方式,Spring 管理action)

    Web.xml<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=" ...

  8. BIP_BI Publisher Administrator设定Configuration/Font/Currencies(案例)

    2014-08-08 Created By BaoXinjian

  9. Mac下的eclipse按住ctrl点击无法查看类文件

    问题主要是项目的.project或者.build文件有问题,github上check的另一个项目就没有这样的现象,可以新建一个项目,然后把新建项目的这两个文件一一替换无法ctrl点击的项目中的文件. ...

  10. JAVA 子父类的特点

    一.变量(属性)    this 代表当前对象的引用 this.变量 首先在本类中找所需要的这个变量,如果没有找到再去父类中找    super 用于访问当前对象的父类成员 super.变量 直接在父 ...