SpringCloudStream最全教程,包括配置文件描述

Spring Cloud Stream 知識整理

概念 使用方法


概念

1. 發佈/訂閱

發佈/訂閱模型

簡單的講就是一種生產者,消費者模式。發佈者是生產,將輸出發佈到數據中心,訂閱者是消費者,訂閱自己感興趣的數據。當有數據到達數據中心時,就把數據發送給對應的訂閱者。

2. 消費組

直觀的理解就是一羣消費者一起處理消息。需要注意的是:每個發送到消費組的數據,僅由消費組中的一個消費者處理。

3. 分區

類比於消費組,分區是將數據分區。舉例:某應用有多個實例,都綁定到同一個數據中心,也就是不同實例都將數據發佈到同一個數據中心。分區就是將數據中心的數據再細分成不同的區。爲什麼需要分區?因爲即使是同一個應用,不同實例發佈的數據類型可能不同,也希望這些數據由不同的消費者處理。這就需要,消費者可以僅訂閱一個數據中心的部分數據。這就需要分區這個東西了。

Spring Cloud Stream簡介

1. 應用模型

Spring Cloud Stream應用由第三方的中間件組成。應用間的通信通過輸入通道(input channel)和輸出通道(output channel)完成。這些通道是有Spring Cloud Stream 注入的。而通道與外部的代理(可以理解爲上文所說的數據中心)的連接又是通過Binder實現的。

Spring Cloud Stream 應用模型

上圖就是Spring Cloud Stream的應用模型。

1.1 可獨立運行的jar

Spring Cloud Stream應用可以直接在IDE運行。這樣會很方便測試。但在生產環境下,這是不適合的。Spring Boot爲maven和Gradle提供了打包成可運行jar的工具,你可以使用這個工具將Spring Cloud Stream應用打包。

2. 抽象的Binder

Binder可以理解爲提供了Middleware操作方法的類。Spring Cloud 提供了Binder抽象接口以及KafKaRabbit MQ的Binder的實現。

使用Spring Cloud Stream

1. 快速開始

這裏先放出前面的應用模型圖

應用模型圖

下面例子使用的Middleware是Kafka,版本是kafka_2.11-1.0.0。Kafka使用的是默認配置,也就是從Kafka官網下載好後直接打開,不更改任何配置。

關於pom.xml中依賴的項目的版本問題,最好不該成別的版本,因爲很大可能導致版本衝突。

1.1 pom.xml

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.8.RELEASE</version>
	</parent>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-stream-dependencies</artifactId>
				<version>Ditmars.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>


	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<exclusions>
				<exclusion>
					<groupId>ch.qos.logback</groupId>
					<artifactId>logback-classic</artifactId>
				</exclusion>
				<exclusion>
					<groupId>ch.qos.logback</groupId>
					<artifactId>logback-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-kafka</artifactId>
		</dependency>
	</dependencies>

需要注意的是:官網上的例子是沒有下面配置的

			<exclusions>
				<exclusion>
					<groupId>ch.qos.logback</groupId>
					<artifactId>logback-classic</artifactId>
				</exclusion>
				<exclusion>
					<groupId>ch.qos.logback</groupId>
					<artifactId>logback-core</artifactId>
				</exclusion>
			</exclusions>

但是在本人電腦上如果不加上上面那段配置就是報錯,讀者可以按照個人情況選擇加不加。

簡單說明一下以上配置

  1. <parent>...</parent>:這段代表繼承spring-boot-starter-parent的配置。因爲Spring Cloud Stream 依賴Spring Boot的自動配置,所以需要加上這段。
  2. <dependencyManagement>...</dependencyManagement>:這段是引入spring-cloud-stream-dependencies.pom.xml,該配置文件裏含有Spring Cloud Stream 項目需要使用的jar包的信息(包名加版本號)
  3. <dependencies>...</dependencies>依賴兩個starter

1.2 App.java

