简介:为什么SOFA RPC调用30s还不超时?

1. 背景

最近帮客户处理了一个诡异的RPC调用问题,想跟大家分享一下。关于SOFA RPC,请参考官网[1]。

2. 问题现象

客户使用 REST 接口触发RPC的调用,发现每次RPC调用都需要30秒的时间,最终的RPC调用结果是成功的。从业务日志来看,开始处理业务和结束业务之间确实花了30秒。

3. 问题分析

RPC 调用花了30秒调用成功,这本身是一件诡异的事情。因为默认SOFA RPC的框架RPC超时时间是3秒。下面的代码显式的设置了超时时间,设置成了默认值。

<sofa:reference jvm-first="false" id="rpcService" interface="com.sofa.rpc.facade.demo.RpcService"><sofa:binding.bolt><sofa:global-attrs timeout="3000" /></sofa:binding.bolt>
</sofa:reference>

我们首先确定了代码中确实没有更改SOFA RPC框架的默认超时时间。所以,理论上RPC调用超过3秒,RPC客户端就应该报错了。
那么,我们来看看这30秒到底发生了什么!

3.1 直击框架核心

我们知道SOFA RPC调用的超时时间是3秒,我们首先需要确认SOFA RPC框架到底花了多少时间。
根据业务日志的时间点(2020-01-21 10:41:34),查看RPC的digest日志: /home/admin/logs/tracelog/rpc-client-digest.log。我们发现RPC执行的时间才54ms。这证明实际上RPC调用是很快的!那么时间到底去哪里了?

2020-01-21 10:42:04.186,xxx_app,0a014046157957449410610155674,0,com.xxx.xxx.service.xxxService:1.0,$genericInvoke,bolt,sync,xxx.xxx.xxx.72:12222,xxx,,,,,00,2296B,889B,54ms,0ms,0ms,54ms,http-nio-8080-exec-10,REGISTRY,,,,xxx.xxx.xxx.72,12222,,,

难道时间花在获得RPC provider 的地址上了?
于是,我们查看RPC客户端的注册中心寻址日志,/home/admin/logs/rpc/rpc-registry.log。我们发现该接口的地址在三秒前就返回了。所以也不是寻址的问题。

2020-01-21 10:41:31,330 INFO  ObserverNotifyThread-2-thread-5  com.alipay.sofa.rpc.registry.dsr.DsrSubscribeCallback - RPC-00204: Receive RPC service addresses: service[com.xxx.xxx.service.xxxService:1.0@DEFAULT]usable target addresses[3]

3.2 怀疑业务代码

基于上述的证据,我们有理由怀疑是业务代码自身的问题。我们要求客户检查业务代码。客户在业务代码中添加了很多日志,显式的打印业务处理和RPC调用时间,结果证明时间还是消失在调用RPC的过程中。以下是客户 SOFA RPC调用的具体代码。

  GenericObject result = (GenericObject)serviceName.$genericInvoke(methodName, argTypes, args);

看到这个结果,我们百思不得其解:RPC的超时时间是3s,但是实际上这次调用花了30s而没有超时(因为实际执行RPC的时间才54ms)。那么,时间到底去哪里了?

3.3 逆向推导

从结果来逆向推导,genericInvoke 应该包含了很多处理方法,而在调用真正的RPC方法之前肯定调用了其他处理方法做了其他事情,那么到底做了什么事情?假如你阅读代码的话,会发现你会被淹没在汪洋代码里面,我们需要其他更有效的方式排查此类问题。
这30秒给人的感觉就是“卡”在了某个地方。这时候,我们需要想,在这种情况下,什么日志或者工具能帮助我们进一步逼近真相?
这时候,jstack登场了。jstack可以帮助我们获得某一个时刻某个进程里面所有线程的调用堆栈。假如某个线程卡在什么方法上的话,通过多抓几次 jstack 的方式,我们能清楚的看到卡住的方法。所以我们让客户在重现问题的时候每隔5s收集一次 jstack $PID >stack.log,至少收集4个日志。$PID需要使用业务应用的java进程ID替换。
皇天不负有心人,从这几个jstack日志中,我们通过genericInvoke 快速定位到相应的线程,发现卡在了OS的方法getLocalHostName上(几个jstack日志都卡在getLocalHostName上)。同时,从调用堆栈来看,线程当时是在初始化RPC的tracer,也就是还没有开始RPC调用,所以不会有RPC调用超时发生。

