Linux 网络性能的 15 个优化建议!

8c00d14226c06584c35f0ecba001c420.gif

作者 | 张彦飞allen

来源 | 开发内功修炼

那么具备了对网络的深刻的理解之后,我们在性能方面有哪些优化手段可用呢?我这里给出一些开发或者运维中的性能优化建议。这些建议都是从书中摘录的。不过要注意的是,每一种性能优化方法都有它适用或者不适用的应用场景。你应当根据你当前的项目现状灵活来选择用或者不用。

建议1:尽量减少不必要的网络 IO

我要给出的第一个建议就是不必要用网络 IO 的尽量不用。

是的,网络在现代的互联网世界里承载了很重要的角色。用户通过网络请求线上服务、服务器通过网络读取数据库中数据,通过网络构建能力无比强大分布式系统。网络很好,能降低模块的开发难度,也能用它搭建出更强大的系统。但是这不是你滥用它的理由!

原因是即使是本机网络 IO 开销仍然是很大的。先说发送一个网络包,首先得从用户态切换到内核态,花费一次系统调用的开销。进入到内核以后,又得经过冗长的协议栈,这会花费不少的 CPU 周期,最后进入环回设备的“驱动程序”。接收端呢,软中断花费不少的 CPU 周期又得经过接收协议栈的处理,最后唤醒或者通知用户进程来处理。当服务端处理完以后,还得把结果再发过来。又得来这么一遍,最后你的进程才能收到结果。你说麻烦不麻烦。另外还有个问题就是多个进程协作来完成一项工作就必然会引入更多的进程上下文切换开销,这些开销从开发视角来看,做的其实都是无用功。

上面我们还分析的只是本机网络 IO,如果是跨机器的还得会有双方网卡的 DMA 拷贝过程,以及两端之间的网络 RTT 耗时延迟。所以,网络虽好,但也不能随意滥用!

建议2:尽量合并网络请求

在可能的情况下,尽可能地把多次的网络请求合并到一次,这样既节约了双端的 CPU 开销,也能降低多次 RTT 导致的耗时。

我们举个实践中的例子可能更好理解。假如有一个 redis,里面存了每一个 App 的信息(应用名、包名、版本、截图等等)。你现在需要根据用户安装应用列表来查询数据库中有哪些应用比用户的版本更新,如果有则提醒用户更新。

那么最好不要写出如下的代码:

<?php 
for(安装列表 as 包名){redis->get(包名)...
}

上面这段代码功能上实现上没问题,问题在于性能。据我们统计现代用户平均安装 App 的数量在 60 个左右。那这段代码在运行的时候,每当用户来请求一次,你的服务器就需要和 redis 进行 60 次网络请求。总耗时最少是 60 个 RTT 起。更好的方法是应该使用 redis 中提供的批量获取命令,如 hmget、pipeline等,经过一次网络 IO 就获取到所有想要的数据,如图。

08cc69dc6db2b4a6dd4bc5d22a5a77ae.png

建议3:调用者与被调用机器尽可能部署的近一些

在前面的章节中我们看到在握手一切正常的情况下, TCP 握手的时间基本取决于两台机器之间的 RTT 耗时。虽然我们没办法彻底去掉这个耗时,但是我们却有办法把 RTT 降低,那就是把客户端和服务器放的足够的近一些。尽量把每个机房内部的数据请求都在本地机房解决,减少跨地网络传输。

举例,假如你的服务是部署在北京机房的,你调用的 mysql、redis最好都位于北京机房内部。尽量不要跨过千里万里跑到广东机房去请求数据,即使你有专线,耗时也会大大增加!在机房内部的服务器之间的 RTT 延迟大概只有零点几毫秒,同地区的不同机房之间大约是 1 ms 多一些。但如果从北京跨到广东的话,延迟将是 30 - 40 ms 左右,几十倍的上涨!

建议4:内网调用不要用外网域名

假如说你所在负责的服务需要调用兄弟部门的一个搜索接口,假设接口是:"http://www.sogou.com/wq?key=开发内功修炼"。

那既然是兄弟部门,那很可能这个接口和你的服务是部署在一个机房的。即使没有部署在一个机房,一般也是有专线可达的。所以不要直接请求 www.sogou.com, 而是应该使用该服务在公司对应的内网域名。在我们公司内部,每一个外网服务都会配置一个对应的内网域名,我相信你们公司也有。

为什么要这么做,原因有以下几点

