当前位置: 首页 > news >正文

江西建设局网站广东网站建设类公司

江西建设局网站,广东网站建设类公司,做淘宝优惠网站,app推荐说明#xff1a;本文记录一次偶然出现的空指针异常#xff0c;在微服务架构中#xff0c;一个服务在调用另一个服务时#xff0c;出现了空指针异常。 业务描述#xff1a;在做订单超时功能时#xff0c;大家都知道#xff0c;可以使用RabbitMQ延迟队列#xff0c;下单…说明本文记录一次偶然出现的空指针异常在微服务架构中一个服务在调用另一个服务时出现了空指针异常。 业务描述在做订单超时功能时大家都知道可以使用RabbitMQ延迟队列下单的同时给队列发送一个延迟消息消息的内容是订单号比如延迟10分钟。10分钟之后该消息被消费者监听到会根据该订单ID查询数据库看该订单的状态是否为已支付是则忽略否则取消该订单恢复商品库存等等其他操作然而此时出现了空指针异常消息未被消费被路由到死信队列中。 微服务调用报空指针异常 消息被路由到死信队列 如下图的第三步 分析 首先排除FeignClient的问题因为下单减少库存取消订单恢复库存我使用的是同一个接口只是修改了商品的正负数不可能出现下单时可以取消订单时再使用就报错。 controller层代码 /*** 根据ID更新商品库存* param id* param num*/PutMapping(/update/{id}/{num})public void updateStockById(PathVariable(id) Long id, PathVariable(num) Integer num){itemService.updateStockById(id,num);}service层代码 Overridepublic void updateStockById(Long id, Integer num) {if (!ObjectUtil.isAllNotEmpty(id, num)) {System.out.println(参数不能为空);}if (id 0 || num 0) {System.out.println(参数非法);}update().setSql(stock stock num).eq(id, id).update();}其次再思考会不会不是因为Feign的调用报错而是微服务之间有什业务产生的报错。于是我找到了拦截器。 为了保证用户登录后经过Gateway网关后信息可以被下游服务获取到我的代码中是使用MVC拦截器Feign拦截器实现的如下图 每个服务会有两个拦截器分别把服务接收到的请求发出的请求拦截到然后分别解析用户信息添加用户信息到请求头以此达到参数透传用户信息可在微服务之间流传。 MVC拦截器代码获取请求头中用户的ID存到ThreadLocal中 public class AuthorizationInterceptor implements HandlerInterceptor {/*** 收到请求会执行的方法* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String id request.getHeader(authorization);if (id ! null id ! ){long l Long.parseLong(id);TokenThreadLocal.set(l);}else {responseHandler(response);return false;}// 放行return true;}…… }Feign拦截器将本服务中的ThreadLocal中的用户ID再设置到请求头上 /*** 发送请求拦截器*/ Slf4j public class AuthorizationRequestInterceptor implements RequestInterceptor {Overridepublic void apply(RequestTemplate requestTemplate) {requestTemplate.header(authorization,TokenThreadLocal.get().toString());} }排查 给这两个地方分别打上断点等订单超时后进入拦截器的代码排查一下 断点来到Feign拦截器选中这行代码一看原来是这里报了空指针异常 再一看原来是TokenThreadLocal.get().toString()这里是空的 然后恍然大悟MQ发送消息是异步请求ThreadLocal本地线程池对象自然为空 解决 很自然的想到一种很简单的解决方法发送消息的时候把ThreadLocal中的值用户ID也给发到延迟队列中然后在消费者监听的代码里面再使用ThreadLocal的set()方法把用户ID设置到线程池中 把订单ID、用户ID封装成一个Map转为json格式发送到延迟队列里 消费者代码这边使用ThreadLocal的set()方法把用户ID再设置进去 启动测试下单等待订单超时清理超时订单进入断点问题解决 总结 这是一个非常隐蔽的异常因为设置了死信队列未被成功消费的消息会被路由到死信队列中程序并不会报错并且因为订单表的内容大部分是在订单服务中此异常仅仅会影响订单被取消后调用商品服务恢复商品库存数量这一个很小的功能未能执行要排除出来是非常困难的。 而问题原因概括来说是因为ThreadLocal的值不能在RabbitMQ的消息中传递导致在使用拦截器获取ThreadLocal值的时候报了空指针异常。
http://www.zqtcl.cn/news/197790/

相关文章:

  • 深圳 网站建设设计如何用公众号做网站
  • 免费微信网站制作北风淘淘网站开发
  • 建筑模型设计网站建设网站设计 分辨率
  • 网站规划包括哪些内容西部建设网站
  • 网站html静态化网站整体色彩的建设
  • 长春比较有名的做网站建设宁波网站建设联系电话查询
  • 建网站中企动力推荐网络营销外包总代理
  • 网站怎么续费网站内链检测
  • 织梦网站地图样式中国品牌网站
  • 上海金山区建设局网站临淄信息港发布信息
  • 保定外贸网站建设学生网站建设首页
  • 商城网站备案要求wordpress插件 手机版
  • 北京市网站备案查询石家庄建设信息网必须交费吗
  • 北京优化网站方法四川省建设局网站
  • 怎么做网站能快速赚钱重庆快速建站
  • 河南专业网站建设公司首选培训心得简短200字
  • 销售网站开发业务高端建网站多少钱
  • 几个做ppt的网站知乎青岛高品质网站制作
  • 网站seo插件wordpress模板中文版
  • 夹江移动网站建设手机网站微信登陆
  • 浏阳做网站网易企业邮箱注册官网
  • 东莞网站建设是什么意思自己怎么做企业网站建设
  • 免费的网站申请泰州网站整站优化
  • 毕业设计做企业门户网站过期域名网站
  • 网站建设和风险分析简单网页制作代码模板
  • 照片展示网站那个网站可以做攻略
  • 优秀网站设计赏析万网网站备案多久
  • 网站维护服务有哪些电商网站
  • 部门网站建设总结鼎城网站建设
  • 制作网站的模板下载大型商城购物平台开发