如何压缩 JSON?

解读

在国内 CouchDB 面试中,面试官问“如何压缩 JSON”并不是想听你背诵 gzip 或 zlib 的 API,而是考察三层能力:

  1. 是否理解 CouchDB 的存储与传输分层——磁盘文件、HTTP 报文、Erlang 内部项;
  2. 能否把“压缩”与复制带宽、移动端离线同步、磁盘 I/O 这些真实痛点挂钩;
  3. 是否熟悉中国国内云环境(如阿里云 ECS 出网流量费、移动 4G/5G 高时延)下的成本与体验权衡。
    回答时要先界定“在哪一层压缩、压给谁看、压完会不会破坏 CouchDB 的语义”,再给出落地套路。

知识点

  • CouchDB 文件结构:.couch 文件本质追加写 B+ 树,内部已做字段级压缩(snappy),但仅针对文档内容,不压 HTTP。
  • Erlang 内置压缩erlang:term_to_binary/2 支持 {compressed, 9},CouchDB 3.x 默认对视图索引启用。
  • HTTP 传输压缩Accept-Encoding: gzip, deflatechttpd 模块处理,默认开启;国内移动弱网场景可降低 60% 流量。
  • 文档级预压缩:把 JSON 序列化后用 gzip+base64 再存回 {"_data":"H4sIAAAA..."},但会丢失视图索引能力,只能当附件 blob。
  • 中国云厂商计费:阿里云内网流量免费,公网出流量 0.8 元/GB;压缩直接决定月账单
  • 同步网关场景:PouchDB/CouchDB 双向同步,若文档平均 8 KB,压缩后可降到 2 KB,3G 网络下首屏时间缩短 40%

答案

我分三层回答:

  1. 存储层:CouchDB 的 .couch 文件已经对文档字段启用 snappy 压缩,DBA 无需干预;若视图索引过大,可在 local.ini 里把 view_index_compression = snappy 改成 zlib,压缩率提升 20%,但 CPU 上涨 10%,适合读多写少的国内政务云归档场景。
  2. 传输层chttpd 默认响应 Accept-Encoding: gzip,只要客户端带请求头即可;若用国内 CDN 做边缘加速,需勾选“智能压缩”,否则 CDN 会删除 Accept-Encoding 导致回源流量翻倍。
  3. 业务层:对于超大附件(如 5 M 的 JSON 日志),建议把原始 JSON 先 gzip 再当成附件上传,CouchDB 只存二进制 stub,拉取时通过 ?attachments=true 一次性带回,节省 70% 公网流量,同时不破坏主文档的索引与同步语义。

拓展思考

如果面试官继续追问“压缩后 CPU 飙高怎么调优”,可以补充:

  • erlang:system_monitor 抓 gzip 进程 mailbox,发现堆积立即调低 compression_level
  • 国内双 11 场景,可临时关闭视图压缩,把 CPU 让给写吞吐,节后再打开,通过 curl -X POST /_view_compaction/q10 手动触发;
  • 对移动 App,可在 PouchDB 侧先预压,上传时带 Content-Encoding: gzip,CouchDB 会透存再透传,实现端到端压缩,不额外耗服务器 CPU。