hi~boy2

75 阅读12分钟

1、kafka

1.1 角色定义

1、broker

Kafka 的服务器端由被称为 Broker 的服务进程构成,即一个 Kafka 集群由多个 Broker 组成,Broker 负责接收和处理客户端发送过来的请求,以及对消息进行持久化。虽然多个 Broker 进程能够运行在同一台机器上,但更常见的做法是将不同的 Broker 分散运行在不同的机器上,这样如果集群中某一台机器宕机,即使在它上面运行的所有 Broker 进程都挂掉了,其他机器上的 Broker 也依然能够对外提供服务。这其实就是 Kafka 提供高可用的手段之一。

2、topic

发布订阅的对象是主题,你可以为每个业务、每个应用甚至是每类数据都创建专属的主题。

3、producer

发布消息的客户端应用程序称为生产者

4、consumer

而订阅这些主题消息的客户端应用程序就被称为消费者。

5、partition

Kafka 中的分区机制指的是将每个主题划分成多个分区(Partition),每个分区是一组有序的消息日志。生产者生产的每条消息只会被发送到一个分区中,也就是说如果向一个双分区的主题发送一条消息,这条消息要么在分区 0 中,要么在分区 1 中。

6、group

所谓的消费者组,指的是多个消费者实例共同组成一个组(groupId)来消费一组主题。每个分区只能有一个消费者,这一个消费者可以消费多个分区。

7、offset

每个消费者在消费消息的过程中必然需要有个字段记录它当前消费到了分区的哪个位置上,这个字段就是消费者位移(Consumer Offset)。注意,这和分区位移是不同的。分区位移的是分区内的消息位置,它是不变的,即一旦消息被成功写入到一个分区上,它的位移值就是固定的了。而消费者位移则不同,它是消费者消费进度的指示器嘛,不同消费者的位移是不同的。

可以理解为书签

8、Replication

副本是把相同的数据拷贝到多台机器上来实现高可用。分为领导者副本和跟随者副本。

领导者对producer和consumer提供读写服务;而后者只是向领导者副本发送请求,请求领导者把最新生产的消息发给它,与领导者的同步,不对外提供服务。

9、Rebalance

再均衡是kafka实现高可用的手段,当一个consumer实例挂掉后,kafka会检测到并将挂掉实例负责的分区,重新分配给其他消费者。是消费者端实现高可用的重要手段。

1.2、生产者配置

① acks

broker的确认数,通常有0、1、all三种常见配置。
acks 如果设置为零,那么生产者将完全不等待服务器的任何确认。记录添加到缓冲区就视为已发送。这种方案有最高的吞吐率,但是不保证消息是否真的发送成功。
acks 如果设置为1,表示领导者确认后就视为已发送。不会等待跟随者同步成功。提供了不错的吞吐,但收到消息后跟随者还没同步leader就挂掉了,会丢消息。
acks 设置为all,表示领导者和跟随者都确认成功,才视为已发送。效率是三者里面最低的。如果要确保不丢消息就要设置为all

② buffer.memory

指定Producer端用于缓存消息的缓冲区大小,kafka采用的是异步发送的消息架构,prducer启动时会首先创建一块内存缓冲区用于保存待发送的消息,然后由一个专属线程负责从缓冲区读取消息进行真正的发送。默认32m

消息持续发送过程中,当缓冲区被填满后,producer立即进入阻塞状态直到空闲内存被释放出来,这段时间不能超过max.blocks.ms设置的值,一旦超过,producer则会抛出TimeoutException 异常,因为Producer是线程安全的,若一直报TimeoutException,需要考虑调高buffer.memory了。
用户在使用多个线程共享kafka producer时,很容易把 buffer.memory 打满。

③ max.block.ms

最大阻塞时间,如果生产消息的速度过快导致buffer满了的时候,将阻塞max.block.ms配置的时间,超时将会抛TimeoutException异常
默认1分钟

④ compression.type

数据的压缩类型,broker会自动适应producer的压缩算法,有效值为none、gzip、snappy、lz4或zstd,压缩是为了节省带宽。压缩发生在生产者端,broker不做处理,由consumer解压还原为之前的消息。
默认 无压缩 推荐配置一种适合的压缩算法,可以大幅度的减缓网络压力和Broker的存储压力。

⑤ retries

失败后的自动重试次数,默认 Integer.MAX_VALUE 客户端会一直进行重试直到broker返回ack

⑥ batch.size

批次大小,当多个消息发送到相同分区时,生产者会将消息打包到一起,而不是一条条发送,以减少请求交互. 这个东西也不能无限的大,过于大了之后,要是数据老是缓冲在Batch里迟迟不发送出去,那么岂不是你发送消息的延迟就会很高。默认16kb
一般和linger.ms搭配使用

⑦ linger.ms

批处理延迟
比如有的时刻消息比较少,过了很久也没有凑够16KB,这样消息延迟会很大。所以需要设置一个时间,时间到了,没有凑够15K,也将消息发出去。
一般和batch.size搭配使用,同时设置batch.size和 linger.ms,就是哪个条件先满足就都会将消息发送出去

1.3、消费者配置

① fetch.max.bytes

配置 Consumer 在一次拉取请求中从 Kafka 中拉取的最大数据量,默认50m

② max.partition.fetch.bytes

这个参数用来配置从每个分区里返回给 Consumer 的最大数据量,默认1m。
这个参数与 fetch.max.bytes 参数相似,只不过前者用来限制一次拉取中每个分区的消息大小,而后者用来限制一次拉取中整体消息的大小。

③ fetch.min.bytes

指定了消费者从服务器获取记录的最小字节数。如果可用的数据量小于 fetch.min.bytes 指定的大小,那么它会等到有足够的可用数据时才把它返回给消费者。这样可以降低消费者和 broker 的工作负载。

