Rabbitmq调用FeignClient接口失败

文章目录

  • 一、框架及逻辑介绍
    • 1.背景服务介绍
    • 2.问题逻辑介绍
  • 二、代码
    • 1.A服务
    • 2.B服务
    • 3.C服务
  • 三、解决思路
    • 1.确认B调用C服务接口是否能正常调通
    • 2.确认B服务是否能正常调用A服务
    • 3.确认消息能否正常消费
    • 4.总结
  • 四、修改代码验证
    • 1.B服务异步调用C服务接口——失败
    • 2.将消费消息放到C服务中,消费时直接调用service——成功
  • 五、结论

走过路过大神帮忙给个正确解决方案~~~~~

一、框架及逻辑介绍

1.背景服务介绍

微服务结构,目前有A、B、C三个服务。

  • A服务:做一些工具类的功能
  • B服务:类似于门户,调用A、C服务来给到前端
  • C服务:基础模块,日志、权限、数据维护

2.问题逻辑介绍

  • A服务:实现blast功能,该功能是异步任务,需要几分钟的时间才能执行完成,所以采用了消息队列的方式通知功能完成,可查看数据。当代码执行完成之后通过rabbitmq发送消息到B服务
  • B服务:消费消息,调用C服务存储完成通知数据
  • C服务:提供FeignClient接口

二、代码

1.A服务

业务代码,详细的逻辑部分就不列出代码部分了, 测试确认无问题。

@Api(tags = "blast工具")
@RequiredArgsConstructor
@RequestMapping("blast")
@RestController
public class BlastController {private final BlastService blastService;@PostMapping("uniport")@ApiOperation("蛋白质序列对比")public ApiResponse<Boolean> check(@RequestBody BlastEntity blastEntity) {boolean flag = blastService.check(blastEntity);if(flag){return ApiResponse.success(flag);}else{return ApiResponse.failure("序列比对失败");}}@GetMapping("uniportDetail")@ApiOperation("蛋白质序列对比详情")public ApiResponse<BlastLogEntity> selectDetailById(@ApiParam("主键") @RequestParam("id") Integer id){return ApiResponse.success(blastService.selectDetailById(id));}
}

通过FeignClient提供功能接口给B服务(门户)

@FeignClient(name = "tool", url = "${customer.tool-url}")
public interface DataClient {@PostMapping("/blast/uniport")@ApiOperation("蛋白质序列对比")ApiResponse<Boolean> checkBlastUniprot(@RequestBody BlastEntity blastEntity);@GetMapping("/blast/uniportDetail")@ApiOperation("蛋白质序列对比详情")ApiResponse<BlastLogEntity> selectDetailById(@ApiParam("主键") @RequestParam("id") Integer id);
}

通过Rabbitmq发送消息

@Configuration
public class DirectRabbitMQConfig {//创建一个名为TestDirectExchange的Direct类型的交换机@BeanDirectExchange directExchange(){// durable:是否持久化,默认是false,持久化交换机。// autoDelete:是否自动删除,交换机先有队列或者其他交换机绑定的时候,然后当该交换机没有队列或其他交换机绑定的时候,会自动删除。// arguments:交换机设置的参数,比如设置交换机的备用交换机(Alternate Exchange),当消息不能被路由到该交换机绑定的队列上时,会自动路由到备用交换机return new DirectExchange(RabbitMqConstants.EXCHANGE_NAME,true,false);}//创建一个名为insertChassisDirectQueue的队列@Beanpublic Queue insertBlastDirectQueue(){// durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效// exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable// autoDelete:是否自动删除,有消息者订阅本队列,然后所有消费者都解除订阅此队列,会自动删除。// arguments:队列携带的参数,比如设置队列的死信队列,消息的过期时间等等。return new Queue(RabbitMqConstants.INSERT_BLAST_NAME,true);}//绑定交换机和队列@BeanBinding insertBlastDirect(){return BindingBuilder.bind(insertBlastDirectQueue()).to(directExchange()).with(RabbitMqConstants.INSERT_BLAST_KEY);}
}

2.B服务

