概述
在 UModel 系統中,實體(Entity)是 EntitySet 的具體執行個體,代表系統中的各種資來源物件,如服務、主機、Pod 等。本文檔詳細介紹實體的資料格式、寫入方法和最佳實務。
關於 UModel、EntitySet、Entity 的詳細概念,請參見EntityStore 簡介。
實體資料格式
實體資料通過 SLS Log 協議寫入到 EntityStore的${workspace}__entity日誌庫中。每個實體記錄包含系統欄位和自訂欄位兩部分。
系統欄位
欄位名 | 類型 | 是否必須 | 樣本 | 說明 |
| string | 是 | apm, k8s, acs | 實體所屬的域,用於資料隔離和分類 |
| string | 是 | apm.service, k8s.pod | 實體類型,定義實體的分類 |
| string | 是 | 391274C9A1D369FB5222E273D02B81B8 | 實體唯一識別碼,128位hex值 |
| string | 否(預設Update) | Create, Update, Expire, Delete, Revise | 操作類型,控制實體的生命週期 |
| int | 否 | 1700000000 | 首次觀察時間,秒級時間戳記 |
| int | 是 | 1700000001 | 最近觀察時間,秒級時間戳記 |
| int | 否(預設3600) | 3600 | 存活時間,秒為單位 |
欄位說明
__entity_id__建置規則
標準格式:128位十六進位字串。
建議產生方法:對主鍵使用 MD5 或雙重 xxhash 函數。
兜底處理(不建議):如不符合128位hex格式,內部自動進行 xxhash 轉換。
時間欄位管理
__first_observed_time__:實體首次被發現的時間,一旦設定通常不變。__last_observed_time__:實體最近一次被觀察的時間,每次更新時更新。實體可見時間範圍:
[FirstObservedTime, LastObservedTime + KeepAliveSeconds]。說明:若不確定實體的首次被發現時間,可以不填
__first_observed_time__此欄位。EntityStore 在寫入時會自動使用第一次接收的__last_observed_time__的值作為__first_observed_time__的值。
自訂欄位
除系統欄位外,可以添加 EntitySet 中定義的各類 Field 欄位:
{
"__domain__": "apm",
"__entity_type__": "apm.service",
"__entity_id__": "391274C9A1D369FB5222E273D02B81B8",
"__method__": "Update",
"__last_observed_time__": 1700000001,
"__keep_alive_seconds__": 3600,
"service_name": "user-service",
"version": "v1.2.3",
"cluster": "production",
"labels": {
"env": "prod",
"team": "backend"
}
}JSON 欄位注意事項
⚠️ 重要:對於JSON格式的欄位(如labels、annotations),必須確保JSON對象中的鍵按字母順序序列化,避免頻繁重建同一實體的索引。
實體時間區間與查詢覆蓋機制
時間區間基礎概念
實體在 EntityStore 中具有明確的時間可見範圍,查詢引擎只有在查詢時間視窗與實體可見時間產生交集時,才會返回該實體。
實體可見時間計算
實體的可見時間範圍由以下公式確定:
注意:實體可見時間範圍、和查詢時間範圍遵循左閉右開原則。
實體狀態 | 可見時間範圍 | 說明 |
正常狀態 |
| 包含KeepAlive延長時間 |
已到期狀態(顯示調用Expire後) |
| 不包含KeepAlive延長時間 |
已刪除狀態 | 無可見時間 | 任何查詢都不返回 |
時間交集判斷規則
查詢引擎使用以下規則判斷實體是否應該被返回:
查詢返回實體 = 查詢時間視窗 ∩ 實體可見時間具體判斷邏輯:
if (QueryEndTime >= EntityFirstObservedTime &&
QueryStartTime <= EntityVisibleEndTime) {
返回實體
} else {
不返回實體
}寫入方法詳解
Create - 建立實體
使用情境:明確建立新實體時使用,如監聽到Pod建立事件。
行為邏輯:
若實體已存在:不做任何操作。
若實體不存在:建立新實體,覆蓋所有欄位。
樣本:
{
"__domain__": "k8s",
"__entity_type__": "k8s.pod",
"__entity_id__": "abc123...",
"__method__": "Create",
"__first_observed_time__": 1700000000,
"__last_observed_time__": 1700000000,
"pod_name": "web-app-123",
"namespace": "default"
}Update - 更新實體
使用情境:大部分情境使用,包括定期全量更新、累加式更新等。
行為邏輯:
覆蓋除
__first_observed_time__外的所有欄位。對於
__first_observed_time__:若實體已存在:不修改原值。
若實體不存在且事件包含該欄位:使用事件中的值。
若實體不存在且事件不包含該欄位:使用
__last_observed_time__的值。
樣本:
{
"__domain__": "apm",
"__entity_type__": "apm.service",
"__entity_id__": "def456...",
"__method__": "Update",
"__last_observed_time__": 1700000100,
"service_name": "payment-service",
"status": "running",
"instance_count": 3
}Expire - 實體到期
使用情境:實體明確被刪除時使用,如監聽到Pod刪除事件。
行為邏輯:
標記實體的
__deleted__為true。更新
__last_observed_time__。查詢時不再附加計算KeepAlive時間。
時間範圍變化:
到期前:
[FirstObservedTime, LastObservedTime + KeepAliveSeconds]。到期後:
[FirstObservedTime, LastObservedTime]。
樣本:
{
"__domain__": "k8s",
"__entity_type__": "k8s.pod",
"__entity_id__": "abc123...",
"__method__": "Expire",
"__last_observed_time__": 1700000200
}Delete - 刪除實體(謹慎使用)
使用情境:功能被禁用或需要實體在全周期都不可見的情境。
行為邏輯:
直接從底層資料庫刪除實體記錄。
任何時間段的查詢都無法找到該實體。
⚠️ 注意:這是無法復原操作,請謹慎使用。
Revise - 訂正實體(謹慎使用)
使用情境:資料寫錯需要強制訂正時使用,通常與Delete組合使用。
行為邏輯:
直接覆蓋所有欄位,包括
__first_observed_time__。不考慮原有資料狀。
寫入最佳實務
推薦方式:增量事件 + 定期全量
核心思路是以增量事件為主,定期全量寫入作為資料校對和容錯機制。
配置建議:
增量事件:即時或近即時寫入。
定期全量:頻率建議1小時及以上。
KeepAlive時間:根據業務需求設定,通常10分鐘到1小時。
說明:KeepAlive時間根據上報周期進行調整,建議不低於1個上報周期。此外定期上報周期建議不低於5分鐘,避免頻繁更新影響查詢效能。
實際情境應用
情境1:雲產品資源同步
使用RMC提供的增量+全量同步機制:
增量事件處理:
監聽資源建立事件 -> 使用Create方法
監聽資源更新事件 -> 使用Update方法
監聽資源刪除事件 -> 使用Delete方法
全量事件處理:
定期全量同步 -> 統一使用Update方法
KeepAlive 根據業務需求靈活配置
// 雲資源建立事件
{
"__domain__": "acs",
"__entity_type__": "acs.ecs.instance",
"__entity_id__": "i-bp1234567890",
"__method__": "Create",
"__first_observed_time__": 1700000000,
"__last_observed_time__": 1700000000,
"__keep_alive_seconds__": 86400,
"instance_id": "i-bp1234567890",
"instance_name": "web-server-01",
"instance_type": "ecs.c6.large",
"status": "Running"
}情境2:Agent採集資產資料
使用LoongCollector採集K8s資產資料的模式:
啟動時全量採集:
進程啟動時採集一次全量資料
後續每1小時採集一次全量資料
使用Update方法寫入
增量事件訂閱:
訂閱K8s API事件
根據事件類型轉換為對應的寫入方法
即時寫入增量變化
// K8s Pod全量採集
{
"__domain__": "k8s",
"__entity_type__": "k8s.pod",
"__entity_id__": "pod-web-app-123",
"__method__": "Update",
"__last_observed_time__": 1700000400,
"__keep_alive_seconds__": 3600,
"pod_name": "web-app-123",
"namespace": "production",
"node_name": "worker-01",
"pod_ip": "10.0.1.100",
"labels": {
"app": "web-app",
"version": "v1.0"
}
}不推薦的寫入方式
純事件管理
問題:需要查詢所有時間段資料,效能較差。
情境:僅在實體生命週期完全由事件驅動時考慮。
純全量寫入
問題:資料量大,實體發現延遲高。
建議:如無法識別增量,控制寫入頻率為10分鐘或1小時。
寫入介面
實體寫入通過SLS Log協議進行,寫入到對應workspace的${workspace}__entity日誌庫即可。後台會自動同步到 EntityStore 儲存引擎。
支援的寫入方式:
ETL轉換寫入:通過資料加工任務轉換和寫入。
ScheduledSQL計算寫入:通過定時SQL查詢計算並寫入。
API直接上報:通過SDK或API直接寫入日誌庫。
注意事項
資料一致性:確保同一實體的
__domain__、__entity_type__、__entity_id__組合在整個生命週期內保持一致。時間戳記管理:所有時間欄位使用秒級 Unix 時間戳記,確保時區一致性。
方法選擇:根據實際業務情境選擇合適的 Method,避免不必要的Delete操作。
效能考慮:合理設定 KeepAlive 時間,平衡資料保留需求和查詢效能。
JSON格式:確保 JSON 欄位的索引值按字母順序序列化,提高索引效率。
實體數量:建議單個 EntitySet 的實體數量不超過1萬,系統中整體實體數量不超過100萬,避免影響查詢效能和寫入。