@EnableBinding(value = { Processor.class })
@SpringBootApplication
public class App {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(App.class);
		// 註冊處理函數
		System.out.println("註冊結果:" + setHander(context));
		// 發送消息
		System.out.println("發送結果:" + write(context));
	}

	// 發送消息
	public static boolean write(ConfigurableApplicationContext context) {
		Service service = context.getBean(Service.class);
		return service.write("狗子在嗎?");
	}

	// 註冊接收到消息時的處理函數
	public static boolean setHander(ConfigurableApplicationContext context) {
		Service service = context.getBean(Service.class);
		return service.subscribe(result -> {
			System.out.print("狗子收到消息:" + result.getPayload());
		});
	}
}

上面使用了兩個註解:@EnableBinding 和 @SpringBootApplication。@SpringBootApplication 就不說了。@EnableBinding 註解接收一個參數,參數類型是class。上面代碼中,傳入的參數是“Processor.class”,這是一個接口,定義了兩個channel,分別是input和output。看名稱就知道,一個是輸出通道(input channel),一個是輸出通道(output channel)。“@EnableBinding(value = { Processor.class })”這整段代表創建Processor定義的通道,並將通道和Binder綁定。

Porcessor是Spring Cloud Stream爲方便使用而預先定義好的,除了Processor還有Sink和Source,這些接口定義了一些通道(channel),需要時,直接使用就好。我們也能自己定義通道(channel),如何定義下文會講。

App類中的main方法調用了SpringApplication.run,接着調用了write和setHandler方法。方法很簡單,上文有註釋,不再贅述。

1.3 Service.java

@Component
public class Service {

	@Autowired
	private Processor processor;
	
	public boolean write(String data) {
		return processor.output().send(MessageBuilder.withPayload(data).build());
	}
	
	public boolean subscribe(MessageHandler handler) {
		return processor.input().subscribe(handler);
	}
}

這是一個service類,封裝了一些對通道的操作。

需要注意的是這段代碼:

	@Autowired
	private Processor processor;

前面說過,Processor是一個定義了輸入輸出通道的接口,並沒有具體實現。Spring Cloud Stream會幫我們自動實現它。我們只需要獲取它,並使用它。

接着看

processor.output().send(MessageBuilder.withPayload(data).build());

先是調用output()方法獲取輸出通道對象,接着調用send方法發送數據。send方法接收一個Message對象,這個對象不能直接new,需要使用MessageBuilder獲取。

1.4 application.properties

spring.cloud.stream.bindings.input.destination=test
spring.cloud.stream.bindings.output.destination=test

上面配置了目的地,類比於Kafka的Topic和RabbitMQ的隊列的概念。

配置格式如下:

spring.cloud.stream.bindings.<channelName>.<key>=value

channelName就是管道名,key就是對應屬性,這裏是destination,代表目的地。

管道名,key的其他可選值下文會講,這裏不要強求全部弄懂,接着看就好。

1.4 總結

上面就是完整的例子了。對比前面給出的應用模型圖,上面的代碼和配置文件定義了Application Core(代碼中的處理函數,發送消息的函數等等),創建了通道並和Binder綁定(@EnableBinding(value = { Processor.class }))。Middleware就是本節一開始說的Kafka。整個流程大概如下:

  1. 開啓Middleware(Kafka)
  2. 創建通道並與Binder綁定(@EnableBinding)
  3. 編寫操作通道的代碼
  4. 在配置文件上配置目的地,組,Middleware的地址,端口等等

使用Spring Cloud Stream

1 聲明和綁定通道(channel)

1.1 聲明通道

Spring Cloud Stream 可以有任意數量的通道。聲明通道的方式很簡單。下面先給出之前說過的Sink,Source,Processor接口的源碼:

public interface Sink {

	String INPUT = "input";

	@Input(Sink.INPUT)
	SubscribableChannel input();

}

public interface Source {

	String OUTPUT = "output";

	@Output(Source.OUTPUT)
	MessageChannel output();

}

public interface Processor extends Source, Sink {

}

簡單吧,就是使用了@Input和@Output註解了方法。其中@Input註解的方法返回的是SubscribableChannel,@Output註解的方法返回的是MessageChannel。

