<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Cjk on Henry&#39;s Dreamland</title>
        <link>https://b.henryzhou.com/tags/cjk/</link>
        <description>Recent content in Cjk on Henry&#39;s Dreamland</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Sun, 21 Jun 2026 18:47:00 +0000</lastBuildDate><atom:link href="https://b.henryzhou.com/tags/cjk/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>两次 Elasticsearch 踩坑实录:Backblaze B2 快照 501 与中文热词里的英文截断</title>
        <link>https://b.henryzhou.com/%E4%B8%A4%E6%AC%A1-elasticsearch-%E8%B8%A9%E5%9D%91%E5%AE%9E%E5%BD%95backblaze-b2-%E5%BF%AB%E7%85%A7-501-%E4%B8%8E%E4%B8%AD%E6%96%87%E7%83%AD%E8%AF%8D%E9%87%8C%E7%9A%84%E8%8B%B1%E6%96%87%E6%88%AA%E6%96%AD/</link>
        <pubDate>Sun, 21 Jun 2026 18:47:00 +0000</pubDate>
        
        <guid>https://b.henryzhou.com/%E4%B8%A4%E6%AC%A1-elasticsearch-%E8%B8%A9%E5%9D%91%E5%AE%9E%E5%BD%95backblaze-b2-%E5%BF%AB%E7%85%A7-501-%E4%B8%8E%E4%B8%AD%E6%96%87%E7%83%AD%E8%AF%8D%E9%87%8C%E7%9A%84%E8%8B%B1%E6%96%87%E6%88%AA%E6%96%AD/</guid>
        <description>&lt;h1 id=&#34;两次-elasticsearch-踩坑实录backblaze-b2-快照-501-与中文热词里的英文截断&#34;&gt;两次 Elasticsearch 踩坑实录:Backblaze B2 快照 501 与中文热词里的英文截断
