【Kafka】

Kafka

什么是Kafka

Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。该项目的目标是为处理实时数据提供一个统一、高吞吐、低延迟的平台。Kafka最初是由LinkedIn开发,并随后于2011年初开源。

kafka软件结构

Kafka是一个结构相对简单的消息队列(MQ)软件

kafka软件结构图

Kafka Cluster(Kafka集群)

Partition(分片)

Producer:消息的发送方,也就是消息的来源,Kafka中的生产者

order就是消息的发送方,在Dubbo中order是消费者,这个身份变化了

Consumer:消息的接收方,也是消息的目标,Kafka中的消费者

stock就是消息的接收方,在Dubbo中stock是生产者,这个身份变化了

Topic:话题或主题的意思,消息的收发双方要依据同一个话题名称,才不会将信息错发给别人

Record:消息记录,就是生产者和消费者传递的信息内容,保存在指定的Topic中

Kafka的特征与优势

Kafka作为消息队列,它和其他同类产品相比,突出的特点就是性能强大

Kafka将消息队列中的信息保存在硬盘中

Kafka对硬盘的读取规则进行优化后,效率能够接近内存

硬盘的优化规则主要依靠"顺序读写,零拷贝,日志压缩等技术"

Kafka处理队列中数据的默认设置:

  • Kafka队列信息能够一直向硬盘中保存(理论上没有大小限制)
  • Kafka默认队列中的信息保存7天,可以配置这个时间,缩短这个时间可以减少Kafka的磁盘消耗

Kafka的安装和配置

必须将我们kafka软件的解压位置设置在一个根目录,文件夹名称尽量短(例如:kafka)

然后路径不要有空格和中文

我们要创建一个空目录用于保存Kafka运行过程中产生的数据

本次创建名称为data的空目录

下面进行Kafka启动前的配置

先到D:\kafka\config下配置有文件zookeeper.properties

找到dataDir属性修改如下

dataDir=D:/data

修改完毕之后要Ctrl+S进行保存,否则修改无效!!!!

注意D盘和data文件夹名称,匹配自己电脑的真实路径和文件夹名称

还要修改server.properties配置文件

log.dirs=D:/data

修改注意事项和上面相同

启动kafka

要想启动Kafka必须先启动Zookeeper

Zookeeper介绍

zoo:动物园

keeper:园长

可以引申为管理动物的人

Linux服务器中安装的各种软件,很多都是有动物形象的

如果这些软件在Linux中需要修改配置信息的话,就需要进入这个软件,去修改配置,每个软件都需要单独修改配置的话,工作量很大

我们使用Zookeeper之后,可以创建一个新的管理各种软件配置的文件管理系统

Linux系统中各个软件的配置文件集中到Zookeeper中

实现在Zookeeper中,可以修改服务器系统中的各个软件配置信息

长此以往,很多软件就删除了自己写配置文件的功能,而直接从Zookeeper中获取

Kafka就是需要将配置编写在Zookeeper中的软件之一

所以要先启动zookeeper才能启动kafka

Zookeeper启动

进入路径D:\kafka\bin\windows

输入cmd进入dos命令行

D:\kafka\bin\windows>zookeeper-server-start.bat ..\..\config\zookeeper.properties

kafka启动

总体方式一样,输入不同指令

D:\kafka\bin\windows>kafka-server-start.bat ..\..\config\server.properties

附录

Mac系统启动Kafka服务命令(参考):

# 进入Kafka文件夹
cd Documents/kafka_2.13-2.4.1/bin/
# 动Zookeeper服务
./zookeeper-server-start.sh -daemon ../config/zookeeper.properties 
# 启动Kafka服务
./kafka-server-start.sh -daemon ../config/server.properties 

Mac系统关闭Kafka服务命令(参考):

# 关闭Kafka服务
./kafka-server-stop.sh 
# 启动Zookeeper服务
./zookeeper-server-stop.sh

在启动kafka时有一个常见错误

wmic不是内部或外部命令

这样的提示,需要安装wmic命令,安装方式参考

我在cmd输入wmic,提示说不是内部或外部命令,也不是可运行的程序或批处理文件,请问如何解决_百度知道

Kafka使用演示

启动的zookeeper和kafka的窗口不要关闭

我们在csmall项目中编写一个kafka使用的演示

csmall-cart-webapi模块

添加依赖

<!--  添加kafka的依赖  -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>
<!--   能够将java对象和json字符串相互转换的依赖   -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>

修改yml文件进行配置

spring:
  kafka:
    # 定义kafka的配置信息:确定kafka的ip和端口
    bootstrap-servers: localhost:9092
    # consumer.group-id必须设置的配置
    # 意思是"话题分组",这个配置的目的是为了区分不同的项目而配置的
    # 本质上,这个分组名称会前缀在所有话题名名称之前,例如话题名称为message,真正发送时csmall.message
    consumer:
      group-id: csmall

在SpringBoot启动类中添加启动Kafka的注解