聲明通道(channel)的方法就是使用@Input和@Output註解方法。你想要多少通道就註解多少方法。

給通道命名

默認情況下,通道的名稱就是註解的方法的名稱,例如:

@Input
public SubscribableChannel yyy();

那麼該通道的名稱就是yyy。也能夠自己定義通道名稱。只需要給@Input和@Output註解傳入String類型參數就可以了,傳入的參數就是該通道了名稱。例如:

@Input("zzz")
public SubscribableChannel yyy();

通道的名稱就變成了zzz。

1.2 創建和綁定通道

只需要使用@EnableBinding就能創建和綁定通道(channel)。

@EnableBinding(value={Sink.class,Source.class})

@EnableBinding註解接收的參數就是使用@Input或者@Output註解聲明瞭通道(channel)的接口。Spring Cloud Stream會自動實現這些接口。

上文中說過,@Input和@Output註解的方法有相應的返回值,這些返回值就是對應的通道(channel)對象。要使用通道(channel)時,就只要獲取到Spring Cloud Stream對這些接口的實現,再調用註解的方法獲取到通道(channel)對象進行操作就可以了。如何獲取接口的實現下文會講。

綁定通道(channel)是指將通道(channel)和Binder進行綁定。因爲Middleware不只一種,例如有Kafka,RabbitMQ。不同的Middleware有不同的Binder實現,通道(channel)與Middleware連接需要經過Binder,所以通道(channel)要與明確的Binder綁定。

如果類路徑下只有一種Binder,Spring Cloud Stream會找到並綁定它,不需要我們進行配置。如果有多個就需要我們明確配置了,配置方式下文會講。這裏只需要知道@EnableBinding能幫我們自動實現接口,創建通道和實現通道與Binder的綁定就可以了。

獲取綁定了的通道

使用了@EnableBinding註解後,Spring Cloud Stream 就會自動幫我們實現接口。那麼,可以通過Spring支持的任何一種方式獲取接口的實現,例如自動注入,getBean等方式,下面給出官方例子:

@Component
public class SendingBean {

    private Source source;

    @Autowired
    public SendingBean(Source source) {
        this.source = source;
    }

    public void sayHello(String name) {
         source.output().send(MessageBuilder.withPayload(name).build());
    }
}

也能夠直接注入通道(channel)

@Component
public class SendingBean {

    private MessageChannel output;

    @Autowired
    public SendingBean(MessageChannel output) {
        this.output = output;
    }

    public void sayHello(String name) {
         output.send(MessageBuilder.withPayload(name).build());
    }
}

如果你給通道命名了,需要使用@Qualifier註解指明通道名稱

@Component
public class SendingBean {

    private MessageChannel output;

    @Autowired
    public SendingBean(@Qualifier("customOutput") MessageChannel output) {
        this.output = output;
    }

    public void sayHello(String name) {
         this.output.send(MessageBuilder.withPayload(name).build());
    }
}

2 生產和消費消息

2.1 生產消息

一種方式是調用通道(channel)的sned方法發佈消息。還有就是使用Spring Intergration的方式生產數據

@EnableBinding(Source.class)
public class TimerSource {

  @Value("${format}")
  private String format;

  @Bean
  @InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "${fixedDelay}", maxMessagesPerPoll = "1"))
  public MessageSource<String> timerMessageSource() {
    return () -> new GenericMessage<>(new SimpleDateFormat(format).format(new Date()));
  }
}

Spring Cloud Stream是繼承Spring Intergration的,所有Spring Cloud Stream 天然支持Spring Intergration的東西。

2.2 消費消息

一種方式是前面快速開始中的那樣註冊處理函數,這裏不再贅述,下面將是使用@StreamListener註解對消息進行處理

使用@StreamListener的例子

@EnableBinding(value = { Processor.class })
@SpringBootApplication
public class App {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(App.class);
		// 發送消息
		System.out.println("發送結果:" + write(context));
	}

	@StreamListener(Sink.INPUT)
	public void handler(String message) {
		System.out.print("狗子收到消息:" + message);
	}

	// 發送消息
	public static boolean write(ConfigurableApplicationContext context) {
		Service service = context.getBean(Service.class);
		return service.write("狗子在嗎?");
	}
}