&lt;/h1&gt;&lt;p&gt;最近给一个 Telegram 群消息分析的 dashboard 做基础设施,踩了两个挺有代表性的坑。一个是 &lt;strong&gt;Elasticsearch 升级后,Backblaze B2 快照突然传不上去(501)&lt;/strong&gt;;另一个是 &lt;strong&gt;中文热词功能里,英文单词被莫名其妙截断&lt;/strong&gt;(fable 变成 fabl)。&lt;/p&gt;
&lt;p&gt;两个问题表面毫不相干,但回头看,它们其实是同一类&amp;quot;惊喜&amp;quot;的两种形态:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个是&lt;strong&gt;版本升级引入了新的默认行为&lt;/strong&gt;,打破了原本能跑的集成;&lt;/li&gt;
&lt;li&gt;一个是**&amp;ldquo;省事&amp;quot;的封装(开箱即用的分析器)悄悄塞进了你不想要的行为**。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;记录一下现象、排查过程(包括走过的弯路)和最终解法。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;坑一elasticsearch-942-升级后backblaze-b2-快照报-501&#34;&gt;坑一:Elasticsearch 9.4.2 升级后,Backblaze B2 快照报 501
&lt;/h2&gt;&lt;h3 id=&#34;背景&#34;&gt;背景
&lt;/h3&gt;&lt;p&gt;集群是两节点 ES,用 &lt;strong&gt;Backblaze B2&lt;/strong&gt;(S3 兼容对象存储)做快照灾备,走官方的 &lt;code&gt;repository-s3&lt;/code&gt;。在 &lt;strong&gt;9.0.0&lt;/strong&gt; 上一切正常:仓库注册、&lt;code&gt;_verify&lt;/code&gt;、打快照、SLM 定时备份都没问题。&lt;/p&gt;
&lt;p&gt;后来做滚动升级到 &lt;strong&gt;9.4.2&lt;/strong&gt;。升完&lt;strong&gt;第一个节点&lt;/strong&gt;(还没碰第二个),问题就来了。&lt;/p&gt;
&lt;h3 id=&#34;现象&#34;&gt;现象
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;POST _snapshot/b2/_verify&lt;/code&gt; 在&lt;strong&gt;升级到 9.4.2 的那个节点&lt;/strong&gt;上失败,另一个还在 9.0.0 的节点正常:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;s3_exception&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;you&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;provided&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;implies&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;functionality&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;that&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;implemented&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Service&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;S3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Status&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;501&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Unable&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;upload&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;object&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;es&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;snapshots&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xxx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xxx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;single&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;upload&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;幸好是滚动升级,只升一台就暴露了——否则两台一起升,灾备会静默失效。&lt;/p&gt;
&lt;h3 id=&#34;排查两条弯路&#34;&gt;排查(两条弯路)
&lt;/h3&gt;&lt;p&gt;报错信息 &lt;code&gt;A header you provided implies functionality that is not implemented&lt;/code&gt; 很笼统,字面意思是&amp;quot;你发的某个 header,我没实现&amp;rdquo;,方向很多。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;弯路 1:以为是 AWS SDK 的默认 checksum。&lt;/strong&gt;
新版 AWS SDK v2 会默认给上传请求加 CRC32 checksum 头,很多 S3 兼容存储不认。标准解法是把 checksum 计算设成 &lt;code&gt;when_required&lt;/code&gt;。于是往节点丢了 JVM 参数:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-Daws.requestChecksumCalculation=when_required
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-Daws.responseChecksumValidation=when_required
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;确认它确实加载了(&lt;code&gt;GET _nodes/jvm&lt;/code&gt; 的 &lt;code&gt;input_arguments&lt;/code&gt; 里有),但&lt;strong&gt;完全没效果&lt;/strong&gt;。原因:ES 的 repository-s3 在&lt;strong&gt;构建 S3 客户端时&lt;/strong&gt;显式设置了 checksum 行为,&lt;strong&gt;覆盖了全局的 JVM/SDK 配置&lt;/strong&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;教训:全局系统属性/环境变量的优先级&lt;strong&gt;低于&lt;/strong&gt;应用在 client builder 里的显式设置。应用要是自己设了,你在外面怎么调都没用。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;弯路 2:以为是 chunked encoding。&lt;/strong&gt;
试了客户端设置 &lt;code&gt;s3.client.default.disable_chunked_encoding: true&lt;/code&gt;,依然 501。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;上网查 + 看 ES 设置文档。&lt;/strong&gt;
两个关键线索:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;B2 其实在 &lt;strong&gt;2025 年 7 月已经支持了 checksum 头&lt;/strong&gt;——所以 checksum 根本不是病根(也解释了弯路 1 为什么白费)。&lt;/li&gt;
&lt;li&gt;Proxmox 社区有人提到 B2 的兼容点是 &lt;strong&gt;&amp;ldquo;Skip If-None-Match header&amp;rdquo;&lt;/strong&gt;——&lt;strong&gt;B2 不支持 &lt;code&gt;If-None-Match&lt;/code&gt;&lt;/strong&gt;。而 ES 文档里正好有个仓库设置 &lt;code&gt;unsafely_incompatible_with_s3_conditional_writes&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;根因&#34;&gt;根因
&lt;/h3&gt;&lt;p&gt;ES 在较新版本给 &lt;code&gt;repository-s3&lt;/code&gt; 加了 &lt;strong&gt;S3 条件写(conditional writes,即 &lt;code&gt;If-None-Match&lt;/code&gt;)&lt;/strong&gt;,用来防止并发写坏仓库。每次上传都带 &lt;code&gt;If-None-Match&lt;/code&gt; 头,而 &lt;strong&gt;B2 不支持这个头 → 回 501&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;9.0.0 没有这个特性,所以一直好;9.4.2 默认开了,于是炸了。&lt;/strong&gt; 一次小版本升级,引入了一个新的默认安全行为,刚好踩中 B2 的兼容短板。&lt;/p&gt;
&lt;h3 id=&#34;解决&#34;&gt;解决
&lt;/h3&gt;&lt;p&gt;一个&lt;strong&gt;仓库级&lt;/strong&gt;开关,直接用 API 改,&lt;strong&gt;不用重启任何节点&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;PUT&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;_snapshot/b&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;s3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;settings&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;bucket&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;your-bucket&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;endpoint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;s3.us-west-002.backblazeb2.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;base_path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;es-snapshots&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;unsafely_incompatible_with_s3_conditional_writes&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;改完 &lt;code&gt;_verify&lt;/code&gt; 两节点立刻通过。&lt;code&gt;unsafely_&lt;/code&gt; 前缀是 ES 在提醒你:关掉条件写就失去了并发损坏保护——但这层保护主要针对&amp;quot;多个集群往同一个仓库写&amp;quot;的场景,单集群独占一个仓库时风险可接受,何况 B2 本来就不支持,没得选。&lt;/p&gt;
&lt;h3 id=&#34;经验&#34;&gt;经验
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;能跑的集成,会在小版本升级里悄悄坏掉&lt;/strong&gt;,因为新版本可能引入新的默认行为(这里是条件写)。升级前读 breaking changes,升级后&lt;strong&gt;实测关键路径&lt;/strong&gt;(比如真打一次快照)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;滚动升级先升一台、立刻验证&lt;/strong&gt;,能在波及全集群前抓住问题。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;笼统的报错会把你带偏。&lt;/strong&gt; &amp;ldquo;header not implemented&amp;rdquo; 看着像 checksum,实际是 &lt;code&gt;If-None-Match&lt;/code&gt;。先用搜索 + 官方设置文档收敛假设,别埋头试。&lt;/li&gt;
&lt;li&gt;升级前&lt;strong&gt;先有一份验证过能恢复的备份&lt;/strong&gt;——讽刺的是,这次坏的恰恰是备份本身,好在旧快照还在。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;坑二中文热词里英文单词被截断fable--fabl&#34;&gt;坑二:中文热词里,英文单词被截断(fable → fabl)
&lt;/h2&gt;&lt;h3 id=&#34;背景-1&#34;&gt;背景
&lt;/h3&gt;&lt;p&gt;dashboard 有个&amp;quot;热词趋势&amp;quot;功能:用 ES 的 &lt;code&gt;significant_text&lt;/code&gt; 聚合,找出某时间段里相对历史&lt;strong&gt;异常高频&lt;/strong&gt;的词。中文要做到&lt;strong&gt;词级&lt;/strong&gt;(而不是单字),给 &lt;code&gt;text&lt;/code&gt; 字段挂了 smartcn(analysis-smartcn 插件)做分词。&lt;/p&gt;
&lt;h3 id=&#34;现象-1&#34;&gt;现象
&lt;/h3&gt;&lt;p&gt;热词列表里,中文词没问题(世界杯、巴拉圭、伊朗),但&lt;strong&gt;英文词被砍了尾巴&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;期望&lt;/th&gt;
          &lt;th&gt;实际&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;fable&lt;/td&gt;
          &lt;td&gt;fabl&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;mythos&lt;/td&gt;
          &lt;td&gt;mytho&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;claude&lt;/td&gt;
          &lt;td&gt;claud&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;status&lt;/td&gt;
          &lt;td&gt;statu&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;opus&lt;/td&gt;
          &lt;td&gt;opu&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;anthropic&lt;/td&gt;
          &lt;td&gt;anthrop&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;排查&#34;&gt;排查
