Kafka特性:(1)高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。(2) 可扩展性:kafka集群支持热扩展。(3)持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失。(4) 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)。(5) 高并发:支持数千个客户端同时读写。
使用场景:(1)日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。(2)消息系统:解耦和生产者和消费者、缓存消息等。(3)用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。(4) 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。(5) 流式处理:比如spark streaming和storm
Kafka对硬盘的连续读取性能是很高的,可能高于对内存的随机读取。Kafka将海量的数库存储到硬盘中,是持久化的。Broke是指kefka的服务器;Zookeeper是一个独立的应用,可以用来管理一个集群;
消息队列大致有两种实现方式:1、点对点式的,生产者往消息队列写数据,消费者从消息队列一个一个地拿数据;2、发布订阅模式:生产者将消息放到了某一个位置,可以同时有很多个消费者来订阅(读取)这个消息;生产者将消息发布到的某个位置就叫Topic;partition对位置的分区;对Topic分为了多个区域,便于多个线程同时处理,提高性能;offset为消息存放在某区域的一个索引;
Leader Replica:主副本,可以处理请求作响应;Follower Replica:从副本,只是做备份;当主副本挂掉的时候,可以从从副本中选出一个来作为新的主副本;
遇到的问题:kafka应该使用默认的版本,不然又杂又乱,版本依赖不同;
之前面向切面编程,将所有的service目录下的文件(由于只有Controller层调用了service)作为切入点访问,其中实现的是统一的日志记录:需要获取到了得到HttpServletRequest;而加上kafka消息队列在EventConsumer类中也调用了MessageService,而EventConsumer是不会出现HttpServletRequest的,所以会报空指针异常。
改进:
@Before("pointcut()") public void before(JoinPoint joinPoint) { // 用户[1.2.3.4],在[xxx],访问了[com.liu.community.service.xxx()]. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if(attributes == null){ //====如果不是常规的页面Collector对service的调用,则attributes为空;如kafka中EventConsumer调用了service return; } HttpServletRequest request = attributes.getRequest();//得到HttpServletRequest String ip = request.getLocalAddr();//ip String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());//时间 //得到切入处的:getDeclaringTypeName类名,getName方法名; String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(); logger.info(String.format("用户[%s],在[%s],访问了[%s].", ip, now, target)); }
再经过了一次封装:将消息队列信息封装为事件;
封装事件:
public class Event {
//事件对信息进行了包装
//封装:点赞、评论、关注三类情形;
//topic指哪种情形;userId操作的用户id,entityId对什么实体操作的id,
// entityType对什么实体操作的类型,entityUserId为该被操作实体的用户id
private String topic;
private int userId;
private int entityType;
private int entityId;
private int entityUserId;
Map<String,Object> data = new HashMap<>();//支持可扩展
public String getTopic() {
return topic;
}
public Event setTopic(String topic) {
this.topic = topic;
return this;//即灵活,又方便;在使用的时候可以:setTopic().setUserId().......这样来使用
}
public int getUserId() {
return userId;
}
public Event setUserId(int userId) {
this.userId = userId;
return this;//即灵活,又方便;在使用的时候可以:setTopic().setUserId().......这样来使用
}
public int getEntityType() {
return entityType;
}
public Event setEntityType(int entityType) {
this.entityType = entityType;
return this;//即灵活,又方便;在使用的时候可以:setTopic().setUserId().......这样来