记录一次reactive模型接口问题

表现

生产环境一百多台机器,某接口全面返回http错误码590。

接口相关的业务功能不可用,且不能自己恢复,后紧急下线相关功能配置,重启后恢复。

Bug引入

微服务使用netty的reactive模式进行开发,请求返回体为completableFuture<XXResponse>。

接口处理函数中,新建一个completableFucture,作为返回值。

completableFuture中有代码实现判空不到位,导致抛空指针异常,导致无法走到complete(XXResponse)执行。

从外部看,比如使用postman调用的时候,表现为接口一直阻塞,不响应。

定位过程

尝试在本地环境复现:

1)使用postman runner模拟高频请求。

postman runner本身是不支持并发请求的。

有个小技巧,可以通过修改postman setting里的超时时间,不用上一个等返回就发起下一个。

2)jvisualVM查看内存使用,对内存和线程进行dump。

发现内存并没有明显泄漏。看各个线程池也没发现有特别异常的。

相关知识点:

1)Netty的reactive请求处理模型

https://servicecomb.apache.org/references/java-chassis/zh_CN/general-development/reactive.htmlJava CompletableFuture 详解https://servicecomb.apache.org/references/java-chassis/zh_CN/general-development/reactive.html

请求网络数据到达后,请求会写到channel中,这个过程很快。

进入eventloop1的处理:

vertex线程池对eventloop select到的已经就绪的请求进行处理。这个过程包括:走比如熔断、限流等过滤器,再走到业务代码。

进入异步线程池的处理:

业务代码创建comletableFuture,在线程池中异步执行,在异步线程中通过complete带回结果,主线程直接返回future。

此时注册到另一个eventloop中,当响应完成时会在这里就绪,另一个线程会select到就绪的返回结果,再写回连接数据。

vert.x线程不能阻塞。业务异步线程要保证complete效率,否则会导致被调堆积。

如果在业务线程中涉及IO,调用其他的微服务,也使用响应式编程,返回一个future,就释放当前线程到下一个任务。通过eventloop去获取调用返回。

nio的核心思想就是去除因为io阻塞的线程,转换为多路复用,这个有点像操作系统的io中断、中断响应,搞过嵌入式开发的同学应该很熟悉。

实际上当接口中会调用其他接口的时候,使用响应式编程可以将这些一断一断串起来,最大化效率

2)接口熔断

底层还是hystrix,hystrix隔离模式目前有两种方式:信号量模式和线程池模式。

reactive模型下,hystrix通常使用信号量模型。信号量并不支持超时, 早先的一批请求可能长时间无法得到响应。

hystrix两种隔离模式分析 - 指针怒草内存栈 - 博客园

Hystrix 信号量机制实现资源隔离_littleAusna的博客-CSDN博客_hystrix信号量隔离

原因分析

1)线程中抛异常后,未在线程内catch,而是在线程外catch,导致没有给future返回值。

2)Netty的reactive请求处理模型下,无返回值的future会维持在NioEventLoop中。

3)hystrix的信号量不是否,触发了hystrix的隔离机制,导致快速失败返回590。

待确认:

是否future不返回会导致内存泄漏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值