在 ABP VNext 中集成 Serilog:打造可觀測、結構化日志系統

🚀 在 ABP VNext 中集成 Serilog:打造可觀測、結構化日志系統


📚 目錄

  • 🚀 在 ABP VNext 中集成 Serilog:打造可觀測、結構化日志系統
    • 1. 為什么要使用結構化日志? 🤔
    • 2. 核心集成步驟 🛠
      • 2.1 流程圖示例
    • 3. NuGet 包安裝 📦
    • 4. appsettings.json 配置 📝
    • 5. Program.cs 全局日志初始化 💻
      • 5.1 代碼流程圖
    • 6. ABP 模塊注冊 🏗
    • 7. 上下文信息添加 🧩
      • 7.1 UseAbpSerilogEnrichers() 自動插入
      • 7.2 LogContext.PushProperty 自定義屬性
    • 8. 對接平臺:Seq & ELK & Grafana Loki 🌐
      • 8.1 部署 Seq(推薦開發階段)
      • 8.2 部署 ELK(推薦生產環境)
        • 8.2.1 在 Kibana 中創建 Index Pattern 🔍
      • 8.3 對接 Grafana Loki(可選)🔗
    • 9. 總結 📋
    • 📎 推薦閱讀 📚


1. 為什么要使用結構化日志? 🤔

相比于簡單的文本日志,結構化日志有以下優勢:

  • ? 傳統文本日志無法根據 TraceId、UserId 等字段方便地檢索
  • ? 無法像 SQL 那樣對日志字段進行過濾與聚合
  • ? 不易在可視化平臺(如 Kibana、Seq、Grafana Loki)上進行聯動分析

而 Serilog 以原生的 JSON 日志形式輸出,能夠輕松處理上下文、分析調用鏈,方便與 ELK / Seq / Loki 等平臺集成,做到精準定位故障點。


2. 核心集成步驟 🛠

步驟內容
1??安裝 Volo.Abp.AspNetCore.Serilog
2??配置 Serilog Sink(Console、File、Seq、Elasticsearch、Loki)
3??Program.cs 中初始化 Serilog
4??在 ABP 模塊中啟用 UseAbpSerilogEnrichers() 插入上下文

2.1 流程圖示例

啟動項目
讀取 appsettings.json 中 Serilog 配置
Program.cs 中 UseSerilog 初始化 Logger
創建 ABP 應用并調用 UseAbpSerilogEnrichers
HTTP 請求進入 → Enrichers 插入上下文
業務代碼調用 ILogger 輸出日志
Serilog 將日志寫入 Console/File/Seq/ES/Loki
  • 通過 “Enrichers” 階段,可以自動將 TraceId、UserId、MachineName 等信息注入到每條日志。

3. NuGet 包安裝 📦

在項目根目錄下執行以下命令,添加所需依賴包。為了避免版本不一致,建議指定版本號:

dotnet add package Volo.Abp.AspNetCore.Serilog 
dotnet add package Serilog.Sinks.Console          
dotnet add package Serilog.Sinks.File              
dotnet add package Serilog.Sinks.Seq               
dotnet add package Serilog.Sinks.Elasticsearch     # 如想支持 Grafana Loki:
dotnet add package Serilog.Sinks.Grafana.Loki      

4. appsettings.json 配置 📝

appsettings.json 文件中,添加或修改 Serilog 節點,如下所示:

{"Serilog": {"Using": ["Serilog.Sinks.Console","Serilog.Sinks.File","Serilog.Sinks.Seq","Serilog.Sinks.Elasticsearch","Serilog.Sinks.Grafana.Loki"],"MinimumLevel": {"Default": "Information","Override": {"Microsoft": "Warning","Microsoft.EntityFrameworkCore": "Error","Volo.Abp": "Information"}},"WriteTo": [{"Name": "Console"},{"Name": "File","Args": {"path":                 "Logs/log-.log","rollingInterval":      "Day","retainedFileCountLimit": 14,"fileSizeLimitBytes":   104857600,"buffered":             true,"flushToDiskInterval":  "00:00:05"}},{"Name": "Seq","Args": {"serverUrl": "http://localhost:5341"}},{"Name": "Elasticsearch","Args": {"nodeUris":                  "http://localhost:9200","indexFormat":               "myapp-logs-{0:yyyy.MM.dd}","autoRegisterTemplate":      true,"autoRegisterTemplateVersion": "ESv7","numberOfReplicas":          1,"numberOfShards":            5,"batchPostingLimit":         50,"period":                    "00:00:05","failureCallback":           "e => Console.WriteLine(\"Unable to submit event to Elasticsearch: \" + e.Message)"}},{"Name": "GrafanaLoki","Args": {"uri":                 "http://localhost:3100/loki/api/v1/push","batchPostingLimit":   50,"period":              "00:00:05","labels":              "{\"Application\":\"MyAbpApp\",\"Environment\":\"${env:ASPNETCORE_ENVIRONMENT}\"}"}}],"Enrich": ["FromLogContext","WithMachineName","WithThreadId","WithEnvironmentName"]}
}
  • Using:要加載的 Sink 包列表,包括 Console、File、Seq、Elasticsearch、Grafana Loki。
  • MinimumLevel:全局最低日志級別及對各命名空間的 Override。
  • WriteTo:各個輸出通道的配置:
    • 📟 Console:控制臺直接輸出,適合開發與容器模式下采集標準輸出。
    • 📂 File:寫入本地文件,rollingInterval: Day 按天滾動;retainedFileCountLimit: 14 最多保留 14 天日志;fileSizeLimitBytes: 100MB,超出則滾動。
    • 📊 Seq:訪問地址為 http://localhost:5341 的本地 Seq 服務。
    • 🔍 Elasticsearch:連接到 http://localhost:9200,索引名稱按天命名;批量發送 50 條 / 5 秒;失敗回調打印到控制臺。
    • 📈 GrafanaLoki:連接本地 Loki(端口 3100)并打上標簽,一旦在 Grafana 中按標簽篩選,方便定位。
  • Enrich:注入常見上下文字段(如 TraceId、MachineName、ThreadId、Environment)。

Tip:如需在開發/生產環境區分配置,可分別在 appsettings.Development.jsonappsettings.Production.json 中覆蓋 MinimumLevelWriteTo 節點。例如:

  • Development:將 MinimumLevel.Default 設置為 Debug,僅啟用 Console Sink;
  • Production:將 MinimumLevel.Default 設置為 Information,啟用 File、Seq、Elasticsearch、Loki Sink;并關閉 Console 輸出以減少 I/O 壓力。

5. Program.cs 全局日志初始化 💻