消费消息,根据输出日志,可以看到消费消息成功。
但是走到apiClient.addLogMessage(logMessageEntity);不报错,C服务无响应,断点查看apiClient是可以看到C服务的信息localhost:8080的。

	@RabbitHandler@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = INSERT_BLAST_NAME, durable = "true"),exchange = @Exchange(value = RabbitMqConstants.EXCHANGE_NAME),key = INSERT_BLAST_KEY)})public void insertBlast(Map map, Channel channel, Message message) {try {LOGGER.info("【生成的消息-blast序列比对结果】:{}", map.toString());channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);BlastLogEntity blastLogEntity = TypeSwitchUtil.toSnakeObject(JSON.toJSONString(map), BlastLogEntity.class);if (null == blastLogEntity || StringUtils.isEmpty(blastLogEntity.getContent())) {LOGGER.warn("【生成的消息-blast序列比对结果】:{}", map.toString());} else {LogMessageEntity logMessageEntity = new LogMessageEntity();logMessageEntity.setTargetId(blastLogEntity.getId());logMessageEntity.setUserId(String.valueOf(blastLogEntity.getUserId()));logMessageEntity.setMsgType(MsgStatusEnum.BLAST.getCode());logMessageEntity.setContent(MsgStatusEnum.BLAST.getMsg());apiClient.addLogMessage(logMessageEntity);}} catch (Exception e) {LOGGER.error(e.getMessage());}}

3.C服务

@FeignClient(name = "api", url = "${customer.url}", configuration = FeignConfig.class)
public interface ApiClient {@PostMapping("/cms/logMessage/add")@ApiOperation("新增系统通知发送记录")ApiResponse<Boolean> addLogMessage(@RequestBody LogMessageEntity logMessageEntity);
}

三、解决思路

1.确认B调用C服务接口是否能正常调通

在B服务中,通过Controller暴露接口,调用C服务FeignClient的@PostMapping("/cms/logMessage/add") 接口,通过swagger测试,数据成功存储到数据库中。

——接口没有问题,服务之间通信也没有问题

2.确认B服务是否能正常调用A服务

在B服务中,调用A服务接口,测试成功。

——服务之间通信没有问题

3.确认消息能否正常消费

在B服务中,调用A服务接口,A服务输出发送消息日志。B服务消费输出日志。

——消息无问题

4.总结

在这里插入图片描述

  • 服务之间通信没有问题
    在这里插入图片描述

  • 消息提供和消费没有问题

综合猜测可能是线程或事务问题。

四、修改代码验证

1.B服务异步调用C服务接口——失败

	@RabbitHandler@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = INSERT_BLAST_NAME, durable = "true"),exchange = @Exchange(value = RabbitMqConstants.EXCHANGE_NAME),key = INSERT_BLAST_KEY)})public void insertBlast(Map map, Channel channel, Message message) {try {LOGGER.info("【生成的消息-blast序列比对结果】:{}", map.toString());channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);BlastLogEntity blastLogEntity = TypeSwitchUtil.toSnakeObject(JSON.toJSONString(map), BlastLogEntity.class);if (null == blastLogEntity || StringUtils.isEmpty(blastLogEntity.getContent())) {LOGGER.warn("【生成的消息-blast序列比对结果】:{}", map.toString());} else {LogMessageEntity logMessageEntity = new LogMessageEntity();logMessageEntity.setTargetId(blastLogEntity.getId());logMessageEntity.setUserId(String.valueOf(blastLogEntity.getUserId()));logMessageEntity.setMsgType(MsgStatusEnum.BLAST.getCode());logMessageEntity.setContent(MsgStatusEnum.BLAST.getMsg());CompletableFuture.runAsync(() -> {apiClient.addLogMessage(logMessageEntity);});}} catch (Exception e) {LOGGER.error(e.getMessage());}}

经测试,未能解决问题。

2.将消费消息放到C服务中,消费时直接调用service——成功

	@RabbitHandler@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "blast.insert.queue", durable = "true"),exchange = @Exchange(value = "tool"),key = "blast.insert")})public void insertBlast(Map map, Channel channel, Message message) {try {LOGGER.info("【生成的消息-blast序列比对结果】:{}", map.toString());channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);if (null == map || StringUtils.isEmpty(map.get("id").toString())) {LOGGER.warn("【生成的消息-blast序列比对结果】:{}", map.toString());} else {LogMessageEntity logMessageEntity = new LogMessageEntity();logMessageEntity.setTargetId(Integer.valueOf(map.get("id").toString()));logMessageEntity.setUserId(String.valueOf(map.get("user_id")));logMessageEntity.setMsgType(MsgStatusEnum.BLAST.getCode());logMessageEntity.setContent(MsgStatusEnum.BLAST.getMsg());logMessageService.save(logMessageEntity);}} catch (Exception e) {LOGGER.error(e.getMessage());}}

