springcloud记录篇7-spring cloud stream

一 。 Spring Cloud Stream简介
   Spring Cloud Stream 是一个构建消息驱动微服务的框架,应用程序通过 inputs通道 或者 outputs通道 来与 Spring Cloud Stream 中binder(kafka|rabbitmq) 交互,通过我们配置来 binding ,而 Spring Cloud Stream 的 binder 负责与中间件交互。

编程模型 

Binder

        Binder 是 Spring Cloud Stream 的一个抽象概念,是应用与消息中间件之间的粘合剂。
目前 Spring Cloud Stream 实现了 Kafka 和 Rabbit MQ 的binder。通过 binder ,可以很方便的连接中间件,可以动态的改变消息的destinations(对应于 Kafka 的topic,Rabbit MQ 的 exchanges),这些都可以通过外部配置项来做到。甚至可以任意的改变中间件的类型而不需要修改一行代码。

Publish-Subscribe

      消息的发布(Publish)和订阅(Subscribe)是事件驱动的经典模式。Spring Cloud Stream 的数据交互也是基于这个思想。生产者把消息通过某个 topic 广播出去(Spring Cloud Stream 中的 destinations)。其他的微服务,通过订阅特定 topic 来获取广播出来的消息来触发业务的进行。

这种模式,极大的降低了生产者与消费者之间的耦合。即使有新的应用的引入,也不需要破坏当前系统的整体结构。

Consumer Groups

  “Group”, Kafka 中的概念。Spring Cloud Stream 的这个分组概念的意思基本和 Kafka 一致。

微服务中动态的缩放同一个应用的数量以此来达到更高的处理能力是非常必须的。对于这种情况,同一个事件防止被重复消费,只要把这些应用放置于同一个 “group” 中,就能够保证消息只会被其中一个应用消费一次。

其他概念参考
http://cloud.spring.io/spring-cloud-static/Edgware.SR4/single/spring-cloud.html#_spring_cloud_stream

同时 springcloudstream是继承自spring框架spring-integration  其中概念百度 以下简单概要介绍

Message

Message是它的基础构件和核心,所有的流程都围绕着Message运转,如图所示

Message,就是所说的消息体,用来承载传输的信息用的。Message分为两部分,header和payload。header是头部信息,用来存储传输的一些特性属性参数。payload是用来装载数据的,他可以携带的任何Object对象  不同的对象在binder中传输 可以指定不同的mini类型 具体参考
http://cloud.spring.io/spring-cloud-static/Edgware.SR4/single/spring-cloud.html#contenttypemanagement

可以通过application.yml中设置 输入input和输出output的mini类型 
spring.cloud.stream.bindings.<channelName>.content-type 

以下是所有支持的mini类型

Source Payload Target Payload content-type header (source message) content-type header (after conversion) Comments

POJO

JSON String

ignored

application/json

 

Tuple

JSON String

ignored

application/json

JSON is tailored for Tuple

POJO

String (toString())

ignored

text/plain, java.lang.String

 

POJO

byte[] (java.io serialized)

ignored

application/x-java-serialized-object

 

JSON byte[] or String

POJO

application/json (or none)

application/x-java-object

 

byte[] or String

Serializable

application/x-java-serialized-object

application/x-java-object

 

JSON byte[] or String

Tuple

application/json (or none)

application/x-spring-tuple

 

byte[]

String

any

text/plain, java.lang.String

will apply any Charset specified in the content-type header

String

byte[]

any

application/octet-stream

will apply any Charset specified in the content-type header

MessageChannel

消息管道,生产者生产一个消息到channel,消费者从channel消费一个消息,所以channel可以对消息组件解耦,并且提供一个方便的拦截功能和监控功能。
 默认的通道 
   输入(SubscribableChannel)和输出通道(MessageChannel)参考 Processor接口

springcloudstream提供通道的定义 比如自定义通过可以使用接口 

public interface OrderChannel {

	String INPUT = "input_order";
	String OUTPUT="ouput_order";
	/**
	 * input注解制定通道的名称  将来在yml中配置该通道的实际绑定的topic或者订阅组
	 * @return
	 */
	@Input(INPUT)
	SubscribableChannel orderInput();
	/**
	 * output注解指定输出通道的名称
	 * @return
	 */
	@Output(OUTPUT)
	MessageChannel orderOutput();
}

以下 代码参考 Source  Sink Processor接口   将来在yml关于该通道的配置既可以
 

