0. 什么時候該用“高階配置”?
- 復雜網絡/路由需求:自定義“健康節點”判定、權重路由、多租戶隔離。
- 替換 HTTP 棧:接入企業內網網關、打通自研代理/審計、細化超時/連接細節。
- 序列化治理:為超大 JSON、Bulk、查詢串做定制編碼/壓縮/過濾。
- 安全與合規:錯誤元數據(meta)里徹底脫敏,或加強敏感頭替換策略。
- 版本升級:在不一次性改完所有客戶端的前提下,先把服務端升到 8.x。
關于
Transport
的細節與擴展點,請參閱官方文檔的 Transport 部分。
1.ConnectionPool:連接池的“腦子”
職責:維護所有節點的 Connection
實例、失活/復活策略(resurrection)、池內更新。每個節點一個 Connection。
1.1 典型定制點
- 自定義復活策略:例如結合你自家的探活信號/熔斷器。
- 灰度/容災路由偏好:優先同城、讀多寫少集群分流。
1.2 示例:覆寫 markAlive
const { Client, ConnectionPool } = require('@elastic/elasticsearch')class MyConnectionPool extends ConnectionPool {markAlive (connection) {// 自定義探活打點/日志/熔斷恢復邏輯super.markAlive(connection)}
}const client = new Client({ConnectionPool: MyConnectionPool,cloud: { id: '<cloud-id>' },auth: { apiKey: 'base64EncodedKey' }
})
建議:把“節點角色/地域/租戶”等放進 connection.meta 或 headers,配合同層的
nodeFilter
/nodeSelector
做更細致的調度。
2.Connection:真實發起 HTTP 的“手”
職責:代表一個節點(URL、roles、自定義 headers…),并在其上執行實際 HTTP 請求。
想要替換默認 HTTP 客戶端(Node 核心實現)?覆寫 request
即可。
2.1 示例:覆寫 request
const { Client, BaseConnection } = require('@elastic/elasticsearch')class MyConnection extends BaseConnection {request (params, callback) {// 在這里接入你的 HTTP 實現 / 網關 / 審計// 需要調用 callback(err, response) 完成一次請求}
}const client = new Client({Connection: MyConnection,cloud: { id: '<cloud-id>' },auth: { apiKey: 'base64EncodedKey' }
})
實戰建議
- 統一注入鏈路 ID(X-Opaque-Id)、租戶頭、壓縮策略。
- 嚴格處理超時/重試與冪等性(只對讀/安全寫做自動重試)。
- 在
callback
寫好可觀測元數據(took、status、remoteAddr),方便日志聚合。
3.Serializer:性能與協議的“臉面”
職責:序列化/反序列化所有請求/響應,包含:
serialize(obj): string
——請求體編碼deserialize(json): any
——響應體解碼ndserialize(array): string
——Bulk 專用 NDJSONqserialize(object): string
——查詢參數編碼
3.1 示例:自定義 serialize
const { Client, Serializer } = require('@elastic/elasticsearch')class MySerializer extends Serializer {serialize (object) {// 例如:處理 BigInt、安全過濾、穩定鍵序return JSON.stringify(object)}
}const client = new Client({Serializer: MySerializer,cloud: { id: '<cloud-id>' },auth: { apiKey: 'base64EncodedKey' }
})
實戰建議
- Bulk 寫入走
ndserialize
,避免額外復制;控制行尾換行與內存峰值。 - 對查詢串(
qserialize
)可做白名單過濾與編碼規范化,防注入/超長。 - 熱路徑上注意逃逸創建與字符串拼接成本,必要時用生成器/緩沖區。
4.錯誤元數據里的敏感信息脫敏(Redaction)
當 HTTP 層拋出錯誤(如 ConnectionError
、TimeoutError
)時,客戶端會在錯誤對象上附帶 meta
,包含請求/響應等調試信息。為避免泄露憑證,客戶端默認做鍵名匹配 + 值替換的脫敏。
4.1 默認:{ type: 'replace' }
遞歸匹配常見敏感鍵名(大小寫不敏感),值替換為 "[redacted]"
。
const { Client } = require('@elastic/elasticsearch')
const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' } })try {await client.indices.create({ index: 'my_index' })
} catch (err) {console.log(err.meta.meta.request.options.headers.authorization) // "[redacted]"
}
4.2 擴展更多鍵名
const client = new Client({cloud: { id: '<cloud-id>' },auth: { apiKey: 'base64EncodedKey' },headers: { 'X-My-Secret-Password': 'shhh it\'s a secret!' },redaction: { type: 'replace', additionalKeys: ['x-my-secret-password'] }
})
4.3 徹底移除:{ type: 'remove' }
不打算用元數據?可以移除可選敏感來源,必需字段置 null
。
const client = new Client({cloud: { id: '<cloud-id>' },auth: { apiKey: 'base64EncodedKey' },redaction: { type: 'remove' }
})
4.4 關閉(僅本地調試):{ type: 'off' }
警告:不建議用于生產!
回退到 8.11.0 之前的行為(只在console.log
/JSON.stringify
時做基礎脫敏)。
5.遷移到 v8:兼容頭 + 分步升級
要讓 7.x 客戶端在不全量改造的情況下對接 8.x 服務器,可開啟兼容性頭:
客戶端會發送 Accept: application/vnd.elasticsearch+json; compatible-with=7
,請求/響應體遵循 7.x 語義。
開啟方式:設置環境變量
ELASTIC_CLIENT_APIVERSIONING=true
升級順序建議:
- 先升服務端到 8.x(已開啟兼容頭);
- 再逐步把客戶端升級到 8.x,移除兼容頭,按需使用新特性。
6.組合拳:高階定制樣板
const { Client, ConnectionPool, BaseConnection, Serializer } = require('@elastic/elasticsearch')// 1) Pool:灰度與熔斷
class MyPool extends ConnectionPool {markAlive (conn) { /* ...metrics... */ super.markAlive(conn) }
}// 2) Connection:接入企業網關 & 統一鏈路頭
class MyConn extends BaseConnection {request (params, cb) {// 自研 HTTP/代理/審計邏輯// 注入 X-Opaque-Id / 租戶 / 重試策略}
}// 3) Serializer:安全序列化 + Bulk NDJSON
class MySer extends Serializer {serialize (o) { return JSON.stringify(o) }ndserialize (arr) { /* 按需優化 */ return super.ndserialize(arr) }
}const client = new Client({ConnectionPool: MyPool,Connection: MyConn,Serializer: MySer,cloud: { id: '<cloud-id>' },auth: { apiKey: 'base64EncodedKey' },redaction: { type: 'replace', additionalKeys: ['x-tenant-secret'] }
})
7.落地與測試建議
- 契約優先:給
request(params, cb)
、serialize/deserialize
寫契約測試,鎖定邊界行為。 - 壓測與火焰圖:在 Bulk/Scroll/Async Search 場景做基準,盯CPU/內存峰值與 GC。
- 混沌/容災:注入網絡故障(限速、丟包、半開),驗證復活/重試策略。
- 日志與脫敏:任何落盤/外發日志前,確保已做 redaction。
小結
- 用 ConnectionPool/Connection/Serializer 三件套,能把客戶端“改造成你的客戶端”。
- Redaction 是生產必配項:默認
replace
+additionalKeys
足以覆蓋大多數合規需求。 - v8 遷移優先升服務端,打開兼容頭,再慢慢升級客戶端,風險最小。
有具體的改造目標(比如“按租戶分流 + 自研代理 + 自定義序列化”)嗎?把你的約束和目標告訴我,我可以基于上面的骨架給你一份可直接運行的工程模板與測試清單。