下单接口里那行发邮件的代码,把24毫秒的响应拖成了924毫秒

下单接口里那行发邮件的代码,把24毫秒的响应拖成了924毫秒
张文保 更新 26 分钟阅读 2,369 阅读
本文目录
  1. 为什么第一步是量时间,而不是选型?
  2. 一个第三方调用会往响应里加多少毫秒?
  3. 串行、并行、挪走,三条路差多少?
  4. 不上队列,还有哪两条退路?
  5. 退路一:定时任务轮询
  6. 退路二:数据库表当队列
  7. 退路三:真正的队列组件
  8. 为什么换存储只快10倍,换调用方式却快29倍?
  9. 什么样的任务才真该进队列?
  10. 任务本身多快,队列就不划算了?
  11. 消息里到底该放什么?
  12. 上了队列之后会多出哪些新麻烦?
  13. 队列长度这个数,为什么单看没用?
  14. 消费者怎么等下一条,差别有多大?
  15. 怎么分三步走,而不是一步到位?
  16. 第一阶段那张任务表该有哪几列?
  17. 这套判断在独立站上怎么落地?
  18. 怎么把藏在请求路径里的调用找出来?
  19. 常见问题解答
  20. 权威参考资料
摘要:下单成功后给用户发一封确认邮件,这行代码放在哪里,决定了用户要等多久。保哥在自己那台服务器上把这件事量了一遍:本站响应的首字节中位数是23.9毫秒,而一次真实的第三方接口调用中位数落在437到900毫秒之间,还有一个境外接口整整15秒才超时返回。把它内联进请求路径,响应时间会变成原来的19倍到629倍。同一轮实测里还撞出一个反直觉的结论:把存储从数据库换成内存库,吞吐只提升了10倍;而把逐条调用换成批量调用,同一个存储上提升了29倍。换句话说,决定快慢的主要不是你用什么存,是你往返几次。本文给出的不是队列教程,是一张判据表——什么时候还不需要队列,以及三个替代方案各自能撑到哪一步。

先说清楚这篇要解决的问题。市面上讲消息队列的文章,绝大多数从生产者、代理、消费者这三个名词讲起,然后接一张选型对比表。这些内容不能说没用,但它们默认了一个前提——你已经决定要上队列了。

真实情况往往相反。一个日均几百单的独立站,后台跑着几个定时脚本,突然有人说这里应该上个队列,团队里没人能说清为什么。于是要么硬上,多了一个会挂的组件;要么一直不上,把用户晾在那里等第三方接口。

所以保哥决定先不谈方案,先量数字。下面这些数据全部来自本站那台单机,不是从别处抄来的基准测试,跑的时候站点正常对外服务。

为什么第一步是量时间,而不是选型?

那台机器上跑着这个站,热态下的响应很稳。用命令行连打5次,首字节分别是23.8、23.9、23.9、24.0毫秒——四次几乎完全一致。

第5次是486.8毫秒。

这个数字本身就值得停一下:同一个地址、同一分钟、同一台机器,最慢的一次是最快的20.5倍。所以后面所有的对照,保哥都取中位数而不是平均值,平均值会被这种偶发尖刺抬得面目全非。这个坑在服务器负载排查那篇里也踩过,一次异常能把平均值抬高好几倍。

基线定下来了:23.9毫秒。现在往里面塞一个外部依赖。

一个第三方调用会往响应里加多少毫秒?

保哥挑了5个真实端点,每个连打5次,取最快、中位、最慢三个值。全部是从那台服务器上发出去的,不是本地网络:

被调用的对象最快中位最慢返回码
某代码托管平台的接口296.5436.8981.4403
某CDN厂商官网642.3721.9918.9200
某接口调试服务876.6899.71082.2503
某搜索引擎首页15000.515001.115001.20
本站自己(对照组)24.124.4681.9200

单位都是毫秒。最后一列那个0不是笔误,是压根没拿到响应——15秒的超时上限到了,连接被主动掐断。这台机器出不去那个域名,而它三次读数分别是15000.5、15001.1、15001.2,误差不到千分之一。那不是网络抖动,是超时计时器本身的精度。

还有一处细节值得记下来:返回码403和503那两行,耗时并没有比返回200的那行少。失败不比成功快,这是很多人做容量估算时会漏掉的一条——你不能假设出错的调用会很快返回。