這是快速開始的例子,在這將下面的代碼去掉,換成@StreamListener

	public static boolean setHander(ConfigurableApplicationContext context) {
		Service service = context.getBean(Service.class);
		return service.subscribe(result -> {
			System.out.print("狗子收到消息:" + result.getPayload());
		});
	}

@StreamListener接收的參數是要處理的通道(channel)的名,所註解的方法就是處理從通道獲取到的數據的方法。方法的參數就是獲取到的數據。

消息是帶有Header的,類似Http的headler,上面有contentType屬性指明消息類型。如果contentType是application/json,那麼@Streamlistener會自動將數據轉化成@StreamListener註解的方法的參數的類型。

可以是@Header,@Headers註解獲取消息的Header

@StreamListener(target=Sink.INPUT)
	public void handler1(Message message,@Header(name="contentType") Object header) {
		System.out.print("狗子收到message消息:" + message.getMessage());
		System.out.print("消息header:" + header);
	}

用法如上,使用@Header或者@Headers註解方法的參數,指明讓Spring Cloud Stream將消息的Header傳入對應的參數。

@Header和@Headers的區別就是一個是獲取單個屬性,需要指明哪個屬性,一個是獲取全部屬性。

@StreamListener(target=Sink.INPUT)
	public void handler1(Message message,@Headers Map<String,Object> header) {
		System.out.print("狗子收到message消息:" + message.getMessage());
		System.out.print("消息header:" + header);
	}

實際上還有一些註解是@PayLoad和@PayLoads,看名字就知道是獲取消息內容的,具體用法和注意事項Spring Cloud Stream 官方文檔上沒講,這部分內容以後補充。

注意:如果@StreamListener註解的方法有返回值,那麼必須使用@SendTo註解指明返回的值寫入哪個通道

@EnableBinding(Processor.class)
public class TransformProcessor {

  @Autowired
  VotingService votingService;

  @StreamListener(Processor.INPUT)
  @SendTo(Processor.OUTPUT)
  public VoteResult handle(Vote vote) {
    return votingService.record(vote);
  }
}

使用@StreamListener將消息分發給多個方法

若想使用消息分發的功能,方法必須先滿足一下條件:

  • 沒有返回值
  • 方法是單獨的消息處理方法(原文:it must be an individual message handling method (reactive API methods are not supported))

分發的條件在註解的“condition”屬性中指明,而且條件是由SpEL表達式編寫的。所有匹配條件的處理函數將會在相同的線程中無固定順序的調用。

下面給出一個例子(由快速開始中例子修改而來):

下面這個例子中,pom.xml,和application.properties與快速開始的一樣。

//先定義兩個DTO
public class Message {
	private String message;
	private Integer all;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public Integer getAll() {
		return all;
	}

	public void setAll(Integer all) {
		this.all = all;
	}

}

public class Error {

	private String error;

	public String getError() {
		return error;
	}

	public void setError(String error) {
		this.error = error;
	}
	
}

接着是封裝了的通道(channel)操作的Service。與快速開始的例子不同的是,這個裏創建消息時設置的Header的“contentType”屬性,值爲消息攜帶的數據的Class的SimpleName。

@Component
public class Service {

	@Autowired
	private Processor processor;

	public boolean write(Object data) {
		return processor.output().send(
				MessageBuilder.withPayload(data).setHeader("contentType", data.getClass().getSimpleName()).build());
	}
}

最後是App類。這類將發佈了兩次消息,分別是Message類型的和Error類型的。並且使用@StreamListener註解了三個方法,都設置了condition屬性指明分發條件。

@EnableBinding(value = { Processor.class })
@SpringBootApplication
public class App {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(App.class);
		// 發送消息
		Message message = new Message();
		message.setAll(200);
		message.setMessage("狗子在嗎?");

