十三、SpringCloud之消息和异步及Spring Cloud Stream的使用

本文详细介绍异步处理在微服务架构中的应用,包括RabbitMQ的配置与使用,以及Spring Cloud Stream如何简化消息中间件的集成,实现高效的数据交换与处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

1、异步

客户请求不会阻塞进程,服务端的响应是可以非即时的。

2、异步的常见形态

  • 通知
  • 请求/异步响应
  • 消息

3、MQ应用场景

  • 异步处理:比如用户注册之后,需要发送短信或者邮件,注册信息写入数据裤之后通过异步消息,让短信服务和邮件服务去做他们的事,提升用户体验。
  • 流量削峰:秒杀系统,在应用前端加入消息队列,从而控制活动的人数,加入队列长度超过最大,应该直接抛弃用户请求,或者直接跳转到错误页面,
  • 日志处理
  • 应用解藕:用户下单后,订单服务将消息写入消息队列,商品服务来订阅这个下单的消息,采用拉或者推的方式获取下单的信息

二、RabbitMQ的基本使用

  • pom.xml
 <!-- 引入bus-amqp 消息队列-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
  • bootstrap.yml
#消息队列
  rabbitmq:
    host: 192.168.3.233
    username: guest
    password: guest
    port: 5672
  • MqReceiver
/**
 * @Title 接收MQ消息
 * @Author zwj
 * @Date 2018/11/26
 * @Description
 */
@Slf4j
@Component
public class MqReceiver {
    //@RabbitListener(queues = "myQueue") //手动创建队列
    //2.自动创建队列
    //@RabbitListener(queuesToDeclare = @Queue("myQueue"))
    //3.自动创建,Exchange和Queue绑定
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("myQueue"),
            exchange = @Exchange("myExchange")
    ))
    public void process(String message){
        log.info("MqReceiver:{}",message);
    }

    /**
     * 数码供应商服务
     * */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange("myOrder"),
            key = "computer",
            value = @Queue("computerOrder")

    ))
    public void processComputer(String message){
        log.info("computer MqReceiver:{}",message);
    }

    /**
     * 水果供应商服务
     * */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange("myOrder"),
            key = "fruit",
            value = @Queue("fruitOrder")

    ))
    public void processFruit(String message){
        log.info("fruit MqReceiver:{}",message);
    }
}
  • sendMassage
/**
 * @Title 发送消息测试
 * @Author zwj
 * @Date 2018/11/26
 * @Description
 */
@Component
public class MqReceiverTest extends ServerApplicationTests {
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Test
    public void send() {
        amqpTemplate.convertAndSend("myQueue","now"+new Date());
    }

    @Test
    public void sendOrder() {
        amqpTemplate.convertAndSend("myOrder","computer","now"+new Date());
    }
}

三、Spring Cloud Stream的使用

Spring Cloud Stream 为微服务应用构建消息驱动能力的框架,应用程序通过input,output来与Stream中的Binder交互,Stream中的Binder与中间件(Middleware)交互,Binder是stream的抽象概念,是应用与消息中间件的粘合剂,使用Stream最大的方便之处莫过于对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至做到动态切换中间件。

Stream支持的中间件只有两种:RabbitMQ、Kadka

  • pom.xml
<!-- 引入Spring Cloud Stream -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
  • bootstrap.yml
spring:
  cloud:
      stream:
        bindings:
          input: #消息名字
            group: order #消息分组  项目不管启动多少实例,都只有一个实例接收消息
            content-type: application/json #序列化
#消息队列
  rabbitmq:
    host: 192.168.3.233
    username: guest
    password: guest
    port: 5672
  • StreamClient
/**
 * @Title
 * @Author zwj
 * @Date 2018/11/26
 * @Description
 */
public interface StreamClient {
    //报错:Invalid bean definition with name 'myMessageOrdersssss' defined in com.imooc.order.message.StreamClient: bean definition with this name already exists
    //解决方法:@Input和@Output不可一样,同一服务里面的信道名字不能一样,在不同的服务里可以相同名字的信道
    String INPUT = "input";
    String OUTPUT = "output";
    @Input(StreamClient.INPUT)
    SubscribableChannel input();
    @Output(StreamClient.OUTPUT)
    MessageChannel output();

    String INPUT2 = "input2";
    String OUTPUT2 = "output2";
    @Input(StreamClient.INPUT2)
    SubscribableChannel input2();
    @Output(StreamClient.OUTPUT2)
    MessageChannel output2();
}
  • StreamReceiver
/**
 * @Title
 * @Author zwj
 * @Date 2018/11/26
 * @Description
 */
@Component
@EnableBinding(StreamClient.class)
@Slf4j
public class StreamReceiver {
//    @StreamListener(StreamClient.INPUT)
//    public void process(Object message){
//        System.out.println(message);
//        log.info("StreamReceiver:{}",message);
//    }

    /**
     * 接收orderDTO对象消息
     * */
    @StreamListener(value = StreamClient.INPUT)
    @SendTo(StreamClient.INPUT2) //消息发送给谁
    public String process(OrderDTO message){
        log.info("StreamReceiver:{}",message);
        return"收到了";
    }

    /**
     * 接收到消息之后返回的消息
     * */
    @StreamListener(value = StreamClient.INPUT2)
    public void process2(OrderDTO message){
        log.info("StreamReceiver2:{}",message);
    }
}
  • SendMessageController
/**
 * @Title
 * @Author zwj
 * @Date 2018/11/26
 * @Description
 */
@RestController
public class SendMessageController {
    @Autowired
    private StreamClient streamClient;

//    @GetMapping("/sendMessage")
//    public void process(){
//        String message = "now "+new Date();
//        streamClient.input().send(MessageBuilder.withPayload(message).build());
//    }

    @GetMapping("/sendMessage")
    public void process(){
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setOrderId("123456");
        streamClient.input().send(MessageBuilder.withPayload(orderDTO).build());
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值