把这三档数字加回基线上:

  • 内联一个437毫秒的调用:23.9变成460.9毫秒,慢19.3倍
  • 内联一个900毫秒的调用:23.9变成923.9毫秒,慢38.7倍
  • 内联那个出不去的接口:23.9变成15023.9毫秒,慢628.6倍

第三行才是重点。它平时可能一直是好的,某天对方机房出问题,或者某条国际线路抽风,你的下单接口就从24毫秒变成15秒。用户不会知道是第三方的问题,他只知道这个站点击提交之后转了半分钟圈。

判断依据很朴素:凡是调用对象不在你的机房里,它的最坏情况就等于你配的超时时长。你配15秒,最坏就是15秒;你不配超时,最坏是无穷。

串行、并行、挪走,三条路差多少?

假设下单之后要做三件事:发确认邮件、通知仓储、同步给数据看板。按上面实测的耗时取437、722、900毫秒,三种做法的结果是:

做法用户等待说明
三件事串着做2059毫秒三段时间直接相加
三件事并发做900毫秒等于最慢那件事
三件事丢进队列0.4毫秒只付了三次写入的钱

最后一行是实测值,往内存库里推三条消息实际花了0.4毫秒。跟串行的2059毫秒比,差5148倍

这个对照里最容易被忽略的是中间那行。很多团队第一反应是那我并发去调不就行了,确实从2059降到了900。但用户还是在等,而且你现在有三个可能失败的调用挂在同一个请求里,任何一个超时都会把响应时间拉回15秒。进程池被慢请求占满这件事本站写过,并发调用只是把占用时间从串行的总和压到了最大值,没有把它从请求路径里拿走。

还要澄清一个常见误解:队列并没有让这三件事完成得更快。发邮件该花437毫秒还是437毫秒,只是这437毫秒发生在用户已经看到成功页面之后。端到端的总时长甚至可能更长,因为多了入队和出队两跳。队列买的是用户不用等,不是事情做得快。

不上队列,还有哪两条退路?

把任务挪出请求路径,队列不是唯一的办法。按复杂度从低到高,实际能用的是三条。

退路一:定时任务轮询

把要做的事写进一张表或一个文件,让定时任务隔一会儿来扫一遍。这是成本最低的方案,几乎不引入新组件。

代价是延迟。定时任务的最小粒度是一分钟——手册页里那句"cron(8) examines cron entries every minute"说得很直白,守护进程每分钟醒一次去比对表达式,你没法让它每10秒跑一趟。所以:

跑的频率最好情况最坏情况平均等待
每1分钟0秒60秒30秒
每5分钟0秒300秒150秒
每15分钟0秒900秒450秒
每60分钟0秒3600秒1800秒

顺手看了眼那台机器的任务表,上面跑着一条每5分钟触发一次的站点计划任务。也就是说,那个站上任何依赖这条任务的动作,平均要等两分半钟。对于下单后发确认邮件这种场景,两分半钟已经超过了用户的耐心阈值——很多人这时候已经在翻垃圾邮件箱了。

什么时候够用?备份、生成站点地图、续证书、清缓存这类没有人在等结果的事,定时任务完全够用,本站的运维自动化那套就是这么跑的。表达式怎么写本站也有专门一篇。

退路二:数据库表当队列

建一张任务表,写入的时候插一行,消费的时候锁一行、改状态、干活。这是电商系统里最常见的做法,因为它不引入任何新组件,而且天然带持久化。

保哥在那台机器上真跑了一遍,5000条任务,用最标准的写法——事务里先加锁读取一行,再更新状态:

做法入队耗时出队耗时入队速率出队速率
数据库表,逐条5731.0毫秒10092.3毫秒872条/秒495条/秒
内存库列表,逐条560.7毫秒549.2毫秒8917条/秒9104条/秒

出队慢是有原因的。加锁读取这种写法,官方文档里的原话是它会设置与搜索型更新语句相同的锁,其他事务想更新这些行、或者在某些隔离级别下想读这些行,都会被挡住。一条任务的完整流程是开事务、加锁读、更新、提交,四次往返,实测下来每条2.02毫秒。

顺带量了一下体积:5000条任务的表连同索引占464KB,折合每条95字节。也就是说十万条积压任务大概占9MB,对磁盘来说不值一提。用数据库表当队列,瓶颈从来不是空间,是锁。

495条每秒是什么概念?一天86400秒,理论上能处理4200万条。对于日均几百单的站,这个数字绰绰有余。所以别急着嫌它慢——它慢的是单位吞吐,不是绝对能力。

