Spring Cloud构建微服务架构(六)消息驱动的微服务(入门)

前言

Spring Cloud Stream是什么?
Spring Cloud Stream是一个用来为微服务应用构建消息驱动能力的框架。引入了发布-订阅、消费组以及消息分区这三个核心概念,可以有效地简化开发人员对消息中间件的使用复杂度,让系统开发人员可以有更多的精力关注于核心业务逻辑的处理。由于Spring Cloud Stream基于Spring Boot实现,所以它秉承了Spring Boot的优点,实现了自动化配置的功能帮忙我们可以快速的上手使用,但是目前为止Spring Cloud Stream只支持下面两个著名的消息中间件的自动化配置:

  • RabbitMQ
  • Kafka
快速入门

我们通过构建一个简单的示例来对Spring Cloud Stream有一个初步认识。该示例主要目标是构建一个基于Spring Boot的微服务应用,这个微服务应用将通过使用消息中间件RabbitMQ来接收消息并将消息打印到日志中。所以,在进行下面步骤之前请先确认已经在本地安装了RabbitMQ。

构建一个Spring Cloud Stream消费者
  • 创建一个基础的Spring Boot工程,命名为:stream-hello
  • 编辑pom.xml中的依赖关系,引入Spring Cloud Stream对RabbitMQ的支持,具体如下:
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

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

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  • 创建用于接收来自RabbitMQ消息的消费者SinkReceiver,具体如下:
@EnableBinding(Sink.class)
public class SinkReceiver {

    private static Logger logger = LoggerFactory.getLogger(SinkReceiver.class);

    @StreamListener(Sink.INPUT)
    public void receive(Object payload) {
        logger.info("Received: " + payload);
    }

}
  • 创建应用主类,这里同其他Spring Boot一样,没有什么特别之处,具体如下:
@SpringBootApplication
public class SinkApplication {

    public static void main(String[] args) {
        SpringApplication.run(SinkApplication.class, args);
    }

}

到这里,我们快速入门示例的编码任务就已经完成了。下面我们分别启动RabbitMQ以及该Spring Boot应用,然后做下面的试验,看看它们是如何运作的。

手工测试验证
  • 我们先来看一下Spring Boot应用的启动日志。
2020-05-12 17:57:14.374  INFO 41344 --- [           main] c.s.b.r.p.RabbitExchangeQueueProvisioner : declaring queue for inbound: input.anonymous.q3QkcC_2Rh61PS3XAt8erA, bound to: input
2020-05-12 17:57:14.539  INFO 41344 --- [           main] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#2513a118:0/SimpleConnection@656f62dc [delegate=amqp://guest@47.104.219.70:5672/, localPort= 60582]
2020-05-12 17:57:14.869  INFO 41344 --- [           main] o.s.i.a.i.AmqpInboundChannelAdapter      : started inbound.input.anonymous.q3QkcC_2Rh61PS3XAt8erA
2020-05-12 17:57:14.869  INFO 41344 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {message-handler:inbound.input.default} as a subscriber to the 'bridge.input' channel
2020-05-12 17:57:14.869  INFO 41344 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started inbound.input.default
2020-05-12 17:57:14.870  INFO 41344 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2020-05-12 17:57:14.979  INFO 41344 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 60585 (http)
2020-05-12 17:57:14.982  INFO 41344 --- [           main] com.didispace.stream.SinkApplication     : Started SinkApplication in 6.92 seconds (JVM running for 7.644)

从上面的日志内容中,我们可以获得以下信息:

Created new connection: rabbitConnectionFactory#2513a118:0/SimpleConnection@656f62dc [delegate=amqp://guest@47.104.219.70:5672/, localPort= 60582]
  • 使用guest用户创建了一个指向127.0.0.1:5672位置的RabbitMQ连接,在RabbitMQ的控制台中我们也可以发现它。
    在这里插入图片描述
  • 声明了一个名为input.anonymous.Y8VsFILmSC27eS5StsXp6A的队列,并通过RabbitMessageChannelBinder将自己绑定为它的消费者。这些信息我们也能在RabbitMQ的控制台中发现它们。在这里插入图片描述
  • 下面我们可以在RabbitMQ的控制台中进入input.anonymous.Y8VsFILmSC27eS5StsXp6A队列的管理页面,通过Publish Message功能来发送一条消息到该队列中。
    在这里插入图片描述此时,我们可以在当前启动的Spring Boot应用程序的控制台中看到下面的内容:
INFO 16272 --- [C27eS5StsXp6A-1] com.didispace.HelloApplication           : Received: [B@7cba610e

我们可以发现在应用控制台中输出的内容就是SinkReceiver中receive方法定义的,而输出的具体内容则是来自消息队列中获取的对象。这里由于我们没有对消息进行序列化,所以输出的只是该对象的引用,在后面的小节中我们会详细介绍接收消息后的处理。

在顺利完成上面快速入门的示例后,我们简单解释一下上面的步骤是如何将我们的Spring Boot应用连接上RabbitMQ来消费消息以实现消息驱动业务逻辑的。

Spring Cloud Stream的核心注解,它们都被定义在SinkReceiver中:

  • @EnableBinding :该注解用来指定一个或多个定义了@Input@Output注解的接口,以此实现对消息通道(Channel)的绑定。
  • @EnableBinding(Sink.class) : Sink接口,该接口是Spring Cloud Stream中默认实现的对输入消息通道绑定的定义,源码如下:
public interface Sink {

    String INPUT = "input";

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

}
  • @StreamListener :该注解主要定义在方法上,作用是将被修饰的方法注册为消息中间件上数据流的事件监听器,注解中的属性值对应了监听的消息通道名。在上面的例子中,我们通过@StreamListener(Sink.INPUT)注解将receive方法注册为对input消息通道的监听处理器,所以当我们在RabbitMQ的控制页面中发布消息的时候,receive方法会做出对应的响应动作。
编写消费消息的单元测试用例
  • 在上面创建的工程中创建单元测试类:
@RunWith(SpringRunner.class)
@EnableBinding(value = {SinkApplicationTests.SinkSender.class})
public class SinkApplicationTests {

    @Autowired
    private SinkSender sinkSender;

    @Test
    public void sinkSenderTester() {
        sinkSender.output().send(MessageBuilder.withPayload("produce a message :http://blog.didispace.com").build());
    }

    public interface SinkSender {

        String OUTPUT = "input";

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

    }

}
  • 在应用了上面的消息消费者程序之后,运行这里定义的单元测试程序,我们马上就能在消息消费者的控制台中收到下面的内容:
2020-05-12 18:25:30.579  INFO 41344 --- [h61PS3XAt8erA-1] com.didispace.stream.SinkReceiver        : Received: produce a message :http://blog.didispace.com

在上面的单元测试中,我们通过@Output(SinkSender.OUTPUT)定义了一个输出通过,而该输出通道的名称为input,与前文中的Sink中定义的消费通道同名,所以这里的单元测试与前文的消费者程序组成了一对生产者与消费者。到这里,本文的内容就次结束,如果您能够独立的完成上面的例子,那么对于Spring Cloud Stream的基础使用算是入门了。但是,Spring Cloud Stream的使用远不止于此,在近期的博文中,我讲继续更新这部分内容,帮助他们来理解和用好Spring Cloud Stream来构建消息驱动的微服务!

参考文档

参考教程文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值