定义:
卡夫卡一款的英文高储存的分布式发布订阅消息系统- .kafak是什么?
特点:
1. 高吞吐,低延迟:每秒可以处理几十万条消息,延迟最低只有几毫秒;
2. 可扩展性:卡夫卡集群支持热扩展;
3. 持久性,可靠性:消息被持久化到本地磁盘,并支持数据备份防止数据丢失;
4. 容错性:允许集群中节点失败,若副本数量为N,则允许n-1个个个节点失败;
5. 高并发:支持数个客户端同时读写;
卡夫卡优点有哪些?
应用场景:
1.日志收集:收集各种服务的日志,通过卡夫卡统一接口服务的方式开放给各种消费品;
2.消息系统:解耦生产者,消费者,缓存消息等;
3.用户活动跟踪:用来记录网络用户或应用程序用户的各种活动;
4.运营指标:记录运营监控数据,包含收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告;
5.流处理:结合Spark Streaming和Storm;
6.时间源;
卡夫卡用在哪?
架构组件:
生产者:生产者,生产消息到话题的一方;
消费者:消费者,订阅话题消费消息的一方;
经纪人:消息服务器;
主题:主题,消息存放的目录;
Consumer Group:kafka采用广播的方式进行消费分发,而消费者集群在消费某个话题时,zookeeper会为该集群建立抵消消费偏移量,最新的消费者加入并消费该主题时,可以从最新的抵消点开始消费;
分区:kafka采用对数据文件切片(分区)的方式可以讲一个主题分布式存储到多个Broker上,一个topic可以分为多个partition。在多个consumer并发访问一个分区会有同步锁机制;
你好字:
1.加入Maven的仓库,以0.10.0.0版本为例:
<! - 1.kafka-jar - >
<依赖性>
<的groupId> org.apache.kafka </的groupId>
<artifactId的> kafka_2.10 </ artifactId的>
<版本> 0.10.0.0 </版本>
</依赖性>
<! - 1.1。依赖于slf4j-log4j12 - >
<依赖性>
<的groupId> org.slf4j </的groupId>
<artifactId的> SLF4J-log4j12 </ artifactId的>
<版本> 1.7。 7 </
依赖性>
<! - 2.依赖kafka客户端 - >
<依赖性>
<的groupId> org.apache.kafka </的groupId>
<artifactId的>卡夫卡的客户端< / artifactId的>
<版本> 0.10.2.1 </版本>
</依赖性>
2.创建生产者
/ **
* <p>描述:生产者生产者</ p>
*版权:Copyright(c)2018 </ p>
* <p>日期:2018年5月28日
*公司:马赛克</ p>
* @作者马赛克
* @version V1.0
* /
公共类制作人{
/ **
*日志
* /
private static final Logger log = LoggerFactory.getLogger(Producer.class);
/ **
*生产者生产消息到Broker
*参见
* <H4>生产者 - >经纪人</ H4>
* /
public static void main(String [] args){
// 1。配置生产者相关属性
//属性:属性值
属性props = new Properties();
//设置代理服务地址:10.8.5.197:9092; 多个代理地址使用 '' 分隔
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,“10.8.5.198:9092”);
//设置请求时,验证
props.put(ProducerConfig.ACKS_CONFIG,“all”);
//设置请求失败,重试次数
props.put(ProducerConfig.RETRIES_CONFIG,0);
//设置内存缓存区大小
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG,33554432);
//设置消息按键序列化器
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
//设置消息值序列化器
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,BeanSerializer.class.getName());
//ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
// 2。创建生产者
KafkaProducer <String,Object> producer = new KafkaProducer <>(props);
// 3。生产者生产消息到经纪人
for(int i = 0; i <9; i ++){
//将键,值序列化为字节数组
int random =(int)(Math.random()* 10000);
//3.1。生产者生产消息,不关注消息丢失
//producer.send(ProducerRecord);
producer.send(new ProducerRecord <String,Object>(“topic-ids”,String.valueOf(random),Constants.getId()));
//producer.send(new ProducerRecord <K,V>(topic,value));
// new ProducerRecord <K,V>(topic,key,value)
//新ProducerRecord <K,V>(主题,分区,键值)
//新ProducerRecord <K,V>(主题,分区,时间戳,键值)
// topic:消息主题,partition:分区数,timestamp:时间戳,key,value
DeviceBuilder builder = new DeviceBuilder();
设备设备= builder.setId(随机)
.setMgntIp(“10.36.3。”+(i + 1))
.setDeviceName(“测试”+(i + 1))
.setCiKey(getRandomCi())
.setVendorKey(getRandomVendor())
。建立();
//3.2。生产者生产消息,异常后支持回调,防止消息丢失
//producer.send (ProducerRecord,Callback);
producer.send(新ProducerRecord <String,Object>(“topic-devices”,String.valueOf(random),device),new Callback(){
@覆盖
public void onCompletion(RecordMetadata metadata,Exception exection){
//发送失败时,针对该记录数据的回调方法
if(metadata!= null){
log.info(“offset:{},partition:{},device:{}”,metadata.offset(),metadata.partition(),device.getMgntIp());
}
if(exection!= null){
log.error(“发送失败”,exection);
}
}
});
log.info(“发送主题成功!\ n值:{”+ device.getId()+“”+“}”);
}
// 4。生产者生产消息结束
producer.close();
}
private static String getRandomCi(){
String [] cis = {“路由器”,“交换机”,“防火墙”};
int random =(int)(Math.random()* 3);
return cis [random];
}
私人静态字符串getRandomVendor(){
String [] vs = {“华为”,“思科”,“迈普”};
int random =(int)(Math.random()* 3);
返回vs [随机];
}
}
2.1序列化传输对象时,将对象转换成字节组进行传输
* <p>描述:对象序列化器</ p>
* <p>版权:Copyright(c)2018 </ p>
* <p>日期:2018年5月29日</ p>
* <p>Company: 马赛克</p>
* @author 马赛克
* @version V1.0
*/
public class BeanSerializer implements Serializer<Object> {
/**
* log
*/
private static final Logger log = LoggerFactory.getLogger(BeanSerializer.class);
@Override
public void close() {
//调用 producer.close()之后,关闭序列化解析器
log.info("BeanSerializer is Close !");
}
@Override
public void configure(Map<String, ?> map, boolean isKey) {
}
@Override
public byte[] serialize(String topic, Object data) {
log.info("use serialize to Byte !");
return BeanUtils.converToByte(data);
}
}
3.生产消息
value:{ 7204 }
value:{ 6560 }
value:{ 4141 }
value:{ 7605 }
value:{ 9816 }
value:{ 1058 }
value:{ 258 }
value:{ 5088 }
value:{ 3588 }
4.创建消费者
/**
* <p>Description: 消费者 </p>
* <p>Copyright: Copyright (c) 2018 </p>
* <p>Date: 2018年5月29日 </p>
* <p>Company: 马赛克 </p>
* @author 马赛克
* @version V1.0
*/
public class Consumer {
/**
* 消费者从broker中取消息
* @see
* <H4>Broker --> Consumer</H4>
*/
public static void main(String[] args) {
//1.配置消费者相关信息
//属性:值
Properties props = new Properties();
//设置broker服务地址:10.8.5.197:9092
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "10.8.5.198:9092");
//设置消费者组Id group.id
props.put(KafkaProperties.GROUP_ID, "group-tk");
//设置启动自动提交 enable.auto.commit
props.put(KafkaProperties.ENABLE_AUTO_COMMIT, true);
//设置自动提交间隔 auto.commit.interval.ms
props.put(KafkaProperties.AUTO_COMMIT_INTERVAL_MS, 1000);
//设置会话有效时间 session.timeout.ms
props.put(KafkaProperties.SESSION_TIMEOUT_MS, 10000);
//设置消息key反序列化器 key.deserializer
props.put(KafkaProperties.KEY_DESERIALIZER, StringDeserializer.class.getName());
//设置消息value反序列化器 value.deserializer :
props.put(KafkaProperties.VALUE_DESERIALIZER, BeanDeserializer.class.getName());
//2.创建消费者
@SuppressWarnings("resource")
KafkaConsumer<String, Object> consumer = new KafkaConsumer<String, Object>(props);
//3.订阅消息
//3.1.要想broker中订阅要消费的消息
//3.1.1.确定需要订阅的主题: topics
Collection<String> topics = new HashSet<String>();
topics.add("topic-device");
topics.add("topic-ids");
//3.1.2.订阅主题
consumer.subscribe(topics);
//topic
Set<String> scripts = consumer.subscription();
scripts.stream().forEach(script -> {
System.out.println("consumer scription : "+ script);
});
//4.接收消息
do{
//每0.1秒消费一次消息
ConsumerRecords<String, Object> records = consumer.poll(1);
for (ConsumerRecord<String, Object> record : records) {
System.out.println("offset: "+record.offset() + ", partition: " + record.partition() + ", topic:" + record.topic() + ", record-key:" + record.key() + ", record-value:"+ record.value().toString());
}
}while(true);
}
}
4.1.反序列化对象时,将字节组转换成对象
/**
* <p>Description: 对象反序列化器 </p>
* <p>Copyright: Copyright (c) 2018 </p>
* <p>Date: 2018年5月29日 </p>
* <p>Company: 马赛克</p>
* @author 马赛克
* @version V1.0
*/
public class BeanDeserializer implements Deserializer<Object> {
/**
* log
*/
private static final Logger log = LoggerFactory.getLogger(BeanDeserializer.class);
@Override
public void close() {
log.info("BeanDeserializer is Close !");
}
@Override
public void configure(Map<String, ?> map, boolean isKey) {
}
@Override
public Object deserialize(String topic, byte[] bytes) {
log.info("user deserialize to Object !");
return BeanUtils.converToObj(bytes);
}
}
5.对象转换工具类
/**
* <p>Description: BeanUtils </p>
* <p>Copyright: Copyright (c) 2018 </p>
* <p>Date: 2018年5月29日 </p>
* <p>Company: 马赛克</p>
* @author 马赛克
* @version V1.0
*/
public class BeanUtils {
//防止实例化
private BeanUtils(){ }
/**
* 将对象转换成字节组
* @param obj 对象
* @return byte[]
*/
public static byte[] converToByte(Object obj){
byte[] bytes = null;
try {
//字节输出流
ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
//对象输出流
ObjectOutputStream objOutStream = new ObjectOutputStream(byteOutStream);
//写入对象
objOutStream.writeObject(obj);
objOutStream.flush();
bytes = byteOutStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return bytes;
}
/**
* 将字节码转换成对象
* @param bytes 字节码
* @return Object
*/
public static Object converToObj(byte[] bytes){
Object obj = null;
try {
//字节输入流
ByteArrayInputStream byteInStream = new ByteArrayInputStream(bytes);
//对象输入流
ObjectInputStream objOutStream = new ObjectInputStream(byteInStream);
//写入对象
obj = objOutStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}
6.消费消息,这里就不详细打印了
offset: 21, partition: 2, topic:topic-ids, record-key:7204, record-value:fde76c824d7347238ded1fe07b92fdd8
offset: 22, partition: 2, topic:topic-ids, record-key:6560, record-value:3af21949ceb74960acab9d634fdf8bb7
offset: 23, partition: 2, topic:topic-ids, record-key:258, record-value:ea3fa441692640fdad49617a27da4548
offset: 24, partition: 2, topic:topic-ids, record-key:5088, record-value:7b2db6774fc04228bf36f5b6ee8d8f6c
offset: 25, partition: 1, topic:topic-ids, record-key:9816, record-value:586747a189654c60a8f0c7db2197e064
主题:topic-id,record-key:4141,记录值:
26,partition:1,topic:topic-ids,record-key:1058,record-value:a5fd8aee84434b7fad7039f67d98b8f3偏移量:26,分区:0, e5a4473a8a3649949c3134108b598bc6
偏移量:27,分区:0,主题:主题的IDS,记录键:7605,记录值:57a83d5d309244769748ca94d7628818
偏移量:28,分区:0,主题:主题-ID,记录键值:3588,记录值:e6c05210578b4c75b1d63301241073bd