退路三:真正的队列组件

到这一步才引入独立的消息中间件。它带来的不只是吞吐,更重要的是投递保证、重试、死信这些机制。那部分内容单独占一篇,本文只负责回答要不要走到这一步。

为什么换存储只快10倍,换调用方式却快29倍?

这是本轮实测里最反直觉的一组数字,也是保哥觉得最值得单独拎出来的一条。

同样是5000条,四种做法的入队速率:

做法耗时速率相对最慢
数据库表,一条一条插5731.0毫秒872条/秒1倍
内存库,一条一条推560.7毫秒8917条/秒10.2倍
数据库表,每500条一句215.9毫秒23159条/秒26.6倍
内存库,管道批量推19.1毫秒261780条/秒300倍

看第二行和第三行。批量写数据库,比逐条写内存库还快2.6倍。如果你的判断依据是内存比磁盘快,这一行就把它推翻了。

原因在往返次数上。单次连接的开销实测是0.095毫秒——1000次心跳探测总共95.4毫秒。这个数字很小,但乘以5000就是475毫秒,已经接近逐条推送总耗时560.7毫秒的85%。把命令打包一次发出去之后,5000条只剩19.1毫秒。

可以记成一句话:换存储换来一个量级,换调用方式换来两个量级。先把往返次数降下来,再考虑要不要换组件。

这条原语在别的地方也成立。批量推送搜索引擎收录接口、批量写日志、批量更新库存,只要接口支持一次提交多条,收益都比换一个更快的后端来得直接。本站在对象缓存那篇里量过一次同类的差距,结论方向一致。

什么样的任务才真该进队列?

把前面的数字汇总一下,判据其实只有四条,全部满足才值得上:

判据怎么验证不满足时的替代
调用方不关心结果问一句失败了要不要当场告诉用户要告诉,就必须同步做
耗时进了请求路径量一下它占响应时间的比例占比不到5%,不值得动
触发时机不确定是事件驱动还是按点跑按点跑,定时任务就够
生产快过消费比较两端的实测速率消费更快,队列永远是空的

第四条最容易被忽略。本轮实测里内存库的出队速率是9104条每秒,如果你的业务每秒只产生几十条任务,那队列里永远堆不起东西——你花力气搭的那套削峰机制,一次都不会被触发。削峰这个词只在峰值真的存在时才有意义。

反过来,如果入队5000条每秒而消费只有495条每秒,每秒净积压4505条,十分钟就是270万条。这时候队列不是在削峰,是在给你争取扩容的时间。

顺着这个数往下算一步会更清楚:积压270万条之后,就算流量瞬间降到零,按495条每秒消化完也要5454秒,一个半小时。这一个半小时里,所有排在后面的用户都收不到确认邮件。所以削峰不是把问题消掉了,是把一个五分钟的尖峰摊成了一个半小时的长尾,你得确认业务能接受这个摊法。

真正的解法是让消费端也能横向扩。同一个队列挂四个消费者,理论上消费速率乘以四,积压消化时间除以四。这也是队列相比定时任务的核心优势——定时任务加机器会重复干活,队列加机器直接分摊。前提是消费端本身无状态,这一点在动手前就得想清楚。

任务本身多快,队列就不划算了?

这条判据市面上很少有人给具体数字,保哥把它量了出来。单条入队实测0.107毫秒,单条出队0.108毫秒,加起来0.215毫秒是队列的固定开销,跟任务干什么无关。

任务本身耗时队列开销占比结论
0.5毫秒30.1%纯粹的浪费
5毫秒4.1%勉强可接受
50毫秒0.4%完全可忽略
500毫秒0.0%该进队列

所以有一条很实用的粗判据:任务本身跑不到5毫秒,别往队列里塞。给一个写日志、加一个计数器这类动作,直接做完比排队快,还省掉一个组件。见过有人把每次访问的计数更新丢进队列,结果队列本身的开销比那个更新还贵——这就好比为了省两步路,先花十分钟叫了辆车。

消息里到底该放什么?

这条也值得量。同样5000条,只改消息体大小:

消息体大小入队耗时入队速率内存放大
60字节19.1毫秒261780条/秒1.05倍
600字节43.1毫秒116009条/秒1.06倍
6000字节281.8毫秒17743条/秒1.03倍

消息体涨100倍,吞吐掉14.8倍。而内存那一列很干净:放大系数稳定在1.03到1.06之间,说明存储本身几乎不额外收费,贵的是传输。

