测试

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