&lt;/h3&gt;&lt;p&gt;直接用 &lt;code&gt;_analyze&lt;/code&gt; 看 smartcn 分析器到底干了什么:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;POST&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;_analyze&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;analyzer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;smartcn&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;fable mythos claude status opus 世界杯 人工智能&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;输出:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fabl / mytho / claud / statu / opu / 世界杯 / 人工智能
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;破案了——&lt;strong&gt;&lt;code&gt;smartcn&lt;/code&gt; 这个开箱即用的分析器,内部是 &lt;code&gt;smartcn 分词器 + Porter 英文词干器 + 停用词过滤&lt;/code&gt;&lt;/strong&gt;。那个 &lt;strong&gt;Porter 词干器&lt;/strong&gt;会把英文单词按词干规则砍后缀(fable→fabl、mythos→mytho、status→statu)。对中文无影响,但混排里的英文就遭殃了。&lt;/p&gt;
&lt;p&gt;再验证去掉 Porter 的方案——只用分词器 + 小写:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;POST&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;_analyze&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;tokenizer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;smartcn_tokenizer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;lowercase&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;fable mythos claude status opus 世界杯 人工智能&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;输出:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fable / mythos / claude / status / opus / 世界杯 / 人工智能
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;英文完整,中文分词&lt;strong&gt;和之前一模一样&lt;/strong&gt;(因为分词器没变,只是去掉了后面的词干步骤)。&lt;/p&gt;
&lt;h3 id=&#34;根因-1&#34;&gt;根因
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;smartcn&lt;/code&gt; 分析器为了&amp;quot;开箱即用&amp;quot;,把 Porter 英文词干器也打包了进去。在纯中文场景没事,但中英混排的内容里,它会把英文词干化,产生 fabl 这种残缺词。&lt;/p&gt;
&lt;h3 id=&#34;解决-1&#34;&gt;解决
&lt;/h3&gt;&lt;p&gt;定义一个&lt;strong&gt;自定义分析器&lt;/strong&gt; &lt;code&gt;cjk_word = smartcn_tokenizer + lowercase&lt;/code&gt;(不带 Porter):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;analysis&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;analyzer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;cjk_word&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;custom&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;tokenizer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;smartcn_tokenizer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;lowercase&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;一个绕不开的坑:&lt;strong&gt;ES 不允许原地修改已有字段的分析器&lt;/strong&gt;;而且&lt;strong&gt;分析器属于静态 index settings,加它必须先 &lt;code&gt;_close&lt;/code&gt; 索引&lt;/strong&gt;。所以对现有索引,流程是:&lt;code&gt;_close&lt;/code&gt; → &lt;code&gt;PUT _settings&lt;/code&gt;(加分析器)→ &lt;code&gt;_open&lt;/code&gt; → 加一个新的子字段 &lt;code&gt;text.zh&lt;/code&gt;(用 &lt;code&gt;cjk_word&lt;/code&gt;)→ &lt;code&gt;_update_by_query&lt;/code&gt; 重新分词回填。新索引则在建表时就带上这个分析器和子字段。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;significant_text&lt;/code&gt; 改成在 &lt;code&gt;text.zh&lt;/code&gt; 上跑(配合 &lt;code&gt;source_fields&lt;/code&gt; 重分析原文)。&lt;/p&gt;
&lt;h3 id=&#34;附带收获换个显著性算法停用词噪声直接消失&#34;&gt;附带收获:换个显著性算法,停用词噪声直接消失
&lt;/h3&gt;&lt;p&gt;修英文的过程中,顺手对比了 &lt;code&gt;significant_text&lt;/code&gt; 的几种显著性算法(都没加停用词表,看纯算法效果):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;默认 JLH:  的 是 不 就 这 都 伊朗 也 个 claude 大 能 了 没 用 ai ...   ← 一堆停用词
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gnd:       伊朗 codex claude fifa 世界杯 霍尔木兹 mythos spcx 巴拉圭 fable opus ...  ← 全是真词
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;gnd&lt;/code&gt;(Google Normalized Distance)天生就压低无处不在的常见词&lt;/strong&gt;,效果远胜默认的 JLH。换成它之后,即使不维护停用词表,中文虚词(的/是/不/说/去)也自然消失了。这比靠停用词表&amp;quot;打地鼠&amp;quot;治本得多——停用词表反而留作 URL 碎片之类的廉价兜底。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;顺带一提:中文停用词的事实标准是 &lt;code&gt;goto456/stopwords&lt;/code&gt; 仓库(哈工大、百度等),但它们对 不/都/大 这类常见单字反而都漏收;而像&amp;quot;说/去/买&amp;quot;这种动词,任何停用词表都不会收(它们算内容词)。所以&lt;strong&gt;靠停用词表清噪声有天花板&lt;/strong&gt;,选对显著性算法才是关键。&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;经验-1&#34;&gt;经验
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;开箱即用&amp;quot;的封装会塞进你没料到的行为。&lt;/strong&gt; &lt;code&gt;smartcn&lt;/code&gt; 分析器顺手带了 Porter 词干器,在混排内容里就出问题。&lt;strong&gt;遇事先 &lt;code&gt;_analyze&lt;/code&gt;&lt;/strong&gt;,别猜。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分析器不能原地改&lt;/strong&gt;:多字段 + reindex(&lt;code&gt;_update_by_query&lt;/code&gt; 可原地重分词)。改静态分析设置还得先关索引。&lt;/li&gt;
&lt;li&gt;做&amp;quot;热词/显著词&amp;quot;这类功能,&lt;strong&gt;显著性算法(gnd vs JLH)对结果质量的影响,比停用词表大得多&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结几条可复用的经验&#34;&gt;总结:几条可复用的经验
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;升级会改默认行为。&lt;/strong&gt; 能跑的东西在小版本升级后坏掉,往往是某个默认开关变了(B2 那次是条件写)。升级后务必实测关键路径,滚动升级先升一台验证。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;报错信息常常误导。&lt;/strong&gt; &amp;ldquo;header not implemented&amp;rdquo; 像 checksum,其实是 &lt;code&gt;If-None-Match&lt;/code&gt;。用搜索 + 官方文档收敛假设,比埋头逐个试参数高效。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全局配置敌不过应用的显式设置。&lt;/strong&gt; JVM/SDK 层的 checksum 配置,被 ES 在 client builder 里覆盖了,怎么调都没用。排查时先搞清楚配置的优先级链。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;开箱即用&amp;quot;有代价。&lt;/strong&gt; smartcn 分析器图省事把 Porter 也带上了。封装隐藏了行为,&lt;code&gt;_analyze&lt;/code&gt; / &lt;code&gt;_verify&lt;/code&gt; 这类&amp;quot;把黑箱打开看一眼&amp;quot;的工具是排查利器。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;先准备好能恢复的备份再动手。&lt;/strong&gt; 尤其讽刺的是,有一次坏的恰恰是备份系统本身。&lt;/li&gt;
&lt;/ol&gt;
</description>
        </item>
        
    </channel>
</rss>
