SpringCloud Stream整合RabbitMQ各种报错以及解决方案

1,405 阅读4分钟

@[toc](SpringCloud Stream+RabbitMQ各种报错解决)

今天在学习到SpringCloud Stream消息驱动时,工程cloud-stream-rabbitmq-provider8101,作为生产者进行发布消息,使用的RabbitMQ作为消息中间件,启动报错.....针对以下几种错误,做出一些个人可行的解决方案,供参考

1. Failed to load property source from location 'classpath:/application.yml

由于视频给出的YAML配置文件是针对本地配置的RabbitMQ,所以原始的yaml为

server:
  port: 8101

spring:
  application:
    name: cloud-rabbitmq-provider
  cloud:
    stream:
      binders: # 配置需要绑定的RabbitMQ的服务信息
        defaultRabbit: # 表示定义的名称,用于binding的整合
          type: rabbit # 消息组件类型
          environment: # 配置RabbitMQ的环境
            spring:
              rabbitmq:
                host: xxxx
                username: xxxx
                password: xxxx
                port: 5672
# 服务的整合处理
      bindings:
        output: # 生产者
          destination: studyExchange      # Exchange名称
          content-type: application/json # 设置消息类型,使用json,文本数据使用"text/plain"
          binder: defaultRabbit       # 设置需要绑定哪一个消息服务(对应消息服务名)

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    lease-expiration-duration-in-seconds: 30 # 心跳的间隔时间
    lease-renewal-interval-in-seconds: 60    # 间隔时间
    instance-id: send-8101.com # 信息列表中显示的主机名
    prefer-ip-address: true    # 访问路径使用IP地址

我这里提出三点可行的方法

  • yaml中不要使用tab来进行缩进,使用空格进行对齐
  • bindings属性中的binder不要缩进,不要缩进,不要缩进,报红是不影响启动的,也可以用{}括起来
  • 由于视频中给出的RabbitMQ是本地启动的,而我是在Linux上开启的一个RabbitMQ,所以上面两个方法都不行,可以尝试以下操作:
  1. 增加一个RabbitMQ的配置,因为视频中给出的方法需要读取两次RabbitMQ配置,第一次找不到就会直接报错无法连接
server:
  port: 8101

spring:
  application:
    name: cloud-rabbitmq-provider
  rabbitmq:
    host: xxxx
    username: xxxx
    password: xxxx
    port: 5672
    
  cloud:
    stream:
      binders: # 配置需要绑定的RabbitMQ的服务信息
        defaultRabbit: # 表示定义的名称,用于binding的整合
          type: rabbit # 消息组件类型
          environment: # 配置RabbitMQ的环境
            spring:
              rabbitmq:
                host: xxxx
                username: xxxx
                password: xxxx
                port: 5672
# 服务的整合处理
      bindings:
        output: # 生产者
          destination: studyExchange      # Exchange名称
          content-type: application/json # 设置消息类型,使用json,文本数据使用"text/plain"
          binder: defaultRabbit       # 设置需要绑定哪一个消息服务(对应消息服务名)

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    lease-expiration-duration-in-seconds: 30 # 心跳的间隔时间
    lease-renewal-interval-in-seconds: 60    # 间隔时间
    instance-id: send-8101.com # 信息列表中显示的主机名
    prefer-ip-address: true    # 访问路径使用IP地址
  1. 另外,检查你在==Linux上是否启动了RabbitMQ,以及是否关闭了防火墙==,就像这样 在这里插入图片描述在这里插入图片描述3. 使用你的==主机IP地址:15672==查看是否能登录RabbitMQ界面 在这里插入图片描述到这里,基本上就可以解决了。

2. Field messageProvider in com.hz.stream.controller.SendMessageController required a single bean, but 3 were found:

- output: defined by method 'output' in null
- nullChannel: defined in null
- errorChannel: defined in null

这是因为在视频中的MessageProviderImpl类中,Resource是没有指明使用哪一个MessageChannel消息信道的,在Resource注解中指明==output==,由于当前是消息生产者服务。另外,这里的send方法中return null对发布消息是没有影响的,因为==消息生产者服务构建(build)一个Message消息对象,然后传递给Source池,再通过管道binding输出给消息中间件MQ,最后消费者服务的Sink池中可以获取到Message对象==

@EnableBinding(Source.class) // 将信道channel和exchange绑定在一起, Source定义消息的推送管到(生产者->Source)
public class MessageProviderImpl implements MessageProvider {

    @Resource(name = "output")
    private MessageChannel messageChannel;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        // 消息生产者服务构建(build)一个Message消息对象,然后传递给Source池,再通过管道binding输出给消息中间件MQ
        // 最后消费者服务的Sink池中可以获取到Message对象
        messageChannel.send(MessageBuilder.withPayload(serial).build());
        System.out.println("*****serial: " + serial);
        return null;
    }
}

3. 正常启动后,返回工程中的controller方法,报500错误

在这里插入图片描述注意:这里报的空指针异常,并不是因为在serviceImpl中return null导致的, 这里是因为我的粗心==没有在MessageProviderImpl上添加注解Autowired导致该对象没有注入进来。==

@RestController
public class SendMessageController {

    @Autowired
    private MessageProviderImpl messageProvider;

    @GetMapping("/sendMsg")
    public String sendMessage(){

      return messageProvider.send();
    }
}

4. 启动测试

控制台正常打印出流水号,完美解决! 在这里插入图片描述.另外,查看RabbitMQ的web界面,在交换机一栏中可以看到studyExchange已经成功添加,以及发布消息的曲线图 在这里插入图片描述在这里插入图片描述