1)外网接口慢。本来内网可能过个交换机就能达到兄弟部门的机器,非得上外网兜一圈再回来,时间上肯定会慢。

2)带宽成本高。在互联网服务里,除了机器以外,另外一块很大的成本就是 IDC 机房的出入口带宽成本。两台机器在内网不管如何通信都不涉及到带宽的计算。但是一旦你去外网兜了一圈回来,行了,一进一出全部要缴带宽费,你说亏不亏!!

3)NAT 单点瓶颈。一般的服务器都没有外网 IP,所以要想请求外网的资源,必须要经过 NAT 服务器。但是一个公司的机房里几千台服务器中,承担 NAT 角色的可能就那么几台。它很容易成为瓶颈。我们的业务就遇到过好几次 NAT 故障导致外网请求失败的情形。NAT 机器挂了,你的服务可能也就挂了,故障率大大增加。

建议5:调整网卡 RingBuffer 大小

在 Linux 的整个网络栈中,RingBuffer 起到一个任务的收发中转站的角色。对于接收过程来讲,网卡负责往 RingBuffer 中写入收到的数据帧,ksoftirqd 内核线程负责从中取走处理。只要 ksoftirqd 线程工作的足够快,RingBuffer 这个中转站就不会出现问题。

但是我们设想一下,假如某一时刻,瞬间来了特别多的包,而 ksoftirqd 处理不过来了,会发生什么?这时 RingBuffer 可能瞬间就被填满了,后面再来的包网卡直接就会丢弃,不做任何处理!

5a1bfced294afabce13a3834222af8e6.png

通过 ethtool 就可以加大 RingBuffer 这个“中转仓库”的大小。。

# ethtool -G eth1 rx 4096 tx 4096

f85070dacbf796d57631e7691ba629f6.png

这样网卡会被分配更大一点的”中转站“,可以解决偶发的瞬时的丢包。不过这种方法有个小副作用,那就是排队的包过多会增加处理网络包的延时。所以应该让内核处理网络包的速度更快一些更好,而不是让网络包傻傻地在 RingBuffer 中排队。我们后面会再介绍到 RSS ,它可以让更多的核来参与网络包接收。

建议6:减少内存拷贝

假如你要发送一个文件给另外一台机器上,那么比较基础的做法是先调用 read 把文件读出来,再调用 send 把数据把数据发出去。这样数据需要频繁地在内核态内存和用户态内存之间拷贝,如图 9.6。

43db0c6c5bd8ab43db739c4237ad5f42.png

目前减少内存拷贝主要有两种方法,分别是使用 mmap 和 sendfile 两个系统调用。使用 mmap 系统调用的话,映射进来的这段地址空间的内存在用户态和内核态都是可以使用的。如果你发送数据是发的是 mmap 映射进来的数据,则内核直接就可以从地址空间中读取,这样就节约了一次从内核态到用户态的拷贝过程。

a079ee176b83206aa979ed0e7ecc218f.png

不过在 mmap 发送文件的方式里,系统调用的开销并没有减少,还是发生两次内核态和用户态的上下文切换。如果你只是想把一个文件发送出去,而不关心它的内容,则可以调用另外一个做的更极致的系统调用 - sendfile。在这个系统调用里,彻底把读文件和发送文件给合并起来了,系统调用的开销又省了一次。再配合绝大多数网卡都支持的"分散-收集"(Scatter-gather)DMA 功能。可以直接从 PageCache 缓存区中 DMA 拷贝到网卡中。这样绝大部分的 CPU 拷贝操作就都省去了。

7ed0afdd40af91cc8e0c59e42510ad3d.png

建议7:使用 eBPF 绕开协议栈的本机 IO

如果你的业务中涉及到大量的本机网络 IO 可以考虑这个优化方案。本机网络 IO 和跨机 IO 比较起来,确实是节约了驱动上的一些开销。发送数据不需要进 RingBuffer 的驱动队列,直接把 skb 传给接收协议栈(经过软中断)。但是在内核其它组件上,可是一点都没少,系统调用、协议栈(传输层、网络层等)、设备子系统整个走 了一个遍。连“驱动”程序都走了(虽然对于回环设备来说这个驱动只是一个纯软件的虚拟出来的东东)。

如果想用本机网络 IO,但是又不想频繁地在协议栈中绕来绕去。那么你可以试试 eBPF。使用 eBPF 的 sockmap 和 sk redirect 可以绕过 TCP/IP 协议栈,而被直接发送给接收端的 socket,业界已经有公司在这么做了。