和fetch.max.wait.ms搭配使用,一般不用配置。

④ fetch.max.wait.ms

从broker拉取数据最大等待时间。
同时设置fetch.min.bytes和 fetch.max.wait.ms,哪个条件先满足就都会拉取消息。
默认500ms,一般不用配置。

⑤ group.id

消费者组。多个消费者实例共同组成的一个组,同时消费多个分区以实现高吞吐。

⑥ heartbeat.interval.ms

心跳间隔,和session.timeout.ms搭配使用。
heartbeat线程每隔heartbeat.interval.ms时间向broker-coordinator发送心跳包,证明还活着。
如果group coordinator在一个session.timeout.ms周期内未收到consumer的心跳,就认为consumer已经挂掉了,会将该消费者移出组,并触发rebalance
默认值3s

⑦ session.timeout.ms

会话超时时间和heartbeat.interval.ms搭配使用
默认只30s,其决定了Consumer存活的时间间隔。

⑧ auto.offset.reset

当Kafka不再存在当前偏移量时的处理方式

latest 从最新offset开始消费
earliest 从最早的offset开始消费

默认 latest

⑨ enable.auto.commit

是否开启自动提交
如果开启自动提交,会在调用poll方法时,将上次poll返回消息的最大位移提交上去。自动提交会导致重复消费
默认 true

⑩ max.poll.records 和 max.poll.interval.ms

max.poll.records每次拉取的最大记录数,与max.poll.interval.ms搭配使用,直接从缓存中取。
默认500

max.poll.interval.ms最大拉取时间间隔。
如果两次poll操作间隔超过了这个时间,broker就会认为这个consumer处理能力太弱,会将其踢出消费组,将分区分配给别的consumer消费,触发rebalance。

partition.assignment.strategy

分区分配策略
RangeAssignor(范围):该策略会把主题的若干个连续的分区分配给消费者
RoundRobinAssignor(轮询):该策略把主题的所有分区逐个分配给消费者
StickyAssignor(粘性):粘性的分区分配策略。该策略会尽可能地保留之前的分配方案,尽量实现分区分配的最小变动。

2Java线程池

Java通过Executors提供四种线程池

(1)newFixedThreadPool 创建一个固定数量的线程池,当有任务提交时,如果线程池中空闲,则立即执行,若没有空闲,则会在队列中等待。

(2)newSingleThreadExecutor 创建一个单线程的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

(3)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收(60秒),则新建线程

(4)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

3jvm

新生代收集器:****

1、Serial单线程收集器

Serial收集器是最基本、发展历史最悠久的收集器,在JDK1.3.1之前是虚拟机新生代收集的唯一选择。这个收集器是一个单线程的收集器,但它的单线程的意义并不仅仅说明它使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,知道它收集结束。“Stop the World”这个名字也许听起来很酷,但这项工作实际上是由虚拟机在后台自动发起和自动完成的,在用户不可见的情况下把用户正常工作的线程全部停掉,这对很多应用来说都是难以接受的。图中示意了Serial/Serial Old收集器的运行过程。 2, ParNew收集器 (多线程版本)

可以认为是Serial的升级版,因为它支持多线程[GC线程],而且收集算法、Stop The World、回收策略和Serial一样,就是可以有多个GC线程并发运行,它是HotSpot第一个真正意义实现并发的收集器。默认开启线程数和当前cpu数量相同【几核就是几个,超线程cpu的话就不清楚了 - -】,是很多运行在Server模式下虚拟机中首选的新生代收集器,

3、 Parallel Scavenge

采用复制算法的收集器,和ParNew一样支持多线程,也是采用复制算法的收集器****

但是该收集器重点关心的是吞吐量【吞吐量 = 代码运行时间 / (代码运行时间 + 垃圾收集时间) 如果代码运行100min垃圾收集1min,则为99%】

对于用户界面,适合使用GC停顿时间短,不然因为卡顿导致交互界面卡顿将很影响用户体验。

对于后台,高吞吐量可以高效率的利用cpu尽快完成程序运算任务,适合后台运算

Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis阐述一斤直接设置吞吐量大小的-XX:GCTimeRatio参数。

由于与吞吐量关系密切,Parallel Scavenge收集器也经常被称为吞吐量优先收集器。除了上述两个参数外,Parallel Scavenge收集器还有一个参数-XX:UseAdaptiveSizePolicy值得关注。这是一个开关参数,当这个参数打开之后,就不需要手工指定新生代的大小、Eden与Survivor去的比例、晋升老年代对象大小等细节参数,虚拟机会根据当前系统的运行状况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式成为GC自适应的调节策略

Parallel Scavenge注重吞吐量,所以也成为"吞吐量优先"收集器。

老年代收集器:****

4 Serial Old

和新生代的Serial一样为单线程,Serial的老年代版本,不过它采用"标记-整理算法",这个模式主要是给Client模式下的JVM使用。

如果是Server模式有两大用途

1.jdk5前和Parallel Scavenge搭配使用,jdk5前也只有这个老年代收集器可以和它搭配。

2.作为CMS收集器的后备。

6 CMS

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿的时间最短,给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。启用CMS:-XX:+UseConcMarkSweepGC

CMS收集器是基于“标记-清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤:

1初始标记(CMS initial mark):标记一下GC Roots能直接关联到的对象,速度很快

2并发标记(CMS concurrent mark):GC Roots Tarcing过程,即可达性分析

3重新标记(CMS remark):为了修正因并发标记期间用户程序运作而产生变动的那一部分对象的标记记录,会有些许停顿,时间上一般 初始标记 < 重新标记 < 并发标记

4并发清除(CMS concurrent sweep)

其中,初始标记、重新标记着两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。