结论直接:消息里只放标识,不放数据。传一个订单号,让消费者自己去库里查详情,比把整个订单对象序列化进消息体划算得多。顺便还避开了另一个坑——消息里那份数据在排队期间可能已经被改过了,消费者拿到的是快照,而去库里查拿到的是当前值。

上了队列之后会多出哪些新麻烦?

引进一项技术,光知道优点是不够的。保哥在同一台机器上顺手查了一下那个内存库的持久化配置,结果挺能说明问题:

  • 追加写日志:关闭
  • 快照策略:空的,等于不做快照
  • 距离上次落盘:530938秒,也就是6.14天
  • 这期间累计的未落盘变更:108431次
  • 内存打满时的淘汰策略:allkeys-lru

翻译成人话:这台机器上的那个内存库,六天没往磁盘写过一个字节,十万多次变更全在内存里飘着。官方持久化文档把这几种模式的取舍讲得很清楚,而这台机器选的是最松的那一档。

如果有人在这个配置下把它当队列用,进程一重启,队列里所有还没消费的消息就全没了。而最后那条淘汰策略更微妙——内存打满时它会按最近最少使用删键,你排队等着处理的消息,在它眼里跟普通缓存键没有任何区别。这就像把待办清单贴在一块随时会被擦掉的白板上,还是那种别人路过顺手就擦的白板。

除了丢消息,还有三件事是原来不存在的:

新问题具体表现要额外做的事
可用性下降多一个组件就多一个故障点监控队列长度和消费者存活
顺序不保证多个消费者并发处理,先进的不一定先完成需要顺序就得按键分区
重复投递确认丢失会导致同一条被处理多次消费端做幂等

第三条不是实现质量问题,是行业默认。某云厂商的标准队列文档里写得很坦白:"Standard queues ensure at-least-once message delivery, but due to the highly distributed architecture, more than one copy of a message might be delivered, and messages may occasionally arrive out of order."——至少一次投递,可能重复,可能乱序。这是设计取舍,不是缺陷。

队列长度这个数,为什么单看没用?

上了队列之后,绝大多数团队会做的第一件监控是盯队列长度,超过多少条就告警。这个指标不能说错,但它单看几乎没有信息量。

原因是队列长度是个瞬时值,它同时受两端影响。长度是100条,可能是生产端刚推了100条而消费端还没来得及动,一秒后就清空了;也可能是消费端已经死了半小时,这100条是最近攒下的一小部分。同一个数字,一个是正常波动,一个是重大事故。

真正有判断力的是这三个数,都能从任务表或者队列元信息里直接算出来:

指标怎么算它回答什么
最老一条的等待时长当前时间减最早那条的创建时间最坏情况下用户等了多久
队列长度的变化率两次采样的差除以间隔在积压还是在消化
单条处理耗时的分位数取九十分位而不是平均消费端自己有没有变慢

第一个数最值得挂在最显眼的位置。队列长度1000条听起来吓人,但如果最老那条才等了2秒,说明消费端跟得上,只是刚好赶上一波;反过来长度只有5条却最老那条已经等了20分钟,那基本可以确定消费者卡死了——它连5条都处理不掉。

第三个数用九十分位而不是平均值,理由和文章开头那组23.9对486.8是同一个:平均值会把一次卡死稀释成看不见。相关的排查思路在负载排查那篇里展开过,队列这边完全适用。

消费者怎么等下一条,差别有多大?

这是个很容易写错的地方。消费者取不到消息时怎么办,有两种写法,成本差得离谱。

保哥拿空队列测了3秒:不停地问有没有新消息,3秒里发出了29690次请求,折合每秒9897次,全部空手而归。换成阻塞式等待,同样3秒只发出1次请求,一直挂着直到超时返回。

两者之比是29690比1。前一种写法在业务空闲时反而最费资源——半夜没订单,你的消费者却在以每秒近万次的频率骚扰存储。这个反差很值得记住:轮询的成本和业务量成反比,越闲越贵。

怎么分三步走,而不是一步到位?

按前面的数字,一个正在长大的独立站可以这么排:

第一阶段:把它挪出请求路径就行。写一张任务表,定时任务每分钟扫一次。用户不用等,平均延迟30秒。这一步只花半天,覆盖掉八成的场景。这个阶段最重要的动作其实不是写代码,是把任务表的字段设计对——至少要有状态、重试次数、最后一次尝试时间、错误信息这四列,后面所有的排查都靠它们。

