0

0

5个Dubbo面试题,含金量超高!

Java后端技术全栈

Java后端技术全栈

发布时间:2023-08-17 16:04:16

|

1567人浏览过

|

来源于Java后端技术全栈

转载

猫目
猫目

AI工具导航与智能应用推荐

下载

今天,给大家带来一篇关于dubbo io交互的文章。

本文是一位同事所写,用有趣的文字把枯燥的知识点写出来,通俗易懂,非常有意思,所以迫不及待找作者授权然后分享给大家:


一些有趣的问题

Dubbo是一个优秀的RPC框架,其中有错综复杂的线程模型,本篇文章笔者从自己浅薄的认知中,来剖析Dubbo的整个IO过程。在开始之前,我们先来看如下几个问题:

  • 业务方法执行之后,数据包就发出去了吗?
  • netty3和netty4在线程模型上有什么区别?
  • 数据包到了操作系统socket buffer,经历了什么?
  • Provider打出的log耗时很小,而Consumer端却超时了,怎么可以排查到问题?
  • 数据包在物理层是一根管道就直接发过去吗?
  • Consumer 业务线程await在Condition上,在哪个时机被唤醒?
  • ……

接下来笔者将用Dubbo2.5.3 作为Consumer,2.7.3作为Provider来讲述整个交互过程,笔者站在数据包视角,用第一人称来讲述,系好安全带,我们出发咯。

有意思的旅行

1、Dubbo2.5.3 Consumer端发起请求

我是一个数据包,出生在一个叫Dubbo2.5.3 Consumer的小镇,我的使命是是传递信息,同时也喜欢出门旅行。

某一天,我即将被发送出去,据说是要去一个叫Dubbo 2.7.3 Provider的地方。

这一天,业务线程发起发起方法调用,在FailoverClusterInvoker#doInvoke我选择了一个Provider,然后经过各种Consumer Filter,再经过Netty3的pipeline,最后通过NioWorker#scheduleWriteIfNecessary方法,我来到了NioWorker的writeTaskQueue队列中。

当我回头看主线程时,发现他在DefaultFuture中的Condition等待,我不知道他在等什么,也不知道他要等多久。

我在writeTaskQueue队列排了一会队,看到netty3 IO worker线程在永不停歇的执行run方法,大家都称这个为死循环。

最后,我很幸运,NioWorker#processWriteTaskQueue选择了我,我被写到操作系统的Socket缓冲区,我在缓冲区等待,反正时间充足,我回味一下今天的旅行,期间我辗转了两个旅行团,分别叫主线程和netty3 IO worker线程,嗯,两个旅行团服务都不错,效率很高。

索性我把今天的见闻记录下来,绘制成一张图,当然不重要的地方我就忽略了。

5个Dubbo面试题,含金量超高!

2、操作系统发送数据包

我在操作系统socket缓冲区,经过了很多神奇的事情。

  1. 在一个叫传输层的地方给我追加上了目标端口号、源端口号

  2. 在一个叫网络层的地方给我追加上了目标IP、源IP,同时通过目标IP与掩码做与运算,找到“下一跳”的IP

  3. 在一个叫数据链路层的地方通过ARP协议给我追加上了“下一跳”的目标MAC地址、源MAC地址

最有意思的是,我们坐的都是一段一段缆车,每换一个缆车,就要修改目标MAC地址、源MAC地址,后来问了同行的数据包小伙伴,这个模式叫“下一跳”,一跳一跳的跳过去。这里有很多数据包,体型大的单独一个缆车,体型小的几个挤一个缆车,还有一个可怕的事情,体型再大一点,要分拆做多个缆车(虽然这对我们数据包没啥问题),这个叫拆包和粘包。期间我们经过交换机、路由器,这些地方玩起来很Happy。

当然也有不愉快的事情,就是拥堵,目的地缆车满了,来不及被拉走,只能等待咯。

3、在Provider端的经历

好不容易,我来到了目的地,我坐上了一个叫“零拷贝”号的快艇,迅速到了netty4,netty4果然富丽堂皇,经过NioEventLoop#processSelectedKeys,再经过pipeline中的各种入站handler,我来到了AllChannelHandler的线程池,当然我有很多选择,但是我随便选了一个目的地,这里会经历解码、一系列的Filter,才会来的目的地“业务方法”,NettyCodecAdapter#InternalDecoder解码器很厉害,他可以处理拆包和粘包。

5个Dubbo面试题,含金量超高!

在AllChannelHandler的线程池中我会停留一会,于是我也画了一张图,记录旅程。

5个Dubbo面试题,含金量超高!

自此,我的旅行结束,新的故事将由新的数据包续写。

4、Provider端产生了新的数据包