@SpringBootApplication
@EnableDubbo
// 启动支持Kafka的功能
@EnableKafka
// 为了测试Kafka发送消息的功能
// 我们利用SpringBoot自带的调用工具,周期性的向kafka发送消息
// 下面的注解和Kafka软件没有直接必然的依赖关系
@EnableScheduling
public class CsmallCartWebapiApplication {

    public static void main(String[] args) {
        SpringApplication.run(CsmallCartWebapiApplication.class, args);
    }

}

下面我们就可以实现周期性的向kafka发送消息并接收的操作了

编写消息的发送

cart-webapi包下创建kafka包

包中创建Producer类来发送消息

// 这个类实现周期性向Kafka发送消息
// 因为Spring的任务调度需要将当类保存到Spring容器,所以要加下面的注解
@Component
public class Producer {

    // 直接获取Spring容器中支持向Kafka发送消息的对象
    // 这个对象会在SpringBoot启动时自动的装配到Spring容器
    // KafkaTemplate<[话题的类型],[消息的类型]>
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    // 实现每隔10秒向Kafka发送消息
    int i=1;
    // 设置每隔10秒(10000毫秒)运行一次的调度注解
    @Scheduled(fixedRate = 10000)
    // SpringBoot启动后,每隔10秒运行一次下面的方法
    public void sendMessage(){
        // 实例化一个Cart对象,赋值并发送给Kafka
        Cart cart=new Cart();
        cart.setId(i++);
        cart.setCommodityCode("PC100");
        cart.setUserId("UU100");
        cart.setPrice(RandomUtils.nextInt(90)+10);
        cart.setCount(RandomUtils.nextInt(10)+1);
        // "{"id":"1","price":"58",...}"
        // 利用Gson依赖,将cart对象转换为上面样式的json格式字符串
        Gson gson=new Gson();
        String json=gson.toJson(cart);
        System.out.println("要发送的信息为:"+json);
        // 执行发送
        kafkaTemplate.send("myCart",json);
    }


}

kafka包中创建一个叫Consumer的类来接收消息

接收消息的类可以是本模块的类,也可以是其它模块的类,编写的代码是完全一致

// 需要接收kafka的消息,因为kafkaTemple是Spring容器管理的对象
// 所以消息的接收功能,也要保存到Spring容器中
@Component
public class Consumer {

    // SpringKafka接收消息依靠框架提供的"监听机制"
    // 框架中有一个线程,一直实时关注Kafka的消息接收
    // 如果我们指定的话题名称(myCart)接收了消息,那么这条线程就会自动调用下面的方法
    @KafkaListener(topics = "myCart")
    // 下面方法的参数也是来自监听机制,也就是myCart话题接收到的消息
    public void received(ConsumerRecord<String,String> record){
        // 接收消息的方法参数必须是ConsumerRecord
        // 泛型类型和发送消息时指定的泛型一致<[话题名称的类型],[消息的类型]>
        // record就是消息本身,可以从这个对象中获得具体消息内容
        String json=record.value();
        // 将json格式的字符串转换为java对象
        Gson gson=new Gson();
        // 执行转换
        Cart cart=gson.fromJson(json,Cart.class);
        //{"id":2,"commodityCode":"PC100","price":61,"count":9,"userId":"UU100"}
        System.out.println(cart);

    }
}

RabbitMQ

什么是RabbitMQ

RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。 RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

RabbitMQ特征

1.可靠性(Reliability) RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。

2.灵活的路由(Flexible Routing) 在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。

3.消息集群(Clustering) 多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker

4.高可用(Highly Available Queues) 队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。

5.多种协议(Multi-protocol) RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。

6.多语言客户端(Many Clients) RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。

7.管理界面(Management UI) RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。

8.跟踪机制(Tracing) 如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。

9.插件机制(Plugin System) RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

下载软件

苹果mac系统的同学直接苍老师网站看MacOS安装RabbitMQ的技术贴

RabbitMQ是Erlang语言开发的,所以要先安装Erlang语言的运行环境

下载Erlang的官方路径

OTP Versions Tree

安装的话就是双击

安装过程中都可以使用默认设置,需要注意的是

不要安装在中文路径和有空格的路径下!!!

下载RabbitMQ的官方网址

Installing on Windows — RabbitMQ

安装也是双击即可

不要安装在中文路径和有空格的路径下!!!

配置Erlang的环境变量

要想运行RabbitMQ必须保证系统有Erlang的环境变量

配置Erlang环境变量

把安装Erlang的bin目录配置在环境变量Path的属性中

启动RabbitMQ

找到RabbitMQ的安装目录

可能是:

D:\tools\rabbit\rabbitmq_server-3.10.1\sbin

具体路径根据自己的情况寻找

地址栏运行cmd

输入启动指令如下

D:\tools\rabbit\rabbitmq_server-3.10.1\sbin>rabbitmq-plugins enable rabbitmq_management

结果如下

运行完成后,验证启动状态

RabbitMQ自带一个管理的界面,所以我们可以访问这个界面来验证它的运行状态

http://localhost:15672

登录界面用户名密码

guest

guest

登录成功后看到RabbitMQ运行的状态

