前言:

     如何理解中间件的概念:中间件我们可以简称为代理,好比我们生活中的邮政局,张三向李四寄东西,不要自己跑老远送到李四身边,而是把快件投到邮局,由邮局代理送给接收人。

 本文实例以Windows7 64位为例

rabbitMq与kafka的对比和安装使用:

     rabbitMq,遵循AMQP协议,由内在高并发的erlang语言开发,用在实时的对可靠性要求比较高的消息传递上,安装rabbitMq前需要先安装erlang环境,资源下载地址:链接:https://pan.baidu.com/s/1JbBwVzom9CKdclvJyEPGRg 提取码:3g1z   。安装完rabbitMq之后,进入sbin安装目录,通过rabbitmq-plugins list 命令查看插件状态,如下图

在相同的目录下通过rabbitmq-plugins enable rabbitmq_management命令开启插件管理,如下图(因为本人rabbitMq 不属于刚安装,命令输出结果可能会跟刚安装的不一样

开启插件管理之后可在浏览器访问http://localhost:15672/ ,默认的登入用户名/密码: guest/guest,如下图:

   

登入之后即可开启对rabbitMq的管理控制

    kafka采用zookeeper对集群中的broker(经纪人)、consumer(消费者)进行管理,可以注册topic到zookeeper上;通过zookeeper的协调机制,安装kafka前需要先安装zookeeper,资源下载地址:链接:https://pan.baidu.com/s/1iu6Ywb8qoiJB80_of_wQcA  提取码:vv7b 下载解压之后两个软件都属于压缩包,解压使用即可。先解压zookeeper-3.4.8 压缩文件,然后conf目录中复制zoo_sample.cfg文件为zoo.cfg,如下图

复制好之后使用Windows命令行工具进入解压文件的bin目录用zkServer命令启动zookeeper,如下图

如果启动成功会占用系统的2181端口(该命令行窗口不可关闭);解压kafka_2.11-0.11.0.0文件,开启新的命令行窗口进入

解压文件的bin\windows目录用 kafka-server-start ../../config/server.properties 命令启动kafka,如下图

如果正常启动会占用系统的9092端口,启动过程如果出现了类似如下的命令返回异常

可以通过删除解压根目录的\tmp\kafka-logs文件夹再启动可以解决。

 

rabbitMq与kafka整合spring cloud集群的使用

  在springCloud中整合rabbitMq与kafka,springCloud可以看作是一个绑定器或适配器,它有连接消息代理中间件的功能,更换绑定器只需要更换依赖,不需要更改任何业务逻辑,实现了绑定器跟消息的耦合,本文仅展示kafka作为消息代理中间件的代码,采用Eureka作为服务器集群。

消息生产者(producer)代码:

pom依赖:
<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<!--<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
		</dependency>
        如果使用rabbitMq作为消息中间件,kafka依赖更换为此依赖-->

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-kafka</artifactId>
		</dependency>
	</dependencies>

yml配置:

server:
  port: 8080
spring:
  application:
    name: spring-msg-producer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/  #注册eureka服务器

  
发送消息的接口:

import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.SubscribableChannel;

/**
 * 声明发送消息的接口
 */
public interface SendService {

	@Output("myTopic20190605")//声明消息生产者通道名称,myTopic20190605:通道名称
	SubscribableChannel sendOrder();
} 


控制器类:
@RestController
public class TestController {
	@Autowired
	private SendService sendService;
	/**
	 * sendService.sendOrder() 返回发送消息的通道,然后进行对应的发送消息
	 * @return
	 */
	@RequestMapping(value = "/send", method = RequestMethod.GET)
	public String send() {
		Date  date=new Date();
		SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss:sss");
		String msgstr="发送成功 Hello World"+simpleDateFormat.format(date);
		Message msg = MessageBuilder.withPayload(msgstr.getBytes()).build();
		sendService.sendOrder().send(msg);
		System.out.println("发送成功:"+msgstr);
		return "success :"+msgstr;
	}
}


启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableBinding(SendService.class)//声明绑定消息生产者接口
public class ProducerApp {
	public static void main(String[] args) {
		new SpringApplicationBuilder(ProducerApp.class).run(args);
	}
}

生产者启动之后就会新增对应的消息通道,在kafka解压文件的bin\windows目录使用 kafka-topics --list --zookeeper localhost:2181 命令查看,如下图

  消息消费者(producer)代码:

pom.xml依赖:
<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<!--<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
		</dependency>
        如果使用rabbitMq作为消息代理中间件,kafka依赖更换为此依赖-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-kafka</artifactId>
		</dependency>
	</dependencies>

yml 配置:

server:
  port: 8081
spring:
  application:
    name: spring-msg-consumer
  cloud:
    stream:
      bindings:
        myTopic20190605: #myTopic20190605是消息生产者通道的名称
          group: groupA   #配制组名
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/


接收消息的接口:

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;

/**
 * 定义消费者接收消息的接口
 */
public interface ReceiveService {
	/**
	 * 声明输入通道的名称,要跟输出的通道名称一样才能收到对应生产者发送的消息
	 * @return
	 */
	@Input("myTopic20190605")
	SubscribableChannel myInput();
}



启动类和消息监听类:

@SpringBootApplication
@EnableEurekaClient
@EnableBinding(ReceiveService.class)//绑定接收消息的接口
public class ConsumerApp {

	public static void main(String[] args) {
		new SpringApplicationBuilder(ConsumerApp.class).web(true).run(args);
	}

	@StreamListener("myTopic20190605")//声明消费者监听的通道名称,需要跟生产者的通道名称一样
	public void onReceive(byte[] msg) {
		System.out.println("消息者1,接收到的消息:" + new String(msg));
	}
}

    一个消息生产者通道可以有多个消息消费者,通过配置组名可以达到负载均衡的效果。假如每个消息消费者组名不一样,每个消息消费者都可以收到生产者发送的消息;假如每个消息消费者组名一样,则不会每个消费者都获得消息,会轮询收到对应的消息。为达到负载均衡的效果,在生产者和消费者依赖中需要ribbon依赖,采用默认负载均衡机制

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

kafka常用命令的注意事项:

删除topic命令:  

   删除命令为:kafka-topics --delete --zookeeper localhost:2181 --topic topic名称,但仅仅单独执行该命令,无法做到完全删除,只是做了一个标记,查询topic列表还会显示出来,如下图:

如果要做到执行命令就完全删除需要在kafka_2.11-0.11.0.0\config目录下往server.properties配置文件末尾添加delete.topic.enable=true再执行对应topic的删除命令即可,如下图:

有时候为了方便会有一次性删除全部topic的需求,那该怎么处理呢,如果topic存在数量比较多,一条一条删显得有点不现实。因为kafka是采用zookeeper进行集群管理的,新增的每个topic都会注册到zookeeper中,较为便捷的解决方法是:我们可以先把zookeeper和kafka服务器关闭,再把tmp目录下的两个文件夹都删除,或直接删除tmp根目录,如下图:

 重新启动zookeeper和kafka服务器之后,再执行查询topic列表命令就一条都看不到,大功告成了,如下图:

springcloud整合的消息中间件修改成rabbitMq的注意事项:

 由于springcloud与消息中间件的低耦合型,转换kafka消息中间件为rabbitMq只需要把 stream-kafka依赖转换成

stream-rabbit即可(消息生产者和消费者都需要转换),如下示例:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>

 ->转换为

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

依赖修改完,按整合kafka消息中间件时操作一样,先启动Eureka服务器,再分别启动消息生产者和消息消费者。启动消息生产者之后,打开rabbitMq控制台发现新增的通道名称会在exchanges栏目下显示,在kafka控制台是查询topic列表里面显示,如下图:

一个消息生产者,如果启动多个消费者,且分组名不一样,在rabbitMq控制台queues栏目下会显示类似如下信息(分组名称分别是:groupA、groupB、groupC):

 

rabbitmp工作模式示意图

 

Logo

Kafka开源项目指南提供详尽教程,助开发者掌握其架构、配置和使用,实现高效数据流管理和实时处理。它高性能、可扩展,适合日志收集和实时数据处理,通过持久化保障数据安全,是企业大数据生态系统的核心。

更多推荐