KakfaSpout自定义scheme
一.Mapper和Scheme
scheme:将kafka传到spout里的数据格式进行转化. record->tuple
mapper:将storm传到kafka的数据格式进行转化.tuple->record
二.为什么要自定义消息格式
在很多需求里, 从kafka传递过来的数据并不是单纯的string, 可以是任意对象.当我们需要根据对象的某个属性进行分组时, 默认的new Fields("bytes")就不太适合.但是消息传递的形式还是string.我们可以在传入kafka之前使用fastJson的转化方法将实体对象转化成jsonString.
到了scheme在转换成实体类对象.
三.怎么更改scheme
构建kafkaSpout时我们要配置很多参数, 可以看一下kafkaConfig代码.
public final BrokerHosts hosts; //用以获取Kafka broker和partition的信息
public final String topic;//从哪个topic读取消息
public final String clientId; // SimpleConsumer所用的client id
public int fetchSizeBytes = 1024 * 1024; //发给Kafka的每个FetchRequest中,用此指定想要的response中总的消息的大小
public int socketTimeoutMs = 10000;//与Kafka broker的连接的socket超时时间
public int fetchMaxWait = 10000; //当服务器没有新消息时,消费者会等待这些时间
public int bufferSizeBytes = 1024 * 1024;//SimpleConsumer所使用的SocketChannel的读缓冲区大小
public MultiScheme scheme = new RawMultiScheme();//从Kafka中取出的byte[],该如何反序列化
public boolean forceFromStart = false;//是否强制从Kafka中offset最小的开始读起
public long startOffsetTime = kafka.api.OffsetRequest.EarliestTime();//从何时的offset时间开始读,默认为最旧的offset
public long maxOffsetBehind = Long.MAX_VALUE;//KafkaSpout读取的进度与目标进度相差多少,相差太多,Spout会丢弃中间的消息
public boolean useStartOffsetTimeIfOffsetOutOfRange = true;//如果所请求的offset对应的消息在Kafka中不存在,是否使startOffsetTime
可以看到, 所有的配置项都是public, 所以当我们实例化一个spoutConfig之后, 可以通过直接引用的方式进行更改属性值.
我们可以看构建kafkaspout的代码:
ZkHosts zkHosts = new ZkHosts(zkHost);
// zk对地址有唯一性标识
String zkRoot = "/" + topic;
String id = UUID.randomUUID().toString();
// 构建spoutConfig
SpoutConfig spoutConf = new SpoutConfig(zkHosts, topic, zkRoot, id);
spoutConf.scheme = new SchemeAsMultiScheme(new SensorDataScheme());
spoutConf.startOffsetTime = OffsetRequest.LatestTime();
KafkaSpout kafkaSpout = new KafkaSpout(spoutConf);
四.怎么自定义scheme
我们有这样一个需求,有一个实体类如下:
public class SensorData implements Serializable {
// 设备Id;
private String deviceId;
// 型号id
private String dmPropertiesId;
// 通道名称;
private String channelName;
// 采集的温度值
private double deviceTemp;
// 采集的时间;
private Date date;
}
数据进来kafka到storm消费时, 根据deviceId进行分组.当然, 我们在写入的时候对数据json化, 使用fastjson把实体对象变成字符串, 而不是直接传实体类对象进入kafka(亲测会报错, 无法进行转换).最终数据会在scheme的declare的方法里处理.
Scheme接口:
public interface Scheme extends Serializable {
List<Object> deserialize(ByteBuffer ser);
public Fields getOutputFields();
}
可以看到有两个需要实现的方法, 一个是传过来的byte数据进行转化, 一个是传入下一层bolt的时候以什么字段分组. 跟踪kafka的源码我们可以看到, 他的declare方法最终会调用scheme的方法来确认字段名.
看一下scheme的整体代码:
package dm.scheme; import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List; import org.apache.storm.kafka.StringScheme;
import org.apache.storm.spout.Scheme;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import org.apache.storm.utils.Utils; import com.alibaba.fastjson.JSON; import dm.entity.SensorData;
/**
*
* KafkaRecord 映射 tuple 转化类;
*
* @author chenwen
*
*/
public class SensorDataScheme implements Scheme {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Charset UTF8_CHARSET = StandardCharsets.UTF_8; /**
*
* 反序列化
*/
@Override
public List<Object> deserialize(ByteBuffer byteBuffer) {
// 将kafka消息转化成jsonString
String sensorDataJson = StringScheme.deserializeString(byteBuffer);
SensorData sensorData = JSON.parseObject(sensorDataJson, SensorData.class);
String id = sensorData.getDeviceId();
return new Values(id, sensorData);
}
public static String deserializeString(ByteBuffer byteBuffer) {
if (byteBuffer.hasArray()) {
int base = byteBuffer.arrayOffset();
return new String(byteBuffer.array(), base + byteBuffer.position(), byteBuffer.remaining());
} else {
return new String(Utils.toByteArray(byteBuffer), UTF8_CHARSET);
}
}
@Override
public Fields getOutputFields() {
return new Fields("deviceId", "sensorData"); // 返回字段及其名称;
}
}
KakfaSpout自定义scheme的更多相关文章
- Scheme是什么、怎么自定义Scheme、JLRoutes的使用-备
转到移动端开发后居然现在才用到Scheme真是惭愧惭愧. URL Scheme是什么 相信大家都知道URL. http://www.apple.com就是一个URL. 而://之前的部分就称为Sche ...
- CEF 自定义用户协议(scheme)实现以二进制流的方式显示图片、视频、音频
转载:https://www.cnblogs.com/sinceret/p/10417941.html 转载:https://stackoverflow.com/questions/48811756/ ...
- 在cef中使用自定义协议(scheme)
在谷歌浏览器中点击设置,地址栏里出现的不是普通网址,而是chrome://settings/ 这个地址就是谷歌浏览器的自定义scheme,cef也提供了自定义协议手段.主要是通过 以下几步: 1.继承 ...
- iOS开发系列--App扩展开发
概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...
- 如何实现 javascript “同步”调用 app 代码
在 App 混合开发中,app 层向 js 层提供接口有两种方式,一种是同步接口,一种一异步接口(不清楚什么是同步的请看这里的讨论).为了保证 web 流畅,大部分时候,我们应该使用异步接口,但是某些 ...
- 初识CEF
介绍 CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chromium项目主要是为Google Chrome应用开 ...
- 网页二维码推广App的实现
移动互联网时代,一个APP的平均推广成本早已经超过了10块.而推广通常分二类: 1.已经下载过的用户,可以直接打开应用(一般人的手机上安装的应用都非常多,要快速找到某个应用是很困难的事情,而且Andr ...
- 【转】使用JavaScriptCore在JS和OC间通信
http://www.cocoachina.com/ios/20160623/16796.html iOS 开发中,我们时不时的需要加载一些 Web 页面,一些需求使用 Web 页面来实现可以更可控, ...
- iOS音频篇:AVPlayer的缓存实现
授权转载,作者:明仔Su(简书) 在上一篇文章<使用AVPlayer播放网络音乐>介绍了AVPlayer的基本使用,下面介绍如何通过AVAssetResourceLoader实现AVPla ...
随机推荐
- 使用Nginx实现服务器反向代理和负载均衡
前言 同事总问我Nginx做反向代理负载均衡的问题,因此特意留下一篇扫盲贴! 直接部署服务器的风险 假设,我开发了一个网站,然后买了一台Web服务器和一台数据库服务器,直接部署到公共网络上.如下图,网 ...
- django rest framework 项目创建
Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Rest Framework Django REST Framework可以在Django的基 ...
- HDU 1840 Equations (简单数学 + 水题)(Java版)
Equations 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1840 ——每天在线,欢迎留言谈论. 题目大意: 给你一个一元二次方程组,a(X^2 ...
- 远程连接MySQL数据库问题总结
远程连接MySQL数据库时,陆陆续续遇到了一些杂七杂八的问题,相信很多人也曾经遇到过这类问题,下面总结归纳在下面,方便以后直接查找. 1:出现ERROR 2003 (HY000): Can't con ...
- 反射生成 INSERT 多个对象的 SQL 语句(批量插入)
+ View code private static void insertObject(List<?> objectList) throws IllegalAccessException ...
- C# 函数1 (函数的定义)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 na ...
- Linux进程核心调度器之主调度器schedule--Linux进程的管理与调度(十九)
主调度器 在内核中的许多地方, 如果要将CPU分配给与当前活动进程不同的另一个进程, 都会直接调用主调度器函数schedule, 从系统调用返回后, 内核也会检查当前进程是否设置了重调度标志TLF_N ...
- Jenkins2.32打包Unity项目的记录
前言 使用jenkins来打包unity3d的工程. jenkins :2.50 /2.32.3(长期支持版 建议使用此版本) 操作系统:windows 7 x64 sp1 (打包安卓和win) ,m ...
- python 进程池的简单使用方法
回到python,用一下python的进程池. 记得之前面试的时候,面试官问:你知道进程池的默认参数吗? 我没有回答上来,后来才知道,是有默认参数的.下面就看看它的默认参数 1. 不加参数 from ...
- LeetCode算法题-House Robber(Java实现)
这是悦乐书的第187次更新,第189篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第46题(顺位题号是198).你是一个专业的强盗,计划在街上抢劫房屋. 每个房子都藏着一 ...