第一阶段那张任务表该有哪几列?

这一步做扎实了,后面两个阶段都轻松。保哥的经验是最少七列,缺一列就会在某次排查时后悔:

作用缺了会怎样
类型区分是发邮件还是同步库存只能一种任务一张表,越建越多
载荷放订单号这类标识只能靠表名硬编码,改不动
状态待处理、处理中、已完成、已放弃并发消费时同一条被多人抢
重试次数失败了第几次坏任务无限重试,占死消费能力
下次可执行时间实现退避,也实现延迟任务失败就立刻重试,把下游打得更惨
最后错误失败原因原文只知道失败,不知道为什么
创建时间算积压时长说不清一条任务等了多久

其中最容易被省掉的是下次可执行时间那一列,而它恰恰是最有用的。有了它,取任务的条件就从状态等于待处理,变成状态等于待处理并且下次可执行时间已经到了。同一个字段顺手实现了三件事:失败退避、延迟任务、以及定时发送。想让一封提醒邮件三天后发,写一行时间进去就行,不用额外搭调度器。

状态列一定要建索引,这条前面提过一次,这里再强调是因为它是最常见的翻车点:表里几万行的时候感觉不出来,涨到几百万行,每次取任务都变成全表扫,消费速率会一路掉到个位数。

第二阶段:把轮询换成常驻消费。还是那张表,但改成一个常驻进程一直在跑,处理完立刻取下一条。延迟从30秒降到毫秒级,吞吐拿到实测的495条每秒。进程守护交给系统服务管理器就行,写成开机自启服务本站有现成的做法。这一步要注意的是别让常驻进程空转——用带超时的阻塞读,别写成死循环里不停查表,否则就是上面那个29690比1的翻版。

第三阶段:换成专门的队列组件。触发条件是前面那四条判据全部满足,并且第二阶段的消费速率已经追不上生产速率。这时候再上,你至少知道自己要解决哪个具体问题。像主流框架自带的队列抽象,允许你在不改业务代码的前提下把驱动从数据库换成内存库或者专门的中间件,这个切换成本值得在第一阶段就预留出来。

本站在邮件群发队列那篇里写过一个反面例子:把队列当成万能药,结果配置错了发送节流,邮件一次性全推出去,进垃圾箱的比例反而更高。技术选对了,参数配错了,效果一样是负的。

这套判断在独立站上怎么落地?

把视角切回搜索这一侧。响应时间不只是用户体验问题,它同时影响抓取。

本站热态首字节23.9毫秒,是长期把动态渲染挡在缓存后面的结果。如果在这个链路里内联一个900毫秒的第三方调用,首字节变成923.9毫秒——对访客是能感觉到的卡顿,对爬虫则意味着同样的时间预算里能抓的页面少了一大截。

更麻烦的是不稳定。那个境外接口的15秒超时如果发生在爬虫抓取的时候,拿到的就是超时或者错误页。偶发几次没关系,成为常态就会影响索引。而且这类问题在监控上很难发现——你的正常访客可能因为地理位置不同并不触发那条慢路径,只有爬虫恰好撞上。

具体到独立站,哪些动作应该被挪出渲染路径,其实有一份很稳的清单:

动作典型耗时该放哪
发交易类邮件数百毫秒队列
推送收录接口数百毫秒队列,且批量提交
同步库存到第三方数百毫秒到数秒队列,带重试
生成缩略图数百毫秒队列,或者上传时一次做完
写访问统计亚毫秒直接做,进队列反而亏
刷新缓存标记亚毫秒直接做

怎么把藏在请求路径里的调用找出来?

上面那张表看着清楚,但真实项目里最难的是第一步——你根本不知道自己的下单流程里到底有几个外部调用。代码是几年里好几个人陆续加的,谁也说不全。

有个不用读代码的笨办法,实测很好使:把同一个接口在两种条件下各打十次,比较耗时的分布形状。一种是正常状态,一种是把出网流量掐掉或者把第三方域名解析到一个不通的地址。如果两组数字差得很多,说明请求路径里确实挂着外部依赖;如果几乎没变,那说明那些调用已经是异步的,或者根本没被触发。

更精细一点,可以看响应时间的分布形状。纯本地处理的接口,快慢会集中在一个很窄的区间里,就像本文开头那四次23.8到24.0毫秒。一旦分布拉出长尾——大部分很快,偶尔冒出几百毫秒甚至几秒——那条长尾几乎一定来自网络调用。本地计算不会突然慢十倍,网络会。