cb577bfb11a7b67c109de7a0c7f06084.png

建议8:尽量少用 recvfrom 等进程阻塞的方式

在使用了 recvfrom 阻塞方式来接收 socket 上数据的时候。每次一个进程专⻔为了等一个 socket 上的数据就得被从 CPU 上拿下来。然后再换上另一个 进程。等到数据 ready 了,睡眠的进程又会被唤醒。总共两次进程上下文切换开销。如果我们服务器上需要有大量的用户请求需要处理,那就需要有很多的进程存在,而且不停地切换来切换去。这样的缺点有如下这么几个:

  • 因为每个进程只能同时等待一条连接,所以需要大量的进程。

  • 进程之间互相切换的时候需要消耗很多 CPU 周期,一次切换大约是 3 - 5 us 左右。

  • 频繁的切换导致 L1、L2、L3 等高速缓存的效果大打折扣

大家可能以为这种网络 IO 模型很少见了。但其实在很多传统的客户端 SDK 中,比如 mysql、redis 和 kafka 仍然是沿用了这种方式。

建议9:使用成熟的网络库

使用 epoll 可以高效地管理海量的 socket。在服务器端。我们有各种成熟的网络库进行使用。这些网络库都对 epoll 使用了不同程度的封装。

首先第一个要给大家参考的是 Redis。老版本的 Redis 里单进程高效地使用 epoll 就能支持每秒数万 QPS 的高性能。如果你的服务是单进程的,可以参考 Redis 在网络 IO 这块的源码。

如果是多线程的,线程之间的分工有很多种模式。那么哪个线程负责等待读 IO 事件,哪个线程负责处理用户请求,哪个线程又负责给用户写返回。根据分工的不同,又衍生出单 Reactor、多 Reactor、以及 Proactor 等多种模式。大家也不必头疼,只要理解了这些原理之后选择一个性能不错的网络库就可以了。比如 PHP 中的 Swoole、Golang 的 net 包、Java 中的 netty 、C++ 中的  Sogou Workflow 都封装的非常的不错。

建议10:使用 Kernel-ByPass 新技术

如果你的服务对网络要求确实特别特特别的高,而且各种优化措施也都用过了,那么现在还有终极优化大招 -- Kernel-ByPass 技术。

内核在接收网络包的时候要经过很⻓的收发路径。在这期间牵涉到很多内核组件之间的协同、协议栈的处理、以及内核态和用户态的拷贝和切换。Kernel-ByPass 这类的技术方案就是绕开内核协议栈,自己在用户态来实现网络包的收发。这样不但避开了繁杂的内核协议栈处理,也减少了频繁了内核态用户态之间的拷贝和切换,性能将发挥到极致!

目前我所知道的方案有 SOLARFLARE 的软硬件方案、DPDK 等等。如果大家感兴趣,可以多去了解一下!

8f6c5249fa9a2165d3fcd4cf78c69897.png

建议11:配置充足的端口范围

客户端在调用 connect 系统调用发起连接的时候,需要先选择一个可用的端口。内核在选用端口的时候,是采用从可用端口范围中某一个随机位置开始遍历的方式。如果端口不充足的话,内核可能需要循环撞很多次才能选上一个可用的。这也会导致花费更多的 CPU 周期在内部的哈希表查找以及可能的自旋锁等待上。因此不要等到端口用尽报错了才开始加大端口范围,而且应该一开始的时候就保持一个比较充足的值。

# vi /etc/sysctl.conf
net.ipv4.ip_local_port_range = 5000 65000
# sysctl -p  //使配置生效

如果端口加大了仍然不够用,那么可以考虑开启端口 reuse 和 recycle。这样端口在连接断开的时候就不需要等待 2MSL 的时间了,可以快速回收。开启这个参数之前需要保证 tcp_timestamps 是开启的。

# vi /etc/sysctl.conf
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tw_recycle = 1
# sysctl -p

建议12:小心连接队列溢出

服务器端使用了两个连接队列来响应来自客户端的握手请求。这两个队列的长度是在服务器 listen 的时候就确定好了的。如果发生溢出,很可能会丢包。所以如果你的业务使用的是短连接且流量比较大,那么一定得学会观察这两个队列是否存在溢出的情况。因为一旦出现因为连接队列导致的握手问题,那么 TCP 连接耗时都是秒级以上了。

