想象一下:你开了一家网上书店,所有书都存放在城市郊区的中央大仓库。顾客在北京下单,包裹要从仓库出发,穿过半个中国才能送到——慢,而且快递费贵。现在,你在上海、成都、广州、哈尔滨各开了一家社区便利店,每家店里都放着最常卖的几百本书。顾客下单,直接从最近的便利店取货,下楼即取;只有便利店没货的书,才需要从中央仓库调货。 这就是CDN(内容分发网络)的核心思想:把内容搬到离用户最近的地方。边缘缓存节点就像社区便利店,源站就像中央大仓库,而DNS智能解析就像顾客手机里的地图App——自动告诉你“附近哪家便利店最近、有货”。命中缓存就像“店里正好有货”,回源就像“得从大仓库调货”。本章我们沿着这条“便利店网络”的比喻,拆解CDN加速的六大工程环节:节点缓存、智能调度、缓存策略、预热刷新、HTTPS加速、压缩优化,以及最后的监控排障。
对AI从业者而言,CDN是高并发系统性能的“最后一公里”加速器。理解它的缓存命中与失效机制,能帮你在模型服务、数据分发、API网关等场景下做出低延迟、高可用的架构决策。
目录
可视化演示
展示用户在DNS解析下就近接入最近边缘节点、缓存命中率与回源的关系、以及大流量前的缓存预热与变更时的缓存刷新机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
就近节点解析 DNS解析选择最近的边缘节点 用户就近获取内容减少回源 用户→最近节点→缓存 降低网络传输距离与延迟
节点缓存选址:便利店该开在哪条街
深夜的上海,你刚在网上下单了一本热门小说。三秒后,手机弹出“已从附近便利店发货”——这家店离你只有800米。这背后的功臣,是遍布城市的CDN边缘节点。它们就像社区便利店,选址标准只有一个:离潜在顾客足够近,且覆盖足够密。如果这家便利店开在了无人区,再大的仓库也换不来一个回头客。
边缘节点的部署不是平均撒网,而是跟着流量地图走。人口密集、网络繁忙的城市核心区,节点密度高;偏远地区则用少量节点覆盖大片区域。每个节点内部还会做内容分层:最热门的视频、图片放在内存级缓存(相当于便利店门口的“热销专柜”),中等热度的放在SSD(货架区),冷门内容则回源站取(大仓库调货)。
技术实现上,内容分层通常由缓存系统根据访问频率动态调整。边缘节点记录每个内容的访问次数与最近访问时间,热度下降的对象从内存降级到磁盘,最后被淘汰。这套机制的目标,是在有限的存储空间中最大化缓存命中率——即用户请求直接命中本地缓存的概率。
便利店选址决定了生意好不好。节点部署得当,用户就近取货,延迟自然低;部署失当,顾客跑远路,体验直线下降。这也是为什么CDN厂商在全球部署成千上万个节点,本质上是把“近”这个字做到极致。
- 命中率的定义命中率是衡量缓存系统效率的核心指标,表示所有用户请求中,能在边缘节点本地直接返回的比例。
- 回源率的定义回源率是命中率的镜像指标,表示需要到源站取数据的请求比例。
- 二者互补关系命中率与回源率之和恒等于1,所以监控回源率等于间接监控命中率。
智能调度解析:顾客如何找到最近的店
新顾客走进商场,怎么知道楼上哪家便利店有货?他会打开商场导览屏查询——CDN中的DNS智能解析就是这个“导览屏”。
当用户在浏览器输入网址时,浏览器先向DNS服务器询问“这个域名对应的IP是什么”。普通DNS只会机械地返回一个固定IP;而CDN的DNS服务器(通常称为GSLB,全局负载均衡器)会“抬头看”发起请求的用户来自哪个城市、哪个运营商,然后从全局节点列表中挑选一个地理位置最近、负载最轻、网络质量最好的节点IP返回。整个过程对用户透明,耗时通常在几十毫秒以内。
GSLB的决策依赖一组实时指标:节点往返时延(RTT)、节点当前负载、节点与用户间的网络跳数。它把这些指标代入评分函数,得分最高的节点胜出。DNS解析结果并非永久有效,而是带有TTL(存活时间)——就像商场导览屏上的信息每隔几分钟更新一次,DNS记录过期后,用户的设备会重新请求解析,从而有机会被调度到更优的节点。
导览屏不是一次性指路就完事,它会在你每次“迷路”(DNS过期)时重新指路。这套“引导+更新”的机制,确保了用户永远被导向当下最优的便利店。
- 延迟评分项节点与用户间延迟越低,该项得分越高,引导用户访问最近的节点。
- 负载评分项节点当前负载越低,得分越高,避免把用户调度到即将过载的节点。
- 网络质量评分项综合丢包率、抖动等指标,量化节点网络质量。
缓存策略设计:便利店的保质期与商品指纹
便利店里的牛奶会过期,CDN缓存的内容也会“过期”。源站在返回内容时,会附上一张“保质期标签”——HTTP头中的Cache-Control: max-age=600,意思是“这份内容600秒内不会变,便利店可以放心卖”。在这600秒内,用户的请求直接命中缓存,完全不打扰源站。
但过期之后呢?便利店不需要立刻把商品扔掉,而是拿着商品去仓库问一句:“这个东西变了吗?”仓库回应“没变”(HTTP 304 Not Modified),便利店只需把保质期标签撕掉换一张新的,商品继续卖;如果仓库说“变了”,便利店才重新拉取最新内容。这个“确认是否变化”的机制,就是ETag/Last-Modified协商缓存。ETag相当于商品的指纹——文件内容变了,指纹就变;Last-Modified相当于商品的出厂日期,两者配合使用。
聪明的店长会把“生鲜”(动态API)和“干货”(静态图片)分开管理——动态内容设置短缓存甚至不缓存,静态内容设置长缓存。这套“动态静态分离”策略,让便利店既保证新鲜度,又最大化缓存效益。
max-age和Expires中较早到期的时刻——谁先到期,以谁为准。这是缓存系统最基础的时间边界,任何缓存策略都在这条边界内运转。- max-age 优先级
Cache-Control中的max-age是HTTP/1.1标准的相对时间指令,优先级最高。 - Expires 兜底
Expires是HTTP/1.0时代的绝对过期时间,两者并存时以max-age为准。 - 取最小值最终有效时间取两者更早者,确保任何一条规则都不会被突破。
预热与刷新:大促前先把货架填满
双十一零点,某电商平台要在早上10点上线一款限量球鞋。如果等到用户开始抢购,边缘节点才发现“没货”再去源站拉取,源站瞬间会被海量回源请求打爆。聪明做法是:提前把球鞋页面推送到全国各边缘节点,让每家便利店的货架上都备好货。这就是URL预热。
预热是主动行为,由运营或运维人员调用CDN厂商的预热API,传入URL列表,CDN系统主动回源拉取内容并分发到各节点。与预热相对的是URL刷新——当球鞋价格标错了需要紧急下架,或者页面样式改了需要用户立刻看到新版,就需要主动通知各节点“把某个URL的缓存作废”。这相当于便利店总店发出召回通知:某批商品有问题,全部下架。
大型系统的预热讲究“分层”:核心页面提前一天预热,次要页面提前几小时预热,边缘长尾页面在流量到达前半小时预热。这样既避免一次性预热过多内容造成网络拥堵,又能确保最关键的流量被缓存兜住。
预热是“未雨绸缪”,刷新是“亡羊补牢”。两者一推一拉,构成了CDN内容更新的完整闭环——大促前把货备足,发布后把旧货清掉。
- 已预热URL数指在所有边缘节点完成缓存写入的内容数量,是预热的“实绩”。
- 活动涉及URL总数指活动页面所有依赖资源(HTML、CSS、JS、图片)的总数,是预热的“目标”。
- 覆盖率的意义覆盖率接近100%时,大促流量几乎全部命中缓存,源站只需服务极少量回源请求。
HTTPS加速:给便利店装上“秒开安全门”
便利店加了防盗门,安全性提高了,但顾客每次进门都要多花两秒开锁,体验变差。HTTPS也是一样——TLS握手需要额外的往返次数,让首次访问变慢。CDN加速HTTPS的关键,就是把这扇安全门从“每次重开”变成“一次打开,多次通行”。
TLS 1.3把握手从2-RTT压缩到1-RTT,而会话恢复(Session Resumption)机制更进一步:用户首次完成TLS握手后,CDN边缘节点会发给客户端一个会话票据(Session Ticket)。下次该用户再来访问时,直接凭票据恢复会话,不需要重新交换密钥——相当于便利店发给老顾客一张VIP卡,第二次来直接刷卡进门,不用再掏身份证。
另一个容易忽略的性能点是OCSP Stapling。浏览器验证网站证书是否有效时,原本需要额外请求证书颁发机构(CA)的OCSP服务器。启用OCSP Stapling后,CDN边缘节点代替浏览器定期向CA查询证书状态,并把结果“钉”在TLS握手消息中直接返回给浏览器——省掉了浏览器额外的一次网络请求。
安全与速度不是二选一。CDN通过会话复用和OCSP Stapling,把安全门的开锁时间压到几乎为零——顾客既安全,又不耽误进门买货。
- 完整握手耗时客户端与边缘节点首次建立TLS连接所需的时间,包含密钥交换与证书验证。
- 会话恢复耗时携带Session Ticket再次连接时,客户端与边缘节点恢复会话所需的时间。
- 节省时间两者之差即为每次请求因会话恢复节省的延迟,是HTTPS加速的量化收益。
Brotli压缩优化:把包裹压得更小再出发
便利店送货上门,同样一件衣服,用大纸箱装和小纸箱装,快递费完全不同。CDN传输数据也一样——内容越小,网络传输越快。传统的Gzip压缩如同标准纸箱,有效但不够极致;Google推出的Brotli算法则像定制压缩袋,能把体积再压小一圈。
Brotli的优势在于它内置了预定义的静态字典(包含常见的HTML标签、CSS属性、JavaScript关键字),对Web文本内容的压缩率显著优于Gzip。实测中,对同样一份HTML文档,Brotli(质量等级5)比Gzip(等级6)体积减少约15%~20%。体积小了,下载时间自然缩短——尤其对弱网用户,收益极其明显。
但“压缩袋”不是免费午餐。Brotli的压缩需要更多CPU计算,压缩级别越高,CPU消耗越大,延迟越长。CDN通常采用动态分级策略:对高频访问的小文件用高压缩等级(反正缓存后只需压缩一次),对超大文件或CPU紧张的节点用较低的压缩等级,平衡“压得更小”与“算得更快”。
给内容穿上更贴身的“压缩衣”,传输效率立竿见影。但不是所有内容都值得穿——已经高度压缩的图片(JPEG、PNG)和视频,再压也挤不出多少水分,CDN通常只对文本类资源启用Brotli。
- Gzip压缩后体积使用传统Gzip算法压缩后的内容大小,作为基准值。
- Brotli压缩后体积使用Brotli算法压缩后的内容大小,通常更小。
- 体积缩减率两者差值占Gzip体积的比例,量化Brotli的压缩增益。
监控与排障:便利店的经营仪表盘
社区便利店的店长每天看三张表:销售额、客流、缺货率。CDN运维也有类似的仪表盘——命中率、回源率、延迟。某天深夜,店长发现“缺货率”突然从5%飙到50%,而便利店门口排起长队——对应到CDN,就是某节点命中率骤降、回源率暴涨、用户响应时间飙升。
故障排查的逻辑是“由近及远”:先看用户→边缘节点这段链路是否正常,再看边缘节点→源站的回源链路是否健康。常见的故障原因包括:源站更新了文件但未执行URL刷新导致缓存与源站不一致;某个边缘节点被下线导致流量全部压到剩余节点;或者预热任务因配置错误没有触发,大促流量直接穿透到源站。
容量规划则要求运维根据历史流量趋势和业务增长预测未来峰值,为关键节点预留余量。当预测到某个节点将过载时,提前扩容或通过调度系统把流量分散到周边节点。这就像便利店在大促前预估客流,提前多备人手和货架,避免客流高峰时手忙脚乱。
仪表盘不会说谎。命中率的起伏、回源率的异动、延迟的抖动,这些数字背后是用户的真实体验。学会读表,就能在大故障发生前按下暂停键。
- 回源率计算回源率是回源请求占总请求的比例,是判断缓存系统健康度的关键指标。
- 预警阈值行业经验值30%是警戒线,超过后源站可能过载,需要介入排查。
AI 应用场景
大促活动页自动预热
阶段:数据分发与资源调度
解决的问题:大促前运营人员需手动整理数百个活动URL并逐条调用预热接口,容易遗漏且无法优化预热时机。AI从历史流量数据中学习各商品页面的访问峰值时间,自动生成分层预热计划。
具体案例:某电商平台在大促前,AI系统根据往年同时段流量曲线预测各商品页的访问峰值,提前2小时自动预热Top 100热销商品页面,峰值前30分钟预热次热销页面,大促当天命中率从78%提升到96%,源站峰值QPS下降45%。
动态压缩策略的AI调优
阶段:性能优化与自适应控制
解决的问题:Brotli压缩等级需要人工根据CPU余量和网络状况调整,无法应对流量突发。AI实时监控各边缘节点的CPU利用率和用户带宽分布,动态调整每个节点的压缩等级。
具体案例:某视频点播网站的边缘节点在晚高峰CPU达到92%,AI自动将Brotli压缩等级从5降到3,CPU回落到70%,同时因压缩等级降低带来的带宽成本增加不到5%,用户卡顿率反而下降了30%。
命中率异常智能告警
阶段:监控与故障预测
解决的问题:传统监控基于固定阈值告警,无法区分“正常波动”与“故障前兆”。AI模型学习每个节点的历史命中率规律,能提前30分钟预测异常回源事件。
具体案例:某新闻App的AI监控系统在凌晨2点检测到某省节点命中率偏离预测值25个百分点,自动触发预热任务刷新该省热点新闻缓存,20分钟后指标恢复正常,避免了早高峰的源站过载。
Python 演示
"""边缘缓存模拟器:演示缓存命中、回源、预热与刷新""" import timefrom collections import OrderedDict class EdgeCache: """模拟单个CDN边缘节点的LRU缓存""" def __init__(self, capacity, origin_store): self.capacity = capacity self.origin = origin_store self.store = OrderedDict() self.hit_count = 0 self.miss_count = 0 def get(self, key): """读取缓存内容,未命中则回源并写入缓存""" if key in self.store: self.store.move_to_end(key) self.hit_count += 1 return self.store[key] value = self.origin[key] self.miss_count += 1 self.store[key] = value self.store.move_to_end(key) if len(self.store) > self.capacity: self.store.popitem(last=False) return value def warmup(self, key): """预热:主动回源拉取并写入缓存""" if key not in self.store: self.store[key] = self.origin[key] self.store.move_to_end(key) print(f"warmup {key}") def refresh(self, key): """刷新:删除缓存,下次请求回源拉取新内容""" if key in self.store: del self.store[key] print(f"refresh {key}") @property def hit_rate(self): total = self.hit_count + self.miss_count return self.hit_count / total if total else 0.0 def main(): origin = { "index.html": "<html>v1</html>", "logo.png": "PNG-DATA-V1", "banner.jpg": "JPG-DATA-V1", "app.js": "JS-V1", "report.pdf": "PDF-V1", } cache = EdgeCache(capacity=3, origin_store=origin) cache.warmup("index.html") cache.warmup("logo.png") requests = [ "index.html", "logo.png", "banner.jpg", "index.html", "report.pdf", "logo.png", ] for req in requests: cache.get(req) print(f"hit_rate={cache.hit_rate:.2%}") origin["app.js"] = "JS-V2" cache.refresh("app.js") cache.get("app.js") print(f"hit_rate={cache.hit_rate:.2%}") if __name__ == "__main__": main()
self.store = OrderedDict()用有序字典保存缓存内容,实现LRU淘汰if key in self.store: self.store.move_to_end(key)LRU核心:每次访问把key移到队尾value = self.origin[key]; self.miss_count += 1未命中时回源拉取,并记录回源次数if len(self.store) > self.capacity: self.store.popitem(last=False)超出容量时淘汰队首最少使用的keydef warmup(self, key)预热:不经过用户请求,直接回源填充缓存def refresh(self, key)刷新:主动删除指定key的缓存,下次请求时强制回源origin["app.js"] = "JS-V2"; cache.refresh("app.js")模拟源站更新文件后调用刷新接口使缓存失效
常见误区
误区很多人以为CDN就是把内容复制到一台“更快”的服务器上,用户还是访问同一台服务器,只是带宽变大了。
正解CDN的核心价值在“分布式”而非“单点加速”。它是在全球成千上万个节点同时缓存内容,再通过智能DNS解析把用户引导到最近的节点。就像便利店网络的威力不在于某一家店有多大,而在于门店密度足够高,让每个顾客都能就近取货。单点加速只能服务一个区域的用户,分布式网络才能服务全球。
为何常见:因为“加速”这个词容易让人联想到“换一台更快的服务器”,而忽略了“就近分发”这个更本质的机制。
误区缓存命中率是CDN的核心指标,那命中率当然越高越好,最好所有内容都命中缓存。
正解命中率100%意味着所有内容都长缓存,但业务是动态的——用户登录信息、实时库存、价格变动这些内容必须实时回源。过度追求高命中率会导致动态内容被错误缓存,用户看到过期数据。正确做法是动态静态分离:静态资源追求高命中率,动态内容保证实时性,整体命中率在80%~95%是健康的。
为何常见:因为把“命中率”当成了唯一目标,忽略了缓存一致性和数据新鲜度同样重要。
误区很多人认为预热只要把URL列表提交上去,CDN就会自动搞定一切,不需要关注预热时机和覆盖率。
正解预热需要精细的节奏控制。一次性预热大量URL会瞬间产生海量回源请求,反而把源站打垮。实战中采用分层策略:核心页面提前一天预热、次要页面提前几小时、长尾页面半小时前。同时要监控预热覆盖率,覆盖率不足时及时补推。就像便利店补货不是闭着眼把所有货都搬来,而是根据预测销量分批上架。
为何常见:因为预热API的使用门槛看起来很低,提交URL列表就行,让人忽略了背后的节奏设计和覆盖率管理。
误区有些人认为HTTPS加密了内容,CDN无法读取缓存,所以HTTPS网站用不了CDN加速。
正解HTTPS加密的是“传输过程”而非“缓存逻辑”。CDN边缘节点会解密请求、按缓存策略处理内容、再重新加密返回给用户。实际上,大型CDN节点都标配TLS终止和会话复用功能,HTTPS不仅能用CDN,还能通过边缘节点的会话复用获得额外的握手加速。回源链路同样可以通过自定义证书保持加密,不存在“加密就不能缓存”的矛盾。
为何常见:因为把“端到端加密”误解为“每一跳都必须加密传输”——实际上CDN是可信中间人,解密后内部处理再加密是标准做法。
误区Brotli压缩率比Gzip高,那把压缩等级调到最高(quality=11),就能获得最大的传输节省。
正解压缩等级越高,CPU消耗越大,压缩耗时越长。质量等级11的Brotli压缩速度可能比等级5慢一个数量级,边缘节点在高并发下会因CPU过载而响应变慢。生产环境通常使用质量等级4~5,搭配预压缩(静态资源提前压缩好存储)来同时获得高压缩率和低CPU开销。
为何常见:因为只看到了“压缩率”这个收益指标,忽略了压缩时长这个成本指标——利润表只看收入不看成本,必然算错账。
面试题
Q1. CDN加速最核心的原理是什么?
- A.使用更快的源站服务器
- B.将内容缓存在离用户近的节点← 正确答案
- C.使用更大的网络带宽
- D.通过压缩减少传输体积
答案:B。CDN的本质是“就近分发”——把内容缓存到遍布各地的边缘节点,让用户从最近的节点获取数据。虽然压缩和带宽也能加速,但它们不是CDN区别于普通Web架构的核心原理。B准确抓住了“边缘缓存”这一本质,A、C、D都只是辅助手段。
Q2. 边缘节点缓存未命中时,CDN会执行什么操作?
- A.直接返回404错误给用户
- B.向源站发起回源请求获取内容← 正确答案
- C.让用户等待缓存自动过期后重试
- D.将请求转发给其他边缘节点
答案:B。缓存未命中时,边缘节点会代表用户向源站发起请求,拿到内容后一方面返回给用户,另一方面在本地缓存一份,后续请求即可命中。这是CDN最基本的“回源”机制。A是错误处理,C是消极等待,D在某些场景可能发生但并非缓存未命中的标准行为。
Q3. 以下哪些措施可以提升CDN缓存命中率?
- A.合理设置Cache-Control过期时间← 正确答案
- B.对静态资源启用长时间缓存← 正确答案
- C.大促前执行URL预热操作← 正确答案
- D.所有内容一律禁用浏览器缓存
答案:ABC。合理的长缓存时间(A和B)让内容在有效期内反复命中,预热(C)让内容在请求到达前就存在于缓存中,三项都能提升命中率。D禁用浏览器缓存只会增加CDN层请求量,不会提升命中率。
Q4. 源站更新了文件但CDN仍返回旧内容,最可能的原因是?
- A.CDN节点发生硬件故障
- B.缓存未过期且未刷新← 正确答案
- C.用户本地网络连接断开
- D.DNS解析到了错误节点
答案:B。CDN在缓存有效期内不会回源,即使源站已更新,边缘节点仍会返回旧内容。这时需要执行URL刷新主动清除缓存,或等待缓存自然过期。A、C、D也可能导致异常,但“内容是旧的但能正常返回”最典型的场景就是缓存未过期。
Q5. 关于CDN的URL预热,下列说法正确的是?
- A.预热应在大促前分批次执行← 正确答案
- B.预热会主动向源站拉取内容← 正确答案
- C.预热完成后所有请求都命中
- D.预热可降低大促当天回源压力← 正确答案
答案:ABD。预热通过主动回源(B)把内容推送到边缘节点,分批执行(A)避免一次性压力过大,有效降低大促当天的回源量(D)。但预热不等于永久缓存,内容仍会过期失效,所以C“所有请求都命中”过于绝对。
Q6. DNS的TTL时间对CDN调度有什么影响?
- A.TTL表示内容在缓存中的存活时间
- B.TTL越短节点切换越频繁← 正确答案
- C.TTL越长用户刷新越频繁
- D.TTL与DNS调度没有任何关系
答案:B。TTL是DNS记录在用户设备上的存活时间。TTL越短,用户重新解析DNS越频繁,CDN越有机会根据最新负载和网络状况切换节点。但TTL过短会导致解析请求增多。TTL控制的是DNS解析结果的生命周期,不是内容缓存时间,A是对概念的混淆。
Q7. 某CDN节点回源率从10%突增到50%,以下哪种排查思路最合理?
- A.立即重启所有边缘节点
- B.检查缓存是否被批量清除← 正确答案
- C.直接增加源站服务器数量
- D.关闭CDN强制用户直连源站
答案:B。回源率突增通常意味着缓存大面积失效,常见原因包括清空缓存操作、缓存过期时间配置变更、预热任务失败等。应先定位缓存失效原因再对症下药。B是最直接的排查方向。A是盲目操作,C和D回避了CDN问题本身,可能使故障扩大。
Q8. 关于Brotli压缩级别选择,生产环境最合理的做法是?
- A.所有资源都使用最高压缩级别
- B.文本资源用中高压缩级别并预处理← 正确答案
- C.图片视频也使用高压缩级别
- D.压缩级别越高CPU消耗越低
答案:B。Brotli质量等级4~5兼顾压缩率和速度,静态资源建议离线预压缩减少运行时CPU开销。图片视频本来已是压缩格式,再用Brotli收益极小。A忽视CPU成本,C对已压缩格式无意义,D说法本身错误——级别越高CPU消耗越大。
Q9. TLS会话复用机制为什么能加速HTTPS?
- A.会话票据避免重新交换密钥← 正确答案
- B.边缘节点代替CA验证证书
- C.减少TLS握手往返次数← 正确答案
- D.把加密传输改成明文传输
答案:AC。会话复用(Session Ticket)让客户端在后续连接中直接恢复之前的会话,不再需要完整的密钥交换流程,从而减少握手往返次数(A和C)。B是OCSP Stapling做的事,不属于会话复用;D完全不正确,加密是安全底线,不能因加速而放弃。
Q10. 边缘节点无法缓存动态API响应,下列哪种方案最合理?
- A.强制缓存并设置一年有效期
- B.对API响应做边缘计算聚合← 正确答案
- C.所有请求直接穿透到源站
- D.将API改成WebSocket长连接
答案:B。动态API难以缓存的关键在于个性化内容,但很多API响应是半动态的——公共部分多、个性化部分少。在边缘节点做计算聚合(B),比如将首页公共模块缓存、个性化模块回源拼接,是CDN厂商推荐的“边缘计算”方案。A会导致用户数据串号,C放弃边缘优化,D改变了传输协议,都不合理。