Program.cs 文件里,使用 Serilog 提供的“Bootstrap Logger”+“配置讀取”模版,示例如下:

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Volo.Abp.Serilog;namespace MyAbpApp
{public class Program{public static async Task Main(string[] args){// 1. 創建 Bootstrap Logger(只輸出到 Console,用于捕獲最早期的日志)Log.Logger = new LoggerConfiguration().MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning).WriteTo.Console().CreateBootstrapLogger();try{// 2. 構建 Host 并讀取 appsettings.json 中的 Serilog 配置var builder = WebApplication.CreateBuilder(args);builder.Host.UseSerilog((ctx, services, config) =>{config.ReadFrom.Configuration(ctx.Configuration)    // 讀取 appsettings.json 的 Serilog 設置.ReadFrom.Services(services)                  // 讀取 DI 容器中注冊的 ILogEventEnricher.Enrich.FromLogContext()                      // 從 LogContext 拉取附加屬性.Enrich.WithProperty("Application", "MyAbpApp").Enrich.WithProperty("Environment", ctx.HostingEnvironment.EnvironmentName);});// 3. 添加 ABP 應用及所需模塊builder.Services.AddApplication<MyAbpAppModule>();// 4. 構建應用var app = builder.Build();// 5. 注入 Serilog Enrichers(TraceId、UserId、TenantId 等)app.UseAbpSerilogEnrichers();// 6. 初始化 ABP 模塊(包括 Routing、Authentication、Authorization 等)await app.InitializeApplicationAsync();// 7. 啟動 HTTP 服務并阻塞await app.RunAsync();}catch (Exception ex){// 8. 捕獲主機啟動時的異常并記錄 Fatal 日志Log.Fatal(ex, "Application start-up failed");Environment.ExitCode = 1;}finally{// 9. 應用退出時刷新并關閉日志Log.CloseAndFlush();}}}
}

5.1 代碼流程圖

Main 方法開始
創建 Bootstrap Logger
構建 WebHostBuilder
UseSerilog 讀取配置并初始化 Logger
Services.AddApplication
Build 應用
UseAbpSerilogEnrichers 注入上下文
InitializeApplicationAsync 初始化 ABP 模塊
RunAsync 啟動 Kestrel 并監聽請求
請求到達 → Enrichers 插入 TraceId 等
業務代碼調用 ILogger 輸出日志 → Serilog 寫入 Sink
  • 該圖展示了 Program.cs 中從 Main 開始,到最終應用啟動并接收請求,日志如何一步步初始化并插入上下文的執行路徑。

6. ABP 模塊注冊 🏗

MyAbpAppModule.cs 中聲明所需的依賴模塊,例如:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.DistributedEventBus;
using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement;namespace MyAbpApp
{[DependsOn(typeof(AbpAspNetCoreSerilogModule),    // Serilog 集成模塊typeof(AbpAspNetCoreMvcModule),        // MVC/Web API 基礎模塊typeof(AbpBackgroundWorkersModule),    // 后臺任務模塊(示例)typeof(AbpDistributedEventBusModule),  // 分布式事件總線模塊(示例)typeof(AbpTenantManagementModule)      // 多租戶管理模塊(如需多租戶場景))]public class MyAbpAppModule : AbpModule{public override void OnApplicationInitialization(ApplicationInitializationContext context){var logger = context.ServiceProvider.GetRequiredService<ILogger<MyAbpAppModule>>();logger.LogInformation("🔥 ABP 模塊已啟動!");}public override void OnApplicationShutdown(ApplicationShutdownContext context){var logger = context.ServiceProvider.GetRequiredService<ILogger<MyAbpAppModule>>();logger.LogInformation("💤 ABP 模塊已關閉!");}}
}
  • 說明
    1. AbpAspNetCoreSerilogModule 會將 ABP 框架內部的日志重定向到 Serilog。
    2. 如果您的業務需要后臺任務或分布式事件,請在 DependsOn 一并引入對應模塊。
    3. 如果項目啟用多租戶,一定要引入 AbpTenantManagementModule 等租戶相關模塊。
    4. OnApplicationInitialization 中寫一條“ABP 模塊已啟動”日志方便確認模塊加載成功;在 OnApplicationShutdown 中寫一條“ABP 模塊已關閉”日志方便確認優雅退出。

7. 上下文信息添加 🧩

7.1 UseAbpSerilogEnrichers() 自動插入

Program.cs 中調用 app.UseAbpSerilogEnrichers(); 后,Serilog 會自動注入以下常見上下文字段到每條日志中:

  • 🔗 TraceId:分布式鏈路追蹤 ID(需配合 OpenTelemetry/Jaeger 等鏈路追蹤服務)
  • 👤 UserId、UserName:當前登錄用戶信息(需在請求上下文中有認證信息)
  • 🏷? TenantId:當前多租戶系統的租戶 ID(如啟用了多租戶模塊)
  • 🖥? MachineName:主機名稱(適用于集群調試)
  • 🧵 ThreadId:線程 ID(方便定位多線程日志)
  • 🌐 Environment:部署環境(如 Development、Production)

注意UseAbpSerilogEnrichers() 必須放在 UseRouting() 之后、UseAuthentication() 之前;如果您使用 ABP 腳手架模板,則無需手動調用中間件順序,InitializeApplicationAsync() 已自動處理。

7.2 LogContext.PushProperty 自定義屬性

在業務代碼里,如果需要在單次請求或某個操作中,對特定實體(如 Order)添加自定義屬性,可以使用 LogContext.PushProperty(...),示例如下:

using Serilog;
using Serilog.Context;
using Microsoft.Extensions.Logging;public class OrderService
{private readonly ILogger<OrderService> _logger;public OrderService(ILogger<OrderService> logger){_logger = logger;}public void ProcessOrder(Order order){// 在這個 using 塊內,所有日志都會帶上 OrderId 屬性using (LogContext.PushProperty("OrderId", order.Id)){_logger.LogInformation("? Processing order {@Order}", order);// … 其它業務邏輯_logger.LogWarning("?? Order {@Order} took too long to process", order);}}
}
  • 說明
    1. LogContext.PushProperty("OrderId", order.Id) 會在當前上下文中將 OrderId 寫入所有后續日志。
    2. 使用 {@Order} 這種序列化寫法,會把 Order 對象的所有字段寫到 JSON 中,方便在 ES/Kibana/Loki 中查看結構化數據。
    3. 在控制臺或日志平臺中,該條日志會像:
      {"Timestamp": "2025-05-31T20:00:00.0000000Z","Level": "Information","MessageTemplate": "? Processing order {@Order}","Properties": {"OrderId": 12345,"Order": { "Id": 12345, "Amount": 99.99, "CustomerId": 67890 },"TraceId": "abcdef1234567890","UserId": 42,"TenantId": 1,"MachineName": "server01","ThreadId": 12,"Environment": "Production"}
      }
      

8. 對接平臺:Seq & ELK & Grafana Loki 🌐

8.1 部署 Seq(推薦開發階段)

docker run -d \-p 5341:80 \-v seq_data:/data \datalust/seq
  • 說明
    1. -p 5341:80 將容器 80 端口映射到宿主機 5341 端口;訪問地址為 http://localhost:5341
    2. -v seq_data:/data 掛載一個 Docker 卷,用于持久化 Seq 數據;容器重啟后數據依然保留。
    3. 啟動后,可在 Seq Web 界面里創建 Dashboard,使用篩選條件(如 @l = "Error"@t >= "2025-05-01")進行日志定位。

8.2 部署 ELK(推薦生產環境)

創建一個 docker-compose.yml 文件,內容如下:

version: '3.7'volumes:es_data:kibana_data:services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0container_name: elasticsearchenvironment:- node.name=es-node-1- discovery.type=single-node- xpack.security.enabled=false- ES_JAVA_OPTS=-Xms1g -Xmx1gvolumes:- es_data:/usr/share/elasticsearch/dataports:- 9200:9200kibana:image: docker.elastic.co/kibana/kibana:7.17.0container_name: kibanaenvironment:- ELASTICSEARCH_HOSTS=http://elasticsearch:9200volumes:- kibana_data:/usr/share/kibana/dataports:- 5601:5601depends_on:- elasticsearch

運行:

docker-compose up -d
  • 說明
    1. Elasticsearch
      • 掛載 es_data 卷用以持久化數據;
      • 設置 JVM 堆大小為 1G(ES_JAVA_OPTS=-Xms1g -Xmx1g),生產環境可根據節點內存調整;
      • 關閉 X-Pack 安全認證方便本地測試;
    2. Kibana
      • 指定 ELASTICSEARCH_HOSTS 以連接 Elasticsearch;
      • 掛載 kibana_data 用于持久化 Kibana 配置;
      • 啟動后訪問 http://localhost:5601 即可登錄;
8.2.1 在 Kibana 中創建 Index Pattern 🔍
  1. 打開 Kibana → 左側菜單 “Management” → “Index Patterns” → “Create index pattern”。
  2. 在 “Index pattern name” 中輸入 myapp-logs-*,點擊 “Next step”。
  3. 選擇時間字段(如 @timestamp)后點擊 “Create index pattern”。
  4. 在 “Discover” 頁面就能看到所有符合 myapp-logs-2025.05.XX 格式的索引,日志字段會以 JSON 形式展示,可以按字段進行過濾、排序、聚合。

提示:為了更直觀地展示 Kibana 中的日志分組和聚合效果,可以創建一個簡單的 Dashboard,比如“日志級別分布圖”、“每小時錯誤請求數統計”等。這樣在生產環境排查問題時,更加快捷。

8.3 對接 Grafana Loki(可選)🔗

如果您使用 Grafana Loki 作為日志收集平臺,可參考以下步驟:

  1. 部署 Loki

    • 推薦使用 Loki 官方提供的 docker-compose.yml 或者 Helm Chart。
    • 簡單示例(僅做測試用):
      version: '3.7'
      services:loki:image: grafana/loki:2.7.1container_name: lokicommand: -config.file=/etc/loki/local-config.yamlports:- 3100:3100promtail:image: grafana/promtail:2.7.1container_name: promtailvolumes:- /var/log:/var/log- ./promtail-config.yaml:/etc/promtail/config.yamlcommand: -config.file=/etc/promtail/config.yaml
      
    1. promtail-config.yaml 中,配置讀取應用輸出到標準輸出(Console Sink)的日志,并推送到 Loki。
    2. 在 Grafana 中添加 Loki 數據源,創建 Dashboard 時選擇 Loki 數據源即可查詢 MyAbpApp 相關日志。
  2. GrafanaLoki Sink 配置示例
    已在第四節的 appsettings.json 中給出完整配置。再次回顧重點字段:

    {"Name": "GrafanaLoki","Args": {"uri": "http://localhost:3100/loki/api/v1/push","batchPostingLimit": 50,"period": "00:00:05","labels": "{\"Application\":\"MyAbpApp\",\"Environment\":\"Production\"}"}
    }
    
    • uri:Loki 的 Push API 地址;
    • batchPostingLimitperiod:控制批量推送頻率;
    • labels:為日志打上標簽,便于在 Grafana 中按標簽篩選。

注意:在容器化環境下,將 uri 指向 Loki Service(如 http://loki:3100/loki/api/v1/push),不要使用 localhost


9. 總結 📋

  • 🚀 性能

    • 支持 bufferedflushToDiskInterval 控制文件寫入 IO,平衡延遲與吞吐;
    • Elasticsearch Sink 中可配置 batchPostingLimitperiod,避免過于頻繁的小批量請求。
  • 📈 規模

    • 支持日志按天滾動(rollingInterval: Day)和限制單文件大小(fileSizeLimitBytes),通過 retainedFileCountLimit 最多保留 14 天歷史,防止磁盤耗盡。
  • 🎨 可視化

    • 結構化 JSON 日志讓 Seq/Kibana/Loki 能以字段形式展示,可按字段、日期、級別精準搜索和聚合統計,大幅提升故障排查效率。
  • 🔧 可配置

    • 通過 appsettings.Development.jsonappsettings.Production.json 差異化配置,可在不同環境靈活切換最小日志級別與輸出通道。
    • 支持自定義 Enrichers 和 Sink,能夠將任意業務上下文(如 OrderId、ProductId、TraceId 等)注入到日志中。
  • 🐳 容器化注意

    • 如果服務跑在 Docker 或 Kubernetes,推薦保留 Console Sink 輸出,通過容器平臺日志采集(如 Fluentd、Filebeat、堆棧驅動)統一收集。
    • 若仍需寫入日志文件,請確保掛載 Volume 以避免容器磁盤耗盡。
    • 根據目標平臺(Seq、Elasticsearch、Loki)是否開啟安全認證,需在對應 Sink 的 Args 中添加憑證信息(用戶名、密碼或 API Key)。

📎 推薦閱讀 📚

  • ABP Serilog 模塊文檔
  • Serilog 官方文檔
  • Seq 可視化平臺
  • Grafana Loki 文檔

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83574.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83574.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83574.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

API異常信息如何實時發送到釘釘

#背景 對于一些重要的API&#xff0c;開發人員會非常關注API有沒有報錯&#xff0c;為了方便開發人員第一時間獲取錯誤信息&#xff0c;我們可以使用插件來將API報錯實時發送到釘釘群。 接下來我們就來實操如何實現 #準備工作 #創建釘釘群 如果已有釘釘群&#xff0c;可以跳…

Stone 3D新版本發布,添加玩家控制和生物模擬等組件,增強路徑編輯功能,優化材質編輯

后續版本號改為構建日期加小版本&#xff0c;所以最新版本為20250603.01 功能更新如下&#xff1a; 1. 改寫fps-controls組件&#xff0c;簡化游戲應用的創建&#xff0c;你只需要一個場景glb&#xff0c;然后給Scene節點添加fps-controls組件&#xff0c;即可完成一個第一人…

【C++11】折疊引用和完美轉發

目錄 一. 前言二. 引用折疊引用折疊的規則 三. 完美轉發完美轉發適用場景完美轉發底層實現思考1思考2 一. 前言 在函數傳參時&#xff0c;如果想保持某個參數的屬性不改變&#xff0c;需要完美轉發&#xff0c;而完美轉發的實現需要折疊引用的幫助 二. 引用折疊 在語法上&am…

Vue 樹狀結構控件

1、效果圖如下所示&#xff1a; 2、網絡請求的數據結構如下&#xff1a; 3、新建插件文件&#xff1a;menu-tree.vue&#xff0c;插件代碼如下&#xff1a; <template><div class"root"><div class"parent" click"onParentClick(pare…

洛谷P12610 ——[CCC 2025 Junior] Donut Shop

題目背景 Score: 15. 題目描述 The owner of a donut shop spends the day baking and selling donuts. Given the events that happen over the course of the day, your job is to determine the number of donuts remaining when the shop closes. 輸入格式 The first …

數據挖掘頂刊《IEEE Transactions on Knowledge and Data Engineering》2025年5月研究熱點都有些什么?

本推文對2025年5月出版的數據挖掘領域國際頂級期刊《IEEE Transactions on Knowledge and Data Engineering》進行了分析&#xff0c;對收錄的62篇論文的關鍵詞與研究主題進行了匯總&#xff0c;并對其中的研究熱點進行了深入分析&#xff0c;希望能為相關領域的研究人員提供有…

華為OD機試真題——最小的調整次數/特異性雙端隊列(2025B卷:100分)Java/python/JavaScript/C++/C語言/GO六種最佳實現

2025 B卷 100分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C++、C語言、GO六種語言的最佳實現方式! 2025華為OD真題目錄+全流程解析/備考攻略/經驗分享 華為OD機試真題《最小的調整次數/特異性雙端…

2024年ESWA SCI1區TOP,自適應學習灰狼算法ALGWO+無線傳感器網絡覆蓋優化,深度解析+性能實測

目錄 1.端午快樂2.摘要3.灰狼算法GWO原理4.改進策略5.結果展示6.參考文獻7.代碼獲取8.讀者交流 1.端午快樂 今天端午節&#xff0c;祝各位朋友端午安康&#xff0c;闔家平安&#xff01; 2.摘要 無線傳感器網絡&#xff08;WSNs&#xff09;是一種被廣泛應用的新興技術&…

ADI硬件筆試面試題型解析下

本專欄預計更新60期左右。當前第17期-ADI硬件. ADI其硬件工程師崗位的招聘流程通常包括筆試和多輪技術面試,考察領域涵蓋模擬電路設計、數字電路、半導體器件和信號處理等。 本文通過分析平臺上的信息,匯總了ADI硬件工程師的典型筆試和面試題型,并提供詳細解析和備考建議,…

SpringCloud 分布式鎖Redisson鎖的重入性與看門狗機制 高并發 可重入

可重入 Redisson 的鎖支持 可重入性&#xff0c;這意味著同一個線程在獲取鎖后&#xff0c;如果再次嘗試獲取該鎖&#xff0c;它可以成功地獲得鎖&#xff0c;而不會被阻塞。 每次一個線程成功獲取鎖后&#xff0c;它的持有次數會增加。當線程再次獲取該鎖時&#xff0c;Redi…

Java 中 Redis 過期策略深度解析(含拓展-redis內存淘汰策略列舉)

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點睡覺 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 文章目錄 Java 中 Redis 過期策略深度解析一、Redis 過…

Flutter - 原生交互 - 相機Camera - 01

環境 Flutter 3.29 macOS Sequoia 15.4.1 Xcode 16.3 集成 Flutter提供了camera插件來拍照和錄視頻&#xff0c;它提供了一系列可用的相機&#xff0c;并使用特定的相機展示相機預覽、拍照、錄視頻。 添加依賴 camera: 提供使用設備相機模塊的工具path_provider: 尋找存儲圖…

基于 Amazon Q Developer CLI 和 Amazon Bedrock Knowledge Bases 實現智能問答系統

1. 引言 傳統企業通常將常見問題&#xff08;FAQ&#xff09;發布在網站上&#xff0c;方便客戶自助查找信息。然而&#xff0c;隨著生成式 AI 技術的迅速發展與商業滲透&#xff0c;這些企業正積極探索構建智能問答系統的新途徑。這類系統不僅能顯著提升客戶體驗&#xff0c;…

Go 為何天生適合云原生?

當前我們正處在 AI 時代&#xff0c;但是在基礎架構領域&#xff0c;仍然處在云原生時代。云原生仍然是當前時代的風口之一。作為一個 Go 開發者&#xff0c;職業進階的下一站就是學習云原生技術。作為 Go 開發者學習云原生技術有得天獨厚的優勢&#xff0c;這是因為 Go 天生適…

Mac查看MySQL版本的命令

通過 Homebrew 查看&#xff08;如果是用 Homebrew 安裝的&#xff09; brew info mysql 會顯示你安裝的版本、路徑等信息。 你的終端輸出顯示&#xff1a;你并沒有安裝 MySQL&#xff0c;只是查詢了 brew 中的 MySQL 安裝信息。我們一起來看下重點&#xff1a; &#x1f9fe…

Kafka ACK機制詳解:數據可靠性與性能的權衡之道

在分布式消息系統中&#xff0c;消息確認機制是保障數據可靠性的關鍵。Apache Kafka 通過 ACK&#xff08;Acknowledgment&#xff09;機制 實現了靈活的數據確認策略&#xff0c;允許用戶在 數據可靠性 和 系統性能 之間進行權衡。本文將深入解析 Kafka ACK 機制的工作原理、配…

FastMCP:構建 MCP 服務器和客戶端的高效 Python 框架

在人工智能領域&#xff0c;模型上下文協議&#xff08;Model Context Protocol&#xff0c;簡稱 MCP&#xff09;作為一種標準化的協議&#xff0c;為大型語言模型&#xff08;LLM&#xff09;提供了豐富的上下文和工具支持。而 FastMCP 作為構建 MCP 服務器和客戶端的 Python…

動態庫導出符號與extern “C“

1. windows下動態庫導出符號 根據C/C語法規則&#xff0c;函數聲明中的修飾符&#xff08;如__declspec(dllexport)&#xff09;可以放在返回類型之前或返回類型之后、函數名之前。這兩種方式在功能上是等價的&#xff0c;編譯器會以相同的方式處理。 __declspec(dllexport) …

Linux(9)——進程(控制篇——下)

目錄 三、進程等待 1&#xff09;進程等待的必要性 2&#xff09;獲取子進程的status 3&#xff09;進程的等待方法 wait方法 waitpid方法 多進程創建以及等待的代碼模型 非阻塞的輪訓檢測 四、進程程序替換 1&#xff09;替換原理 2&#xff09;替換函數 3&…

Datatable和實體集合互轉

1.使用已廢棄的 JavaScriptSerializer&#xff0c;且反序列化為弱類型 ArrayList。可用但不推薦。 using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; using System.Web; using Sy…