对于半连接队列, 有个简单的办法。那就是只要保证 tcp_syncookies 这个内核参数是 1 就能保证不会有因为半连接队列满而发生的丢包。

对于全连接队列来说,可以通过 netstat -s 来观察。netstat -s 可查看到当前系统全连接队列满导致的丢包统计。但该数字记录的是总丢包数,所以你需要再借助 watch 命令动态监控。

# watch 'netstat -s | grep overflowed' 
160 times the listen queue of a socket overflowed //全连接队列满导致的丢包

如果输出的数字在你监控的过程中变了,那说明当前服务器有因为全连接队列满而产生的丢包。你就需要加大你的全连接队列的⻓度了。全连接队列是应用程序调用 listen时传入的 backlog 以及内核参数 net.core.somaxconn 二者之中较小的那个。如果需要加大,可能两个参数都需要改。

如果你手头并没有服务器的权限,只是发现自己的客户端机连接某个 server 出现耗时长,想定位一下是否是因为握手队列的问题。那也有间接的办法,可以 tcpdump 抓包查看是否有 SYN 的 TCP Retransmission。如果有偶发的 TCP Retransmission, 那就说明对应的服务端连接队列可能有问题了。

建议13:减少握手重试

在 6.5 节我们看到如果握手发生异常,客户端或者服务端就会启动超时重传机制。这个超时重试的时间间隔是翻倍地增长的,1 秒、3 秒、7 秒、15 秒、31 秒、63 秒 ......。对于我们提供给用户直接访问的接口来说,重试第一次耗时 1 秒多已经是严重影响用户体验了。如果重试到第三次以后,很有可能某一个环节已经报错返回 504 了。所以在这种应用场景下,维护这么多的超时次数其实没有任何意义。倒不如把他们设置的小一些,尽早放弃。其中客户端的 syn 重传次数由 tcp_syn_retries 控制,服务器半连接队列中的超时次数是由 tcp_synack_retries 来控制。把它们两个调成你想要的值。

建议14:如果请求频繁,请弃用短连接改用长连接

如果你的服务器频繁请求某个 server,比如 redis 缓存。和建议 1 比起来,一个更好一点的方法是使用长连接。这样的好处有

1)节约了握手开销。短连接中每次请求都需要服务和缓存之间进行握手,这样每次都得让用户多等一个握手的时间开销。

2)规避了队列满的问题。前面我们看到当全连接或者半连接队列溢出的时候,服务器直接丢包。而客户端呢并不知情,所以傻傻地等 3 秒才会重试。要知道 tcp 本身并不是专门为互联网服务设计的。这个 3 秒的超时对于互联网用户的体验影响是致命的。

3)端口数不容易出问题。端连接中,在释放连接的时候,客户端使用的端口需要进入 TIME_WAIT 状态,等待 2 MSL的时间才能释放。所以如果连接频繁,端口数量很容易不够用。而长连接就固定使用那么几十上百个端口就够用了。

建议15:TIME_WAIT 的优化

很多线上服务如果使用了短连接的情况下,就会出现大量的 TIME_WAIT。

首先,我想说的是没有必要见到两三万个 TIME_WAIT 就恐慌的不行。从内存的⻆度来考虑,一条 TIME_WAIT 状态的连接仅仅是 0.5 KB 的内存而已。从端口占用的角度来说,确实是消耗掉了一个端口。但假如你下次再连接的是不同的 Server 的话,该端口仍然可以使用。只有在所有 TIME_WAIT 都聚集在和一个 Server 的连接上的时候才会有问题。

那怎么解决呢? 其实办法有很多。第一个办法是按上面建议开启端口 reuse 和 recycle。 第二个办法是限制 TIME_WAIT 状态的连接的最大数量。

# vi /etc/sysctl.conf
net.ipv4.tcp_max_tw_buckets = 32768
# sysctl -p

如果再彻底一些,也可以干脆直接用⻓连接代替频繁的短连接。连接频率大大降低以后,自然也就没有 TIME_WAIT 的问题了。

ffb8020479323592ef2817c0773ca6fa.gif

往期推荐

read 文件一个字节实际会发生多大的磁盘IO?

如何优雅保护 Kubernetes 中的 Secrets

Redis 内存满了怎么办?这样置才正确!

云原生的本手、妙手和俗手

39cda6b0887b72df95630e83b1aaa6f1.gif

点分享

