【Kafka】微服务学习笔记九:什么是消息中间件&Kafka的介绍及使用_微服务用哪些中间件

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


### 2.安装Kafka


(1)拉取镜像(注意版本对应)



docker pull wurstmeister/kafka:2.12-2.3.1


(2)创建容器(注意修改成自己的ip地址)



docker run -d --name kafka
–env KAFKA_ADVERTISED_HOST_NAME=4.24.52.122
–env KAFKA_ZOOKEEPER_CONNECT=4.24.52.122:2181
–env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://4.24.52.122:9092
–env KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092
–env KAFKA_HEAP_OPTS=“-Xmx256M -Xms256M”
–restart=always
-p 9092:9092 wurstmeister/kafka:2.12-2.3.1


(3)查看日志



docker logs kafka


如果你的也是云服务器,查看日志时候出现如下情况


![9868c76e458449ea8616ca8fda4f9110.png](https://img-blog.csdnimg.cn/9868c76e458449ea8616ca8fda4f9110.png)


         这时候你就是你的2181端口还未开放,需要自己到防火墙上面进行端口开放设置,除了开放2181端口,9092端口也是需要开放的。


**注意**:要是你的服务器不是云服务器,你可以将-p 9092:9092替换成--net=host,表示直接使用容器宿主机的网络命名空间,即没有独立的网络环境,它使用宿主机的ip和端口。使用云服务器的话则使用-p参数进行端口映射。


## 三:入门案例


### 1.引入依赖



org.apache.kafka kafka-clients ```

2.配置生产者

package com.my.kafka;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.Properties;

/**
 * 生产者
 */
public class ProducerDemo {
    public static void main(String[] args) {
        //1.kafka的配置信息
        Properties pro = new Properties();

        //Kafka的连接地址
        pro.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"4.234.52.122:9092");
        //发送失败,失败重连次数
        pro.put(ProducerConfig.RETRIES_CONFIG,5);
        //消息key的序列化器
        pro.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
        //消息value的序列化器
        pro.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");

        //2.生产者对象
        KafkaProducer<String,String> producer = new KafkaProducer<String, String>(pro);

        //3.封装发送消息
        ProducerRecord<String, String> message = new ProducerRecord<>("my-topic", "asd007", "hello kafka");

        //4.发送消息
        producer.send(message);

        //5.关闭消息通道(必选)
        producer.close();
    }
}

代码解释:上面设置序列化器时候,我们怎么知道序列化器的引用地址呢?你可以点击项目左下角的“外部库”:
ea74e537ac9d4220a79d9e94e8decbe0.png

往下翻找到org.apache.kafka并进入common包里面

a49945aebd584186a78c66d7948af601.png

然后找到serialization包,找到下面两个类:

3ba6bdb0ce6f4f4c87ee00f18ab4c869.png

b6d629ebae274c199667c3935f096337.png

直接复制引用即可(下面的消费者也是如此,只不过需要复制的是反序列化的类)。

3.配置消费者

package com.my.kafka;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

/**
 * 消费者
 */
public class ConsumerDemo {
    public static void main(String[] args) {
        //1.添加Kafka配置信息
        Properties pro = new Properties();

        //Kafka的连接地址
        pro.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"4.234.52.122:9092");
        //消费者组
        pro.put(ConsumerConfig.GROUP_ID_CONFIG,"group2");
        //消息key的反序列化器
        pro.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        //消息value的反序列化器
        pro.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");

        //2.消费者对象
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(pro);

        //3.订阅主题
        consumer.subscribe(Collections.singletonList("my-topic"));

        //4.设置线程一种处于监听状态
        while (true) {
            //5.获取消息
            ConsumerRecords<String, String> messages = consumer.poll(Duration.ofMillis(1000)); //设置每秒钟拉取一次
            for (ConsumerRecord<String, String> message : messages) {
                System.out.print(message.key() + ":");
                System.out.println(message.value());
            }
        }

    }
}

四:结果测试

1.单消费者

启动消费者,然后启动生产者,可以看到成功接收到消息:

cc996ef654d14024b800201fa42dc4ce.png

2.多消费者同组

首先需要创建多个消费者

9cea45a1c6e047ddaf80e59f06939f83.png

然后继续发送消息

a3be8efb865445e79bb5170e71f08095.png

可以看到只有一个消费者能够获取到消息。

3.多消费者不同组

将消费者1设置在group1,将消费者2设置在group2,然后生产者发送消息:

fe109f893533423b8cc09805bf665a89.png

可以看到两个消费者都能接收到消息。

4.总结

  • 生产者发送消息,多个消费者订阅同一个主题,只能有一个消费者收到消息(一对一)
  • 生产者发送消息,多个消费者订阅同一个主题,所有消费者都能收到消息(一对多)

五:Kafka高可用设计(深入原理)

1.集群

3f9537afde10482e8055ac2c08cbfa1b.png

  • Kafka 的服务器端由被称为 Broker 的服务进程构成,即一个 Kafka 集群由多个 Broker 组成
  • 这样如果集群中某一台机器宕机,其他机器上的 Broker 也依然能够对外提供服务。这其实就是 Kafka 提供高可用的手段之一

2.备份机制(Replication)

Kafka的副本分为领导者和追随者,只有Leader副本才能对外提供读写服务(也有资料说Kafka2.4之后社区通过引入新的Broker参数使得Follower副本能有限度地提供读服务),响应Client请求,Follower副本只是采用拉(PULL)方式被动地同步Leader中的数据,见下图:

a866b8feb9594a4db049a0663df6aa89.png

首先我们先了解几个概念:

  • AR(Assigned Repllicas):一个分区里面所有的副本(不区分leader和follower)
  • ISR(In-Sync Replicas):能够和leader保持同步的follower+leader本身组成的集合
  • OSR(Out-Sync Replicas):不能和leader保持同步的follower集合

需要注意的是,Kafka只会保证ISR中的副本实现和Leader同步,Kafka一定会保证Leader接收到消息之后完全同步给ISR中所有副本,ISR的机制保证了处于ISR内部的Follower都可以和Leader保持同步,一旦出现故障或者延迟(一段时间没有同步),该Follower就会被踢出ISR。

为什么会出现ISR呢?世界上没有完全稳定的系统,假如一个Kafka节点的Leader副本出现了问题,这就需要Follower来竞争称为新的Leader,那么这时候是所有的Follower都能参与竞争吗?显然是不可以的,因为并不是所有的Follower都能保持和原Leader数据高同步,假如一个Follower的数据量明显少于Leader的数据量,那么这时候它就不具备竞争资格,这时候ISR的重要性便体现出来了。要选举新的Leader时候,Kafka会优先从ISR中选取,如果ISR中的节点都不行了,这时候才会从OSR中选取。

前面提到同步率跟不上的Follower会被踢出ISR,那么什么原因会导致不同步呢?主要有如下三点:

  • 同步数据请求速度追不上:follower副本在一段时间无法追上leader副本端的消息接收速度。比如follower副本的网络I/O阻塞,这会导致follower副本同步leader副本的速度大大降低。你可以这么理解,如果leader副本的消息流入速度大于follower副本的拉取速度时,你follower就是实时同步有什么用?相关参数为replica.lag.max.messages,该参数用来检测同步数据请求速度追不上的问题,如果ISR中的副本消息数落后于leader副本的消息数超过了该参数的设置,将会被踢出ISR。但是这个参数在kafka0.9.0.9版本之后被移除,至于为什么会被移除,主要原因还是当数据高峰时候Follower数据拉取速度跟不上Leader流入速度,而到了低峰时段Follower又能够慢慢追赶回来,假如在高峰时候就将其踢出ISR这显然是不太合理的。
  • 进程卡住:follower副本一段时间无法向leader发出请求,比如follower频繁的进行GC。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

715701153979)]
[外链图片转存中…(img-UTcfJV8N-1715701153979)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值