拿本站那五次实测当例子:四次23.9,一次486.8。如果这是你的下单接口,那第五次就是需要去查的对象,而不是当成噪声抹掉。做性能优化的人常犯的错是盯着平均值优化,可用户投诉从来都来自长尾那一端。

某个做户外装备的独立站在旺季促销时就撞过这个:平时下单接口的平均耗时一直很体面,一开闸就有用户反馈点提交没反应。后来发现是库存同步接口挂在下单流程里,平时对方响应很快,促销时对方自己也被打满,响应从两百毫秒涨到十几秒。问题不在自己的代码,但受影响的是自己的转化率——把那个调用挪进队列之后,下单接口的耗时曲线立刻变平了。

所以对独立站来说,把第三方调用挪出请求路径这件事有双重收益:访客等得少,爬虫也抓得动。判断标准可以简化成一句——凡是能在页面渲染完之后再做的事,就不该出现在渲染路径上。这个思路和用工作流工具把重复动作产线化是同一个方向:先把人和请求从等待里解放出来,再谈提速。

常见问题解答

问:几百单的小站到底要不要上队列?

按第四条判据,大概率不用。日均几百单意味着每秒不到一条任务,而一张普通数据库表实测能出队495条每秒,中间差着四个数量级。先做第一阶段——把任务写进表、定时任务扫——通常就够了。等到某天你发现表里积压的行数在持续增长,再考虑往上走。判断标准不是订单量的绝对值,是积压曲线的斜率。

问:数据库表当队列会不会把主库拖垮?

会,但不是因为吞吐,是因为锁。加锁读取会阻塞其他事务对这些行的更新,如果消费者拿着锁去做一件耗时几百毫秒的事,锁就一直握着。正确的写法是先在事务里快速把状态标成处理中然后提交,再在事务外面干活。本轮实测的10092.3毫秒就是标准写法的成本,纯粹是锁和事务的开销,跟实际业务无关。另外记得给状态列建索引,否则每次取任务都是全表扫。

问:为什么并发调用不算数?

因为它没有把任务从请求路径里拿走,只是把总耗时从三段相加压到了最慢那一段。实测是2059毫秒降到900毫秒,看起来省了一半多,但用户仍然在等,而且现在有三个可能超时的调用挂在同一个请求上。任何一个撞上15秒超时,整个请求还是15秒。并发是优化,异步是解耦,两件事。

问:内存库当队列到底靠不靠谱?

取决于配置。本轮在那台机器上查到的是:追加写关闭、快照策略为空、六天没落盘、内存打满按最近最少使用淘汰。这个配置下当队列,重启就丢,内存紧张也丢。要用它当队列,至少得把追加写打开,并且把队列的键放在一个不做淘汰的实例上,不要和缓存混用同一个实例。混用最危险的地方在于:缓存打满触发淘汰,被删掉的可能正好是你的待办任务,而且不会有任何提示。

问:批量提交是不是万能的?

不是。批量把往返次数降下来,代价是延迟和失败粒度。攒够500条再发,第一条要多等499条的时间;而且一批里有一条失败,你得决定是整批重来还是挑出来单独处理。实时性要求高的场景,通常的折中是按条数和时间双阈值触发——攒够100条发一次,或者攒够50毫秒发一次,先到哪个算哪个。

问:怎么判断现在的任务表已经撑不住了?

看三个数:待处理行数是不是在持续增长而不是波动,最老一条待处理任务的等待时长是不是在变长,以及消费一条的平均耗时是不是在变长。前两个说明生产快过消费,第三个说明单条处理本身在退化。三个里出现两个,就该考虑往上走一级了。这三个数都能用一条查询算出来,建议直接挂到监控面板上,别等用户投诉才去看。

问:消息体大小有没有硬上限?

各家组件的上限不一样,但按本轮实测的趋势,你根本用不到那个上限就已经被吞吐劝退了——6000字节的消息体入队速率已经掉到60字节时的十四分之一。实操上把消息体控制在几百字节以内是安全区,超过一两千字节就该考虑只传标识。真需要传大对象,标准做法是把对象存到别处,消息里只放一个取回地址。

权威参考资料

分享到
标签
版权声明

本文标题:《下单接口里那行发邮件的代码,把24毫秒的响应拖成了924毫秒》

本文链接:https://zhangwenbao.com/async-task-when-to-use-message-queue.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交