c487c8cb869e38813009b968d049dc35.gif

点收藏

346be1a7179972b9fa4bf79d30486d11.gif

点点赞

4e37d3d38eadb985e7481f34f240b9d1.gif

点在看

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

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

相关文章

Flink Sort-Shuffle 实现简介

简介&#xff1a;Sort-Shuffle 使 Flink 在应对大规模批数据处理任务时更加游刃有余 本文介绍 Sort-Shuffle 如何帮助 Flink 在应对大规模批数据处理任务时更加游刃有余。主要内容包括&#xff1a; 数据 Shuffle 简介引入 Sort-Shuffle 的意义Flink Sort-Shuffle 实现测试结果调…

「现代C++设计魅力」虚函数继承-thunk技术初探

简介&#xff1a;工作中使用LLDB调试器调试这一段C多继承程序的时候&#xff0c;发现通过lldb print(expression命令的别名) 命令获取的指针地址和实际理解的C的内存模型的地址不一样。那么到底是什么原因呢&#xff1f; 作者 | 扬阜 来源 | 阿里技术公众号 一 问题背景 1 实…

万物互联时代到来,锐捷发布场景化无线零漫游方案

数字化和万物互联时代到来&#xff0c;物联网与 IoT 设备发展迅猛&#xff0c;以往只在办公区域主要由手机等移动设备使用的无线网络&#xff0c;正在接入更多核心业务生产、物流仓储等各类的生产设备。据分析机构 IDC 预测&#xff0c;无线网络优先是当下智能园区网络建设投资…

阿里云田涛涛:高效智能的云,CloudOps让运维更简单

简介&#xff1a;CloudOps:以应用为中心的自动化运维新趋势 12月21日&#xff0c;在阿里云弹性计算年度峰会上&#xff0c;阿里云弹性计算体验与控制系统负责人田涛涛发表了主题为《高效智能的云&#xff0c;CloudOps让运维更简单》的演讲&#xff0c;深度解读了云上运维新趋势…

打造南沙“强芯”,南沙首届IC Nansha大会召开

6月25日&#xff0c;2022 中国南沙国际集成电路产业论坛在广州南沙召开。本次峰会由广州南沙经济技术开发区管理委员会、广州市工业和信息化局主办&#xff1b;支持单位为广州湾区半导体产业集团有限公司、广东省集成电路行业协会、广州市半导体协会&#xff1b;广东省半导体及…

OpenAI开发者大会简介

文章目录 GPT-4 Turbo 昨天晚上 OpenAI的首届开发者大会召开 Sam Altman也做了公开演讲&#xff0c;应该说 这是继今年春天发布GPT-4之后 OpenAI在AI行业又创造的一个不眠夜 过去一年 ChatGPT绝对是整个科技领域最热的词汇 OpenAI 也依靠ChatGPT取得了惊人的成绩 ChatG…

阿里云贾少天:大规模云服务器高效使用及管理实践

简介&#xff1a;本篇内容分享了大规模云服务器高效使用及管理最佳实践。 2021年10月22日&#xff0c;在云栖大会的《云上运维最佳实践》分论坛&#xff0c;阿里云高级技术专家贾少天发表了主题为“大规模云服务器高效使用及管理最佳实践”的演讲&#xff0c;本篇内容根据他的…

发现新视界——视觉计算将如何改变生产方式

简介&#xff1a;本篇内容将从3个部分为读者介绍关于视觉计算如何改变生产方式&#xff0c;进一步阐述可视化业务方面的挑战及阿里云视觉计算的解决方案与优势。 编者按&#xff1a;在2021年10月举办的云栖大会的《数字孪生&Cloud XR技术助力产研创新论坛》上&#xff0c;…

容器监控指南:三剑客轻松实现 Docker 容器监控

作者 | Milan Mahat在本指南中&#xff0c;我们将学习如何使用 docker-compose 在容器中设置 cAdvisor&#xff0c;将其与 prometheus 连接&#xff0c;并通过 grafana 监控服务器的容器。CAdvisor 是一种流行的工具&#xff0c;用于收集容器的信息。它是 prometheus 和 grafan…

N个技巧,编写更高效 Dockerfile|云效工程师指北

简介&#xff1a;云原生时代下软件的构建和部署离不开容器技术。提到容器&#xff0c;几乎大家下意识都会联想到 Docker 。而 Docker 中有两个非常重要的概念&#xff0c;一个是Image&#xff08;镜像&#xff09;&#xff0c;一个是Container&#xff08;容器&#xff09;。前…