我是一个数据包,出生在一个叫Dubbo2.7.3 Provider的小镇,我的使命是去唤醒命中注定的线程,接下来我会开始一段旅行,去一个叫Dubbo2.5.3 Consumer的地方。

在Provider业务方法执行之后

  • 由业务线程经过io.netty.channel.AbstractChannelHandlerContext#writeAndFlush
  • 再经过io.netty.util.concurrent.SingleThreadEventExecutor#execute 执行addTask
  • 将任务放入队列io.netty.util.concurrent.SingleThreadEventExecutor#taskQueue
  • 我便跟随着io.netty.channel.AbstractChannelHandlerContext$WriteTask等待NioEventLoop发车,等待的过程中,我记录了走过的脚步。
5个Dubbo面试题,含金量超高!

在这里,我看到NioEventLoop是一个死循环,不停地从任务队列取任务,执行任务AbstractChannelHandlerContext.WriteAndFlushTask,然后指引我们到socket缓冲区等候,永不知疲倦,我似乎领略到他身上有一种倔强的、追求极致的匠人精神。

经过io.netty.channel.AbstractChannel.AbstractUnsafe#write,我到达了操作系统socket缓冲区。在操作系统层面和大多数数据包一样,也是做缆车达到目的地。

5、到达dubbo 2.5.3 Consumer端

到达dubbo 2.5.3 Consumer端,我在操作系统socket缓冲区等了一会,同样是坐了“零拷贝”号快艇,到达了真正的目的地dubbo 2.5.3 Consumer,在这里我发现,NioWorker#run是一个死循环,然后执行NioWorker#processSelectedKeys,通过NioWorker#read方式读出来,我就到达了AllChannelHandler的线程池,这是一个业务线程池。

我在这里等待一会,等任务被调度,我看见com.alibaba.dubbo.remoting.exchange.support.DefaultFuture#doReceived被执行了,同时Condition的signal被执行了。我在远处看到了一个被阻塞线程被唤醒,我似乎明白,因为我的到来,唤醒了一个沉睡的线程,我想这应该是我生命的意义。

至此,我的使命也完成了,本次旅程结束。

总结netty3和netty4的线程模型

我们根据两个数据包的自述,来总结一下netty3和netty4的线程模型。

1、netty3写过程

5个Dubbo面试题,含金量超高!

2、Netty4的读写过程

5个Dubbo面试题,含金量超高!

说明:这里没有netty3的读过程,netty3读过程和netty4相同,pipeline是由IO线程执行。

总结:netty3与netty4线程模型的区别在于写过程,netty3中pipeline由业务线程执行,而netty4无论读写,pipeline统一由IO线程执行。

netty4中ChannelPipeline中的Handler链统一由I/O线程串行调度,无论是读还是写操作,netty3中的write操作时由业务线程处理Handler链。netty4中可以降低线程之间的上下文切换带来的时间消耗,但是netty3中业务线程可以并发执行Handler链。如果有一些耗时的Handler操作会导致netty4的效率低下,但是可以考虑将这些耗时操作放在业务线程最先执行,不放在Handler里处理。由于业务线程可以并发执行,同样也可以提高效率。

一些疑难问题排查

有遇到一些比较典型的疑难问题,例如当Provider答应的didi.log耗时正常,而Consumer端超时了,此时有如下排查方向,didi.log的Filter其实处于非常里层,往往不能反映真实的业务方法执行情况。

  1. Provider除了业务方向执行外,序列化也有可能是耗时的,所以可以用arthas监控最外侧方法org.apache.dubbo.remoting.transport.DecodeHandler#received,排除业务方法耗时高的问题

  2. Provider中数据包写入是否耗时,监控io.netty.channel.AbstractChannelHandlerContext#invokeWrite方法

  3. 通过netstat 也能查看当前tcp socket的一些信息,比如Recv-Q, Send-Q,Recv-Q是已经到了接受缓冲区,但是还没被应用代码读走的数据。Send-Q是已经到了发送缓冲区,但是对方还没有回复Ack的数据。这两种数据正常一般不会堆积,如果堆积了,可能就有问题了。

5个Dubbo面试题,含金量超高!
  1. 看Consumer NioWorker#processSelectedKeys (dubbo2.5.3)方法是否耗时高。

  2. 直到最终整个链路的所有细节……问题肯定是可以解决的。

尾声

在整个交互过程中,笔者省略线程栈调用的一些细节和源代码的细节,例如序列化与反序列化,dubbo怎么读出完整的数据包的,业务方法执行前那些Filter是怎么排序和分布的,netty的Reactor模式是如何实现的。这些都是非常有趣的问题…… 

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

48

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

44

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

37

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

22

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

19

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

3

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

268

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

51

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

430

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号