在这里插入图片描述

五、结论

在使用消息队列(MQ)调用FeignClient服务时,采取以下步骤:

  • 配置消息队列:首先,确保已正确配置和启动您所使用的消息队列,例如 RabbitMQ 或者 Kafka。

  • 创建消息生产者:创建一个消息生产者,用于将消息发送到消息队列。您可以使用消息队列的客户端库或框架来实现此功能。

  • 发送消息:在需要调用FeignClient服务的地方,将消息发送到消息队列。消息中包含请求的相关信息,例如服务名称、路径、参数等。

  • 创建消息消费者:创建一个消息消费者,用于从消息队列接收消息并处理。

  • 处理消息:在消息消费者中,处理接收到的消息。根据消息中的请求信息,使用FeignClient来调用相应的服务。

虽然通过直接调用service的方式成功进行数据存储了,这样做也没有违背原有的逻辑。
但是问题仍然没有一个正确的解决方式,希望走过路过的大神能指点一二,在线求助。

走过路过大神帮忙给个正确解决方案~~~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/651269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能AI系统开发,专业软件硬件物联网开发公司,探索未来科技新纪元

在信息时代&#xff0c;人工智能&#xff08;AI&#xff09;、物联网等前沿技术日益受到人们的关注。智能AI系统、专业软件硬件物联网开发公司应运而生。今天&#xff0c;我们将向大家介绍一家位于XX城的专业公司&#xff0c;致力于智能AI系统开发和软件硬件物联网领域的创新研…

大数据安全 | 期末复习(下)

文章目录 &#x1f4da;安全策略和攻击&#x1f34b;&#x1f407;安全协议&#x1f407;IPsee&#x1f407;SSL&#x1f407;SSH&#x1f407;S/MIME协议&#x1f407;公钥基础设施PKI&#x1f407;PGP&#x1f407;HTTPS&#x1f407;防火墙&#x1f407;防毒墙&#x1f407;…

解决:‘chromedriver’ executable needs to be in PATH

解决&#xff1a;chromedriver’ executable needs to be in PATH 文章目录 解决&#xff1a;chromedriver’ executable needs to be in PATH背景报错问题报错翻译报错位置代码报错原因解决方法方法一&#xff1a;检查python安装路径有没有添加到环境变量里面方法二&#xff1…

谷歌vue插件安装包

链接&#xff1a;https://pan.baidu.com/s/1wTCqn7ttc-rF_wZScfEgPw?pwde7k6 提取码&#xff1a;e7k6 修改D:\谷歌浏览器插件安装包\devtools-main\packages\shell-chrome下manifest.json文件 将里面这四个文件地址改为src下面&#xff0c;因为地址在src下&#xff0c;直接…

基于Guava布隆过滤器的海量字符串高效去重实践

在Java环境中处理海量字符串去重的问题时&#xff0c;布隆过滤器&#xff08;BloomFilter&#xff09;是一种非常高效的数据结构&#xff0c;尽管它有一定的误报率。布隆过滤器适用于那些可以接受一定误报率&#xff0c;并且希望节省空间和时间成本的场景。 布隆过滤器应用 使…

Fastjson代码审计实战

代码审计-漏洞复现 漏洞分析采用的是华夏ERP2.3&#xff0c; 查看pom.xml文件发现fastjson版本1.2.55&#xff0c;该版本存在漏洞&#xff0c;利用DNSlog进行验证。 fastjson涉及反序列化的方法有两种&#xff0c;JSON.parseObject()和JSON.parse()&#xff0c;在代码中直接搜…

MySQL 联合索引

文章目录 1.简介2.最左匹配3.最左匹配原理4.如何建立联合索引?5.覆盖索引参考文献 1.简介 联合索引指建立在多个列上的索引。 MySQL 可以创建联合索引&#xff08;即多列上的索引&#xff09;。一个索引最多可以包含 16 列。 联合索引可以测试包含索引中所有列的查询&#…