TDA-04D8变送器数据上报阿里云

简介&#xff1a;本文将以TDA-04D8变送器作为采集对象&#xff0c;使用海创微联采集控制系统对TDA-04D8变送器进行采集&#xff0c;然后将设备上的毛重、净重、皮重数据采集上传到阿里云物联网平台&#xff0c;阿里云物联网平台将数据实时可视化。 文章分为3部分&#xff1a; …

http ,怎么优雅的拒绝你

作者 | 奇伢来源 | 奇伢云存储典型问题&#xff1a;服务端优雅的拒绝今天分享一个后端编程的实际经验。这个问题来源于对象 S3 后端协议实现的技巧思考。场景&#xff1a;服务端不想接收 http 的 body 的时候&#xff0c;该怎么优雅的拒绝呢&#xff1f;什么意思&#xff1f;对…

企业物联网平台新版公共实例升级企业实例教程

简介&#xff1a;2021年7月30日企业物联网平台重磅升级&#xff0c;发布的新版公共实例支持一键升级企业版实例&#xff0c;本文将为大家介绍一键升级教程 一、企业版实例&#xff0c;企业用户首选 企业物联网平台 提供设备上云必备的基础服务&#xff0c;用户无需自建物联网…

【全观测系列】Elasticsearch应用性能监控实践

简介&#xff1a;本文介绍了应用性能监控的应用价值以及解决方案等。 1、什么是全观测&#xff1f; 要了解全观测&#xff0c;我们先看看传统运维存在哪些问题。 数据孤岛&#xff0c;分散在不同部门&#xff0c;分析排查故障困难&#xff1b;多个厂商的多种工具&#xff0c…

es实战-使用IK分词器进行词频统计

简介&#xff1a;通过IK分词器分词并生成词云。 本文主要介绍如何通过 IK 分词器进行词频统计。使用分词器对文章的词频进行统计&#xff0c;主要目的是实现如下图所示的词云功能&#xff0c;可以找到文章内的重点词汇。后续也可以对词进行词性标注&#xff0c;实体识别以及对…

IC Nansha|AMD高级副总裁、大中华区总裁潘晓明:制程、架构、平台优化突破计算边界

6月25日&#xff0c;中国南沙国际集成电路产业论坛在广州南沙顺利举行。AMD高级副总裁、大中华区总裁潘晓明出席了本次会议&#xff0c;并在高峰论坛环节中以《高性能计算的未来》为主题发表了演讲。 &#xff08;AMD高级副总裁、大中华区总裁 潘晓明&#xff09; 作为一家深耕…

爱数SMART 2022峰会开启,分享数据战略与建设数据驱动型组织方法论

6月28日&#xff0c;爱数SMART 2022线上峰会全球直播正式开启。主论坛上&#xff0c;爱数正式提出了企业制定数据战略以及建设数据驱动型组织的方法论&#xff0c;并推出开源计划与数字伙伴计划2.0&#xff0c;共创数据驱动型组织。 通过清晰的数据战略&#xff0c;从容加速数据…

云原生时代开发者工具变革探索与实践

简介&#xff1a;本篇内容分享了原生时代开发者工具变革探索与实践。 分享人&#xff1a;马洪喜 行云创新CEO 正文&#xff1a;本篇内容将通过三个部分来介绍云原生时代开发者工具变革探索与实践。 一、云原生模块化开发概览 二、软件模块化开发特点 三、ADD产品简介 一、…

喜马拉雅 Apache RocketMQ 消息治理实践

简介&#xff1a;本文通过喜马拉雅的RocketMQ治理实践分享&#xff0c;让大家了解使用消息中间件过程中可能遇到的问题&#xff0c;避免实战中踩坑。 作者&#xff1a;曹融&#xff0c;来自喜马拉雅&#xff0c;从事微服务和消息相关中间件开发。 本文通过喜马拉雅的RocketMQ治…

Docker 容器为什么傲娇?全靠镜像撑腰!

作者 | 飞向星的客机来源 | CSDN博客&#x1f31f; 前言Docker 镜像是 Docker 容器的基石&#xff0c;容器是镜像的运行实例&#xff0c;有了镜像才能启动容器。Docker 镜像是一个只读的模板&#xff0c;一个独立的文件系统&#xff0c;包括运行一个容器所需的数据&#xff0c;…