如果启动失败,可以手动启动RabbitMQ

参考路径如下

RabbitMQ环境的搭建和报错,差点让我放弃,怀着试试的心态

RabbitMQ的结构

RabbitMQ软件支持很多种消息队列的发送方式的

使用的比较多的是路由模式

和Kafka不同,Kafka是使用话题名称来收发信息,结构简单

RabbitMQ是使用交换机\路由key指定要发送消息的队列

消息的发送者发送消息时,需要指定交换机和路由key名称

消息的接收方接收消息时,只需要指定队列的名称

在编写代码上,相比于Kafka,每个业务要编写一个配置类

这个配置类中要绑定交换机和路由key的关系,以及路由Key和队列的关系

利用RabbitMQ完成消息的收发

csmall-stock-webapi项目中测试RabbitMQ

可以利用之前我们使用Quartz实现的每隔一段时间输出当前日期信息的方法改为发送消息

添加依赖

<!--  RabbitMQ的依赖  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

yml文件配置

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    # 设置虚拟host /表示当前目录 设置是固定的
    virtual-host: /

交换机\路由Key\队列的配置类

RabbitMQ要求我们在java代码级别设置交换机\路由Key\队列的关系

我们在quartz包下,创建config包

包中创建配置信息类RabbitMQConfig

// 这个类是配置RabbitMQ中交换机,路由Key和队列的配置类
// 交换机和队列是实际对象,而路由key只是关系,他们都需要保存到Spring容器来管理,才能生效
@Configuration
public class RabbitMQConfig {
    // 需要涉及的交换机\路由Key\队列的名称都需要定义常量来声明
    public static final String STOCK_EX="stock_ex";
    public static final String STOCK_ROUT="stock_rout";
    public static final String STOCK_QUEUE="stock_queue";

    // 声明交换机对象,保存到Spring容器
    // 根据实际需求生成交换机的数量
    @Bean
    public DirectExchange stockDirectExchange(){
        return new DirectExchange(STOCK_EX);
    }
    // 声明队列对象,保存Spring容器
    @Bean
    public Queue stockQueue(){
        return new Queue(STOCK_QUEUE);
    }
    
    // 声明路由key的绑定关系,路由Key不是实体对象,本质上是一种关系的记录
    // 所以要声明哪个交换机绑定了哪个队列
    @Bean
    public Binding stockBinding(){
        return BindingBuilder.bind(
                stockQueue()).to(stockDirectExchange()).with(STOCK_ROUT);
    }

}

RabbitMQ发送消息

我们在QuartzJob类中输出时间的代码后继续编写代码

实现RabbitMQ消息的发送

public class QuartzJob implements Job {

    // 向RabbitMQ发送消息的对象
    // 也是通过配置之后,SpringBoot启动创建的
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        // 实现一个简单的任务做演示
        // 例如输出当前时间
        System.out.println("-------------------"+ LocalDateTime.now() +
                                                            "--------------------");
        // 实例化Stock对象
        Stock stock=new Stock();
        stock.setId(20);
        stock.setCommodityCode("PC100");
        stock.setReduceCount(10);
        // 利用RabbitTemplate发送消息
        // convertAndSend([交换机名称],[路由Key名称],[要发送的消息])
        rabbitTemplate.convertAndSend(RabbitMQConfig.STOCK_EX,
                RabbitMQConfig.STOCK_ROUT,stock);
        System.out.println("发送消息完成:"+stock);

    }
}

我们可以通过修改QuartzConfig类中的Cron表达式修改调用的周期

CronScheduleBuilder cron=
        CronScheduleBuilder.cronSchedule("0/10 * * * * ?");

按上面的cron修改之后,会每隔10秒运行一次发送消息的操作

接收RabbitMQ的消息

quartz包下再创建一个新的类用于接收信息

RabbitMQConsumer代码如下

// 当前类也要实例化对象,保存到Spring容器才能实现监听效果
@Component
// 和Kafka不同,RabbitMQ的监听器注解需要编写在类上
@RabbitListener(queues = {RabbitMQConfig.STOCK_QUEUE})
public class RabbitMQConsumer {
    
    // 类上编写监听,但是不能直接确实是类中的哪个方法
    // 所以我们需要在具体执行队列中消息处理的方法上添加指定注解
    // 这样当队列中有消息时,就会自动运行这个方法
    // 当前类只允许一个方法添加这个注解
    // 参数直接声明发送的对象类型即可
    @RabbitHandler
    public void process(Stock stock){
        System.out.println("消息的接收完成,内容:"+stock);
    }
    
}

启动Nacos\RabbitMQ\Seata

启动stock-webapi

根据Cron表达式,消息会在0/10/20/30/40/50秒数时运行

测试成功表示一切正常

在csmall-business模块中

创建一个rabbit包

包中创建RabbitConfig类配置交换机\路由Key\和队列的配置(允许复制)

创建一个消息的发送者(建议使用Spring任务调度)RabbitProducer

每隔10秒发送一个Order对象到RabbitMQ

最后编写一个类接收RabbitMQ中的信息RabbitConsumer

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值