spring: 
    cloud: 
        stream: 
            bindings: 
                通道名称: 
                    destination: mydest

二。Spring Cloud Stream入门案例

1》安装kafka

具体kafaka学习参考https://blog.csdn.net/liaomin416100569/article/details/78799488
下载kafka:

 https://www.apache.org/dyn/closer.cgi?path=/kafka/1.1.1/kafka_2.11-1.1.1.tgz

解压 将kafka_2.11-1.1.1\bin\windows 目录添加到PATH环境变量中 
bin目录下 新建文件 runzk.cmd  内容
 

pushd %~dp0
zookeeper-server-start.bat ../../config/zookeeper.properties

新建 runkafka.cmd 内容
 

pushd %~dp0
kafka-server-start.bat ../../config/server.properties

运行 runzk.cmd 然后运行 runkafka.cmd 

插件 mydest的主题

kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic mydest

订阅主题 在控制台等消息
 

kafka-console-producer --broker-list localhost:9092 --topic mydest

给主题发送消息 测试
 

kafka-console-producer.sh --broker-list localhost:9092 --topic mydest

2》helloworld案例

以下helloworld程序 参考自官网
http://cloud.spring.io/spring-cloud-static/Edgware.SR4/single/spring-cloud.html#_getting_started
添加订阅监听消息的maven项目  添加依赖

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.13.RELEASE</version>
</parent>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR5</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
	  <groupId>org.springframework.cloud</groupId>
	  <artifactId>spring-cloud-stream-binder-kafka</artifactId>
	</dependency>
</dependencies>

 yml中设置 订阅者 input通道的消息重点的主题 (topic)   这里同时设置 kafka的broker 还有zookeeper默认是本机所以不用设置

参考http://cloud.spring.io/spring-cloud-static/Edgware.SR4/single/spring-cloud.html#_apache_kafka_binder 
  37.31章节 比如
   spring.cloud.stream.kafka.binder.brokers 设置 broker的ip和端口  默认是localhost:9092
   spring.cloud.stream.kafka.binder.zkNodes 设置zk集群的ip 默认是localhost
   spring.cloud.stream.kafka.binder.defaultZkPort 设置默认的zk端口 默认是 2181

server:
  port: 8088
spring: 
    cloud: 
        stream: 
            bindings: 
                input: 
                    destination: mydest

 添加一个消息绑定的运行主类

package cn.ps.stream.input;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;


@SpringBootApplication
/**
 * @EnableBinding表示啟動綁定到中間件 該注解中制定的接口可以定義不同的通道
 * 默認 
 *   Sink 存在一個名字是input的輸入通過
 *   Source 存在一個名字是output額輸出通道
 *   Processor繼承Sink和Source 擁有兩個通道
 * @author Administrator
 *
 */
@EnableBinding(Sink.class)
public class InputMain {
	/**
	 * 監聽輸入通道的消息 消息會傳送到 方法的入参
	 *   Payload是消息体
	 *   header是消息头
	 * @param message
	 */
	@StreamListener(Sink.INPUT)
	public void receive(Message<String> message) {
		System.out.println(message.getPayload());
	}
	
	public static void main(String[] args) {
		SpringApplication sa=new SpringApplication(InputMain.class);
		sa.run(args);
	}

}

添加轮询(每秒发送一次)发送消息的maven项目  添加依赖

同上maven依赖
application.yml设置输出通道的目的 topic

server:
  port: 8089
spring: 
    cloud: 
        stream: 
            bindings: 
                output: 
                    destination: mydest

添加轮询的main方法测试
 

package cn.ps.stream.output;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.context.annotation.PropertySource;
import org.springframework.integration.annotation.InboundChannelAdapter;

@SpringBootApplication
@EnableBinding(Source.class)
public class OutputMain {
	@InboundChannelAdapter(Source.OUTPUT)
	public String greet() {
		return "hello world " + System.currentTimeMillis();
	}

	public static void main(String[] args) {
		SpringApplication sa = new SpringApplication(OutputMain.class);
		sa.run(args);
	}

}

发现input的项目的控制台 不停地接受到消息
其他的比如自定义 通道的接口 等  参考编程模型
http://cloud.spring.io/spring-cloud-static/Edgware.SR4/single/spring-cloud.html#_programming_model

猜你喜欢

转载自blog.csdn.net/liaomin416100569/article/details/81208193
今日推荐