		Error error = new Error();
		error.setError("錯誤呼喚!");
		write(context, message);
		write(context, error);
	}

	@StreamListener(target = Sink.INPUT, condition = "headers['contentType']=='Message'")
	public void handler1(@Payload Message message, @Header("contentType") String header) {
		System.out.println("狗子收到message消息1:" + message.getMessage());
	}

	@StreamListener(target = Sink.INPUT, condition = "headers['contentType']=='Error'")
	public void handler2(Error message) {
		System.out.print("狗子收到error消息2:" + message.getError());
	}

	@StreamListener(target = Sink.INPUT, condition = "headers['contentType']=='Message'")
	public void handler3(@Payload Message message, @Header("contentType") String header) {
		System.out.println("狗子收到message消息3:" + message.getMessage());
	}

	// 發送消息
	public static boolean write(ConfigurableApplicationContext context, Object data) {
		Service service = context.getBean(Service.class);
		return service.write(data);
	}
}

輸出結果:

狗子收到message消息1:狗子在嗎?
狗子收到message消息3:狗子在嗎?
狗子收到error消息2:錯誤呼喚!

可以看到匹配了“contentType=Message”的兩個方法都執行了,匹配了“contentType=error”的方法也執行了。

這裏我再補充一點我使用時遇到的問題

如果我把Header設置一個屬性“type=XXX”,但獲取到消息的時候,Header上並沒有這個屬性。簡單嘗試了一些,發現只能修改現有屬性(例如contentType),不能添加新屬性。

2.3 聚合

2.3.1 使用限制

Spring Cloud Stream 支持聚合多個應用的功能。這個功能可以直接連接多個應用的輸入,輸出通道,避免通過代理(指Kafka,RabbitMQ這些Middleware)交換消息時帶來的額外耗費。到1.0版的Spring Cloud Stream爲止,聚合功能僅支持下列應用:

  1. 只有單個輸出通道,並且命名爲output的應用(就是Source)
  2. 只有單個輸入通道,並且命名爲input的應用(就是Sink)
  3. 只有一個輸出通道和一個輸入通道並且命名爲output和input的應用(就是Processor)

以上是官方文檔原話,個人覺得很雞肋的功能,也許我用得少吧。

具備以上特徵的應用就可以使用Spring Cloud Stream的聚合功能將多個應該連接成一串互相連接的應用。

這裏還有幾個限制,起始的應用必須是Source或者Processor,結束的應用必須是Sink或者Processor。中間的應用必須是Processor,不過可以有任意數量的Processor。(Soruce,Sink,Processor就是指具備上面所說特徵的應用)

2.3.2 例子

下面給出官方例子,先說明幾個注意點:

  1. 下面例子中有三個應用分別是Source,Sink,Processor,這三個應用可以分佈在不同項目中,也能在相同項目中。需要注意的是,如果在相同項目中,應該要處於不同的包中,如果同個包,多個@SpringBootApplication註解會導致報錯
  2. 使用@Transformer註解需要指明inputChannel和outputChannel屬性。官方文檔的例子上是沒有指明的,但我運行的時候如果不指明就不能將多個應用連在一起。
  3. 不要使用eclipse中的Spring Boot應用的插件運行,使用插件運行會報注意點1的錯誤,原因是什麼不清楚。
//Source
@SpringBootApplication
@EnableBinding(Source.class)
public class SourceApplication {
	
	@InboundChannelAdapter(value = Source.OUTPUT)
	public String timerMessageSource() {
		return new SimpleDateFormat().format(new Date());
	}
}
//Processor
@SpringBootApplication
@EnableBinding(Processor.class)
public class ProcessorApplication {
	
	@Transformer(inputChannel=Sink.INPUT,outputChannel=Source.OUTPUT)
	public String loggerSink(String payload) {
		return payload.toUpperCase();
	}
}
//Sink
@SpringBootApplication
@EnableBinding(Sink.class)
public class SinkApplication {

	@StreamListener(Sink.INPUT)
	public void loggerSink(Object payload) {
		System.out.println("Received: " + payload);
	}
}

上面是三個應用,下面是將三個應用連接起來的代碼。

@SpringBootApplication
public class App {

	public static void main(String[] args) {
		new AggregateApplicationBuilder().from(SourceApplication.class).args("--fixedDelay=5000")
				.via(ProcessorApplication.class).to(SinkApplication.class).args("--debug=true").run(args);
	}
}

代碼很簡單,就是使用AggregateApplicationBuilder將三個應用連接起來。.args("XXX")這段代碼的作用就是爲對應的應用傳遞運行時參數。

2.3.3 不同連接情況下的Binder綁定

由於限制多多,可以窮舉出所有的可能連接,下面給出不同連接與Binder的綁定情況:

  1. 如果以Source應用開始並且以Sink應用結束,那麼應用間的連接是直接進行的,不會經過代理(指Kafka,RabbitMQ這些Middleware),也就不會與Binder綁定。例如上面的例子,你把使用的Middleware關閉,例如我使用的是Kafka,我把Kafka關了,應用也能跑起來。
  2. 如果以Processor應用開始,那麼這個應用的input通道就是這一串一樣的input通道,這種情況下,會觸發input通道與Binder的綁定。
  3. 如果以Processor應用結束,那麼這個應用的output通道就是這串硬硬的output通道,會觸發output通道與Binder的綁定。

2.3.4 配置聚合的應用

Spring Cloud Stream 支持爲聚合在一起的多個應用中的一個應用傳遞參數。

爲應用命名namespace後,就可以通過命令行,環境變量等方式給應用傳遞參數。

public static void main(String[] args) {
		new AggregateApplicationBuilder()
		.from(SourceApplication.class).namespace("from").args("--fixedDelay=20000")
		.via(ProcessorApplication.class).namespace("via")
		.to(SinkApplication.class).namespace("to").args("--debug=true").run(args);
	}

這端代碼和前面的例子沒太大差別,只是多了.namespace(),這段代碼就是爲應用設置namesapce。

接着是聚合在一起的應用的代碼:

	//獲取傳入的參數
	@Value("${fixedDelay:null}")
	private String args;
	
	@InboundChannelAdapter(value = Source.OUTPUT)
	public String timerMessageSource() {
      	//輸出參數
		System.out.println("Source get args:"+args);
		return new SimpleDateFormat().format(new Date());
	}

這裏只給出一個,其他類似,都是加了獲取參數和輸出參數的代碼。

接着打包後以下列命令運行:

java -jar stream-aggregation.jar

輸出:

Source get args:20000
Processor get args:null
Sink get args:null
Received: 17-12-14 下午5:43

可以看到,因爲Processor是沒有fixedDelay參數的,所有輸出null

以下列命令運行:

java -jar stream.jar via --fixedDelay=200

輸出:

Source get args:20000
Processor get args:200
Sink get args:null
Received: 17-12-14 下午5:46

可以看到,輸出爲200,就是我們傳入的參數,而Sink和Source的輸出沒變,也就是沒改變它們的參數

總結一下:

  1. 在聚合時候設置namespace
  2. 在命令行或者環境變量等方式使用namespace爲指定應用傳遞參數

Binder以及配置

應用模型圖

這裏再放出應用模型圖。Binder簡單的理解就是封裝了對消息系統(kafka,rabbitMQ)的操作。可以使用開發者簡單的配置就能使用消息系統的發佈/訂閱,點對點傳輸,分組,分區等等功能。是開發者開放時能忽略對消息系統操作的細節。當然,這些組件的設計一般是抽象出一個接口,然後對不同的消息系統有不同的實現,這些東西這裏不講,只講怎麼用。

1 Binder實現類的檢測

1.1 單個Binder實現類

如果在類路徑上只有一個Binder的實現類(例如你在maven項目中,只添加了kafka的Binder的實現的依賴),那麼Spring Cloud Stream會默認使用這個實現類,所有的通道(Channel)都會綁定這個Binder。就像前面的例子那樣,你幾乎感覺不到Binder的存在,你只需要配置一下通道(Channel)的目的地(destination),分組(group),分區(partition)等信息就可以使用。例如快速開始的例子中就僅僅配置了輸入,輸出通道的目的地

spring.cloud.stream.bindings.input.destination=test
spring.cloud.stream.bindings.output.destination=test

1.2 多個Binder實現類

如果有多個Binder實現類,那麼就必須指明哪個通道(Channel)綁定哪個Binder。配置的方式就是在application.peoperties或者application.yaml配置文件上添加一下內容:

spring.cloud.stream.bindings.通道名稱.binder=Binder名稱

這樣就能指明什麼通道綁定哪個Binder了。

當然,你也可以配置默認的Binder

spring.cloud.stream.defaultBinder=Binder名稱

關於Binder的名稱

在每個Binder實現的jar包的META-INF目錄下都會有一個spring.binders文件。該文件是一個簡單的單屬性文件,例如rabbitMQ的Binder的實現的spring.binders文件的內容如下:

rabbit:\org.springframework.cloud.stream.binder.rabbit.config.RabbitServiceAutoConfiguration

前面的key部分(這裏是rabbit)就是Binder的名稱。也就是rabbitMQ的Binder的名稱就是rabbit。實際上現在也就只有兩種Binder的實現,一個是rabbitMQ的一個是kafka的,kafka的Binder的名稱就是kafka。

2 可選配置

可以通過Spring Boot的任意配置機制來對Spring Cloud Stream應用進行配置,例如應用參數(application argument),環境變量(environment variable)以及YAML 或者 properties文件。

2.1 對應用的配置

spring.cloud.stream.instanceCount

這個是配置應用實例的數量。如果使用kafka,必須設置分區。默認值爲1

spring.cloud.stream.instanceIndex

實例的編號,編號從0開始。

spring.cloud.stream.dynamicDesinations

設置一列目的地用以動態綁定。如果設置了,只有列表中的目的地能被綁定。默認值爲空。

spring.cloud.stream.defaultBinder

設置的默認的Binder,這個前面說過,不再贅述。默認值爲空。

spring.cloud.stream.overrideCloudConnectors

默認值爲false。當值爲false時,Binder會檢查並選擇合適的bound Service來創建連接。當設爲true的時候,Binder會按照Spring Cloud Stream配置文件來選擇bound Service。這個配置通常是在需要連接多個消息系統的時候用到。

2.2 連接(Binding)的配置

這類配置的格式如下:

spring.cloud.stream.bindings.<channelName>.<property>=<value>

意思就是配置名爲channelName的通道的property屬性的值爲value。

爲了避免重複配置,Spring Cloud Stream 也支持對全部通道(channel)進行設置。配置默認屬性的格式如下:

spring.cloud.stream.default.<property>=<value>

2.2.1 通用的配置

一下的配置屬性都帶有“spring.cloud.stream.bindings.<channelName>”前綴,爲方便文字排版,省略前綴。

destination

通道(channel)與消息系統連接的目的地(若消息系統是RabbitMQ,目的地(destination)就是指exchange,消息系統是Kafka,那麼就是指topic)。

可以連接多個目的地。要想連接多個目的地,只需要用“,”將多個目的地分開即可。例如:

spring.cloud.stream.channelName.destinaction=destinaction1,destinaction2

group

配置通道的消費者組。僅應用於輸入通道。

默認值爲null

補充:一個channel可以連接多個destination,同一個group內的channel連接的destination可以不同。

如果一個group內的channel連接了A,B,C三個destination。那麼A,B,C這個三個destination的消息都會拷貝一份發給這個group,並且選擇這個group中channel消費這個消息。例如,這個group中的a,b兩個channel連接並且只連接了destination A,channel c連接且只連接了destination B,那麼會在a,b中選一個來處理來自A的消息,c不在選擇的範圍內。

如果有兩個group都連接了destination A,那麼A的消息會拷貝兩份分別發給這兩個group。

contentType

通道(channel)承載的內容的類型。

默認值爲null。

binder

這個在前面“多個Binder實現類”部分講了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章