关于在Ubuntu20.04(ROS1 noetic)中使用catkin_make编译时发生的与pyhton版本不兼容的问题解决办法

今天在另外一台电脑上操作复现【ROS建模&#xff1a;一起从零手写URDF模型】这个博客时&#xff0c;发生了一些问题&#xff0c;特此记录下来 【ROS建模&#xff1a;一起从零手写URDF模型】链接&#xff1a;https://blog.csdn.net/qq_54900679/article/details/135726348?spm…

JasperReports渲染报表文件时候,读取图片报错:Byte data not found at:xxx.png.\r\n\tat

目录【知识星球】 1.1、错误描述 1.2、解决方案 1.1、错误描述 最近在工作中&#xff0c;使用JasperReports报表比较多一些&#xff0c;有次线上环境里面运行报错&#xff0c;查看报错日志&#xff0c;如下所示&#xff1a; net.sf.jasperreports.engine.JRException: Byte…

Spring Boot 启动错误【Kotlin】

目录 错误详情 错误原因 解决方法一 解决方法二 错误详情 Kotlin:     Module was compiled with an incompatible version of Kotlin.     The binary version of its metadata is 1.7.1, expected version is 1.1.16. 错误原因 编译器或构建工具的版本不匹配所造…

(免费领源码)python#Mysql苏州一日游之可视化分析69216-计算机毕业设计项目选题推荐

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对旅游服务等问题&#xff0c;对旅游服务进行…

docker 构建应用

docker 应用程序开发手册 开发 docker 镜像 Dockerfile 非常容易定义镜像内容由一系列指令和参数构成的脚本文件每一条指令构建一层一个 Dockerfile 文件包含了构建镜像的一套完整指令指令不区分大小写&#xff0c;但是一般建议都是大写从头到尾按顺序执行指令必须以 FROM 指…

Web3.0投票如何做到公平公正且不泄露个人隐私

在当前的数字时代&#xff0c;社交平台举办投票活动已成为了一种普遍现象。然而&#xff0c;随之而来的是一些隐私和安全方面的顾虑&#xff0c;特别是关于个人信息泄露和电话骚扰的问题。期望建立一个既公平公正又能保护个人隐私的投票系统。Web3.0的出现为实现这一目标提供了…

java web mvc-04-Apache Wicket

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …

完美调试android-goldfish(linux kernel) aarch64的方法

环境要求 Mac m1Mac m1 中 虚拟机安装aarch64 ubuntu22.02Mac m1安装OrbStack&#xff0c;并在其中安装 ubuntu20.04&#xff08;x86_64&#xff09; 构建文件系统 在虚拟机 aarch64 ubuntu22.02中构建 安装必要的库 sudo apt-get install libncurses5-dev build-essenti…

【江科大】STM32:MPU6050介绍

文章目录 MPU6050介绍结构图MPU6050参数硬件电路模块内部结构框图数据帧格式寄存器地址 MPU6050介绍 MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0c;可进一步得到姿态角&#xff0c;常应用于平衡…

STM32CubeMX教程27 SDIO - 读写SD卡

目录 1、准备材料 2、实验目标 3、轮询方式读取SD卡流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.0、工程基本配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.0、配置Project Manager页面 3.2.1、外设初始化调用流程 3.2.2、外设中断调用流…

现货黄金做日内交易和波段交易有何差异?

在现货黄金投资中&#xff0c;日内交易和波段交易都是投资者常用的手段。但投资者其实搞不懂两者有何区别&#xff0c;有时甚至不清楚自己做的是日内交易还是波段交易&#xff0c;下面我们就来讨论一下这两种交易方法的异同。 两者的区别主要是在持仓的时间上。日内交易顾名思义…

Python中的`__all__`魔法函数使用详解

概要 Python是一门灵活而强大的编程语言&#xff0c;提供了各种机制来控制模块的导入和访问。其中&#xff0c;__all__魔法函数是一种用于限制模块导入的机制&#xff0c;可以明确指定哪些变量、函数或类可以被导入。本文将深入探讨__all__的作用、用法以及示例&#xff0c;以…

C++:类和对象(中)

类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成…