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:
defaultRabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: xxxx
username: xxxx
password: xxxx
port: 5672
bindings:
output:
destination: studyExchange
content-type: application/json
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
我这里提出三点可行的方法
- yaml中不要使用tab来进行缩进,使用空格进行对齐
- bindings属性中的binder不要缩进,不要缩进,不要缩进,报红是不影响启动的,也可以用{}括起来
- 由于视频中给出的RabbitMQ是本地启动的,而我是在Linux上开启的一个RabbitMQ,所以上面两个方法都不行,可以尝试以下操作:
- 增加一个RabbitMQ的配置,因为视频中给出的方法需要读取两次RabbitMQ配置,第一次找不到就会直接报错无法连接
server:
port: 8101
spring:
application:
name: cloud-rabbitmq-provider
rabbitmq:
host: xxxx
username: xxxx
password: xxxx
port: 5672
cloud:
stream:
binders:
defaultRabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: xxxx
username: xxxx
password: xxxx
port: 5672
bindings:
output:
destination: studyExchange
content-type: application/json
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
- 另外,检查你在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)
public class MessageProviderImpl implements MessageProvider {
@Resource(name = "output")
private MessageChannel messageChannel;
@Override
public String send() {
String serial = UUID.randomUUID().toString();
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已经成功添加,以及发布消息的曲线图
|