"http-nio-8080-exec-10" #28 daemon prio=5 os_prio=0 tid=0x00007f54604e5000 nid=0x175c runnable [0x00007f53ef1f6000]java.lang.Thread.State: RUNNABLEat java.net.Inet4AddressImpl.getLocalHostName(Native Method)at java.net.InetAddress.getLocalHost(InetAddress.java:1475)at sun.management.VMManagementImpl.getVmId(VMManagementImpl.java:140)at sun.management.RuntimeImpl.getName(RuntimeImpl.java:59)at com.alipay.common.tracer.core.utils.TracerUtils.getPID(TracerUtils.java:139)at com.alipay.common.tracer.core.generator.TraceIdGenerator.getTraceId(TraceIdGenerator.java:49)at com.alipay.common.tracer.core.generator.TraceIdGenerator.generate(TraceIdGenerator.java:54)at com.alipay.common.tracer.core.SofaTracer$SofaTracerSpanBuilder.createRootSpanContext(SofaTracer.java:296)at com.alipay.common.tracer.core.SofaTracer$SofaTracerSpanBuilder.start(SofaTracer.java:285)at com.alipay.sofa.rpc.tracer.sofatracer.RpcSofaTracer.startRpc(RpcSofaTracer.java:143)at com.alipay.sofa.rpc.tracer.Tracers.startRpc(Tracers.java:102)at com.alipay.sofa.rpc.event.SofaTracerSubscriber.onEvent(SofaTracerSubscriber.java:35)at com.alipay.sofa.rpc.event.EventBus.handleEvent(EventBus.java:153)at com.alipay.sofa.rpc.event.EventBus.post(EventBus.java:123)at com.alipay.sofa.rpc.client.ClientProxyInvoker.invoke(ClientProxyInvoker.java:80)at com.alipay.sofa.rpc.api.GenericService_proxy_0.$genericInvoke(GenericService_proxy_0.java)at com.xxx.xxx.xxx.util.SofaUtil.invokeService(SofaUtil.java:32)at com.xxx.xxx.xxx.controller.xxxxxxxxController.xxxxxxxxController002(xxxxxxxxController.java:425)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)

那么这个getLocalHostName方法到底在干什么呢?通过网络搜索,发现这个函数其实就是去查找本机的HostName,IP。CentOS 查找的顺序是这样的:/etc/hosts 文件,DNS,myhostname(只返回本机配置的公共IP地址)。
由于客户这边DNS配置错误,导致一直卡在该方法DNS超时,所以造成了该问题。同时,经过客户确认,这几台机器并不依赖DNS寻址。
所以我们的解决方案很简单:在 /etc/hosts 中添加了IP与主机名的映射。

参考文档

[1]SOFA RPC:https://help.aliyun.com/document_detail/149865.html?spm=a2c4g.11186623.6.560.178c5fb01GxG9Z

我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

原文链接:https://developer.aliyun.com/article/783846?

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

为什么SOFA RPC调用30s还不超时?相关推荐

  1. 深入剖析通信层和RPC调用的异步化(上)

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析通信层和 RPC 调用的异步化.李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的 ...

  2. rpc 调用webservice怎样传递参数_五分钟让你了解RPC原理详解

    欢迎关注专栏[以架构赢天下]--每天持续分享Java相关知识点 以架构赢天下​zhuanlan.zhihu.com 以架构赢天下--持续分享Java相关知识点 每篇文章首发此专栏 欢迎各路Java程序 ...

  3. SOFA RPC 详细介绍

    简介   SOFA 作为蚂蚁金服自主研发的分布式的系统中间件,包含金融级云原生的架构所需要的各种组件,其中包括微服务的研发框架.RPC调用框架.服务的注册中心.分布式定时任务.限流/熔断机制.动态配置 ...

  4. python rpc调用_从0到1:全面理解 RPC 远程调用

    上一篇关于 WSGI 的硬核长文,不知道有多少同学,能够从头看到尾的,不管你们有没有看得很过瘾,反正我是写得很爽,总有一种将一样知识吃透了的错觉. 今天我又给自己挖坑了,打算将 rpc 远程调用的知识 ...

  5. 开发中的坑:MQ 也能做 RPC 调用?

    hi, 大家好,我是 haohongfan. 最近浏览 帖子[1] 的时候看到一个有意思的吐槽. 大概意思是架构师没有选用 RPC 框架来做服务间调用,而选择用 MQ 来代替.是不是很意外? 当然不出 ...

  6. php rpc调用,PHP 通过 JSON-RPC 调用实现以太坊交互

    PHP 通过 JSON-RPC 调用实现以太坊交互 由 hubwiz 创建于2年前, 最后更新于 2年前 版本号 #1 6262 views 0 likes 0 collects 自去年以来,我们正在 ...

  7. 调用lambda_如何使用Lambda调用上下文动态设置超时

    调用lambda by Yan Cui 崔燕 如何使用Lambda调用上下文动态设置超时 (How to set timeouts dynamically using Lambda invocatio ...

  8. 怎么看调用的接口_Hadoop RPC调用实例分析

    以ClientProtocol接口中的rename RPC调用进行一次实例分析. rename方法在ClientProtocol接口中定义,它的两个参数是String类型的,不能直接通过网络传输. 我 ...

  9. 趣说技术 | 用MQ 能完全替代 RPC 调用?

    最近浏览 帖子[1] 的时候看到一个有意思的吐槽. 图片 大概意思是架构师没有选用 RPC 框架来做服务间调用,而选择用 MQ 来代替.是不是很意外? 当然不出意外的,评论区炸了! 图片 现在提出一些 ...

最新文章

  1. Php传图缩图,使用以下用于上传图像的PHP代码上传时缩小图像大小
  2. 方舟 game.ini 配置文件_方舟突然回归|这次居然是住院篇!
  3. 科大星云诗社动态20210228
  4. nginx日志切割并使用flume-ng收集日志
  5. PID算法搞不懂?看这篇文章就够了。
  6. leetcode1423. 可获得的最大点数
  7. 同事说他的应用起不来了,因为我的代码里面多了一个空格!
  8. Java程序员是如何面试上阿里巴巴,如何拿到年薪50W
  9. 在水晶报表中插入子报表,并动态添加数据源
  10. 优化CUDA数据传输
  11. codeforces 1728E
  12. 视频教程-微信公众号实战(Java版本,带前后台)-微信开发
  13. Java Web 实现文件多线程分片下载方案
  14. #入坑keychron#火爆的keychron机械键盘,你还没有入手?【重点:附键盘选购建议】
  15. 【Web】分页简单实现
  16. 非磺化花菁和磺化花菁有机染料Cyanine dyes的说明应用
  17. 多校训练1 A Alice and Bob 博弈
  18. Python 基礎 - 文件操作_v2
  19. 刘大拿python_零基础Python知识点回顾(一)
  20. 爬虫学习(03): 数据解析_re篇

热门文章

  1. 还在对Matplotlib繁琐的图层设置感到烦恼!?快来看看这个Python绘图工具包吧
  2. 炫酷!用Python制作漂亮的流动桑基图
  3. 今年数据分析到底有多火?全网跪求优质资源!
  4. java executebatch_JDBC批量执行executeBatch
  5. android 自定义频谱,android – 如何从实时音频开发频谱分析仪?
  6. 机器学习-k均值聚类算法-k_means原理14
  7. python applymap_运行Python Applymap需要时间
  8. linux期末脚本作业,linux – 使用R Markdown将bash脚本作为Cron作业运行
  9. 【案例分享】crontab执行脚本异常问题
  10. matlab 非线性曲线拟合