测试
Spring Cloud Stream支持测试您的微服务应用程序,而无需连接到消息系统。您可以使用spring-cloud-stream-test-support库提供的TestSupportBinder,可以将其作为测试依赖项添加到应用程序中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
注意 | TestSupportBinder使用Spring Boot自动配置机制取代类路径中找到的其他绑定。因此,添加binder作为依赖关系时,请确保正在使用test范围。 |
TestSupportBinder允许用户与绑定的频道进行交互,并检查应用程序发送和接收的消息
对于出站消息通道,TestSupportBinder注册单个订户,并将应用程序发送的消息保留在MessageCollector中。它们可以在测试过程中被检索,并对它们做出断言。
用户还可以将消息发送到入站消息通道,以便消费者应用程序可以使用消息。以下示例显示了如何在处理器上测试输入和输出通道。
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleTest {
@Autowired
private Processor processor;
@Autowired
private MessageCollector messageCollector;
@Test
@SuppressWarnings("unchecked")
public void testWiring() {
Message<String> message = new GenericMessage<>("hello");
processor.input().send(message);
Message<String> received = (Message<String>) messageCollector.forChannel(processor.output()).poll();
assertThat(received.getPayload(), equalTo("hello world"));
}
@SpringBootApplication
@EnableBinding(Processor.class)
public static class MyProcessor {
@Autowired
private Processor channels;
@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
public String transform(String in) {
return in + " world";
}
}
}
在上面的示例中,我们正在创建一个具有输入和输出通道的应用程序,通过Processor接口绑定。绑定的接口被注入测试,所以我们可以访问这两个通道。我们正在输入频道发送消息,我们使用Spring Cloud Stream测试支持提供的MessageCollector来捕获消息已经被发送到输出通道。收到消息后,我们可以验证组件是否正常工作。
健康指标
Spring Cloud Stream为粘合剂提供健康指标。它以binders的名义注册,可以通过设置management.health.binders.enabled属性启用或禁用。
指标发射器
Spring Cloud Stream提供了一个名为spring-cloud-stream-metrics的模块,可以用来从Spring Boot度量端点到命名通道发出任何可用度量。该模块允许运营商从流应用收集指标,而不依赖轮询其端点。
当您设置度量绑定的目标名称(例如spring.cloud.stream.bindings.applicationMetrics.destination=<DESTINATION_NAME>)时,该模块将被激活。可以以与任何其他生成器绑定相似的方式配置applicationMetrics。applicationMetrics的contentType默认设置为application/json。
以下属性可用于自定义度量标准的排放:
spring.cloud.stream.metrics.key
要发射的度量的名称。应该是每个应用程序的唯一值。
默认
KaTeX parse error: Expected '}', got 'EOF' at end of input: …plication.name:{vcap.application.name?{spring.config.name:application}}}
spring.cloud.stream.metrics.prefix
前缀字符串,以前缀到度量键。
默认值:``
spring.cloud.stream.metrics.properties
就像includes选项一样,它允许将白名单应用程序属性添加到度量有效负载
默认值:null。
有关度量导出过程的详细概述,请参见Spring Boot参考文档。Spring Cloud Stream提供了一个名为application的指标导出器,可以通过常规Spring Boot指标配置属性进行配置。
可以通过使用出口商的全局Spring Boot配置设置或使用特定于导出器的属性来配置导出器。要使用全局配置设置,属性应以spring.metric.export为前缀(例如spring.metric.export.includes=integration**)。这些配置选项将适用于所有出口商(除非它们的配置不同)。或者,如果要使用与其他出口商不同的配置设置(例如,限制发布的度量数量),则可以使用前缀spring.metrics.export.triggers.application配置Spring Cloud Stream提供的度量导出器(例如spring.metrics.export.triggers.application.includes=integration**)。
注意 | 由于Spring Boot的轻松约束,所包含的属性的值可能与原始值稍有不同。作为经验法则,度量导出器将尝试使用点符号(例如JAVA_HOME成为java.home)以一致的格式标准化所有属性。规范化的目标是使下游用户能够始终如一地接收属性名称,无论它们如何设置在受监视的应用程序上(–spring.application.name或SPRING_APPLICATION_NAME始终会生成spring.application.name)。 |
以下是通过以下命令以JSON格式发布到频道的数据的示例:
java -jar time-source.jar \
--spring.cloud.stream.bindings.applicationMetrics.destination=someMetrics \
--spring.cloud.stream.metrics.properties=spring.application** \
--spring.metrics.export.includes=integration.channel.input**,integration.channel.output**
得到的JSON是:
{
"name":"time-source",
"metrics":[
{
"name":"integration.channel.output.errorRate.mean",
"value":0.0,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.errorRate.max",
"value":0.0,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.errorRate.min",
"value":0.0,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.errorRate.stdev",
"value":0.0,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.errorRate.count",
"value":0.0,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.sendCount",
"value":6.0,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.sendRate.mean",
"value":0.994885872292989,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.sendRate.max",
"value":1.006247080013156,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.sendRate.min",
"value":1.0012035220116378,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.sendRate.stdev",
"value":6.505181111084848E-4,
"timestamp":"2017-04-11T16:56:35.790Z"
},
{
"name":"integration.channel.output.sendRate.count",
"value":6.0,
"timestamp":"2017-04-11T16:56:35.790Z"
}
],
"createdTime":"2017-04-11T20:56:35.790Z",
"properties":{
"spring.application.name":"time-source",
"spring.application.index":"0"
}
}
样品
对于Spring Cloud Stream示例,请参阅GitHub上的spring-cloud-stream样本存储库。
入门
要开始创建Spring Cloud Stream应用程序,请访问Spring Initializr并创建一个名为“GreetingSource”的新Maven项目。在下拉菜单中选择Spring Boot {supported-spring-boot-version}。在“ 搜索依赖关系”文本框中键入Stream Rabbit或Stream Kafka,具体取决于您要使用的binder。
接下来,在与GreetingSourceApplication类相同的包中创建一个新类GreetingSource。给它以下代码:
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.annotation.InboundChannelAdapter;
@EnableBinding(Source.class)
public class GreetingSource {
@InboundChannelAdapter(Source.OUTPUT)
public String greet() {
return "hello world " + System.currentTimeMillis();
}
}
@EnableBinding注释是触发Spring Integration基础架构组件的创建。具体来说,它将创建一个Kafka连接工厂,一个Kafka出站通道适配器,并在Source界面中定义消息通道:
public interface Source {
String OUTPUT = "output";
@Output(Source.OUTPUT)
MessageChannel output();
}
自动配置还创建一个默认轮询器,以便每秒调用greet()方法一次。标准的Spring Integration @InboundChannelAdapter注释使用返回值作为消息的有效内容向源的输出通道发送消息。
要测试驱动此设置,请运行Kafka消息代理。一个简单的方法是使用Docker镜像:
# On OS X
$ docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=`docker-machine ip \`docker-machine active\`` --env ADVERTISED_PORT=9092 spotify/kafka
# On Linux
$ docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=localhost --env ADVERTISED_PORT=9092 spotify/kafka
构建应用程序:
./mvnw clean package
消费者应用程序以类似的方式进行编码。返回Initializr并创建另一个名为LoggingSink的项目。然后在与类LoggingSinkApplication相同的包中创建一个新类LoggingSink,并使用以下代码:
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
@EnableBinding(Sink.class)
public class LoggingSink {
@StreamListener(Sink.INPUT)
public void log(String message) {
System.out.println(message);
}
}
构建应用程序:
./mvnw clean package
要将GreetingSource应用程序连接到LoggingSink应用程序,每个应用程序必须共享相同的目标名称。启动这两个应用程序如下所示,您将看到消费者应用程序打印“hello world”和时间戳到控制台:
cd GreetingSource
java -jar target/GreetingSource-0.0.1-SNAPSHOT.jar --spring.cloud.stream.bindings.output.destination=mydest
cd LoggingSink
java -jar target/LoggingSink-0.0.1-SNAPSHOT.jar --server.port=8090 --spring.cloud.stream.bindings.input.destination=mydest
(不同的服务器端口可以防止两个应用程序中用于维护Spring Boot执行器端点的HTTP端口的冲突。)
LoggingSink应用程序的输出将如下所示:
[ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
[ main] com.example.LoggingSinkApplication : Started LoggingSinkApplication in 6.828 seconds (JVM running for 7.371)
hello world 1458595076731
hello world 1458595077732
hello world 1458595078733
hello world 1458595079734
hello world 1458595080735