.NET Web API无法连接Elasticsearch,求助问题排查
.NET Web API连接Elasticsearch日志报错问题排查与修复
问题背景
尝试使用Serilog为.NET Web API配置日志,将日志发送至Docker运行的Elasticsearch并在Kibana查看,但API连接Elasticsearch持续报错,不同版本的Serilog.Sinks.Elasticsearch包出现不同错误:
- v10.0.0:产品校验失败,无法确认服务器是Elasticsearch
- v8.4.1:连接被拒绝
现有配置
Program.cs日志配置
Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .Enrich.FromLogContext() .Enrich.WithMachineName() .Enrich.WithEnvironmentName() .Enrich.WithExceptionDetails() .WriteTo.Console() .WriteTo.Elasticsearch(ConfigureElasticSink(builder.Configuration)) .CreateLogger(); builder.Host.UseSerilog(); private static ElasticsearchSinkOptions ConfigureElasticSink(IConfiguration configuration) { var elasticUri = configuration.GetValue<string>("ElasticConfiguration:Uri"); return new ElasticsearchSinkOptions(elasticUri != null ? new Uri(elasticUri) : null) { AutoRegisterTemplate = true, IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name?.ToLower().Replace(".","-")}-{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}-{DateTime.UtcNow:yyyy-MM--dd}", AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7, NumberOfReplicas = 1, NumberOfShards= 2, OverwriteTemplate = true, TemplateName = "DevProject", TypeName = null, BatchAction = ElasticOpType.Create }; }
Docker Compose配置
elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.12.1 container_name: elasticsearch restart: always environment: - discovery.type=single-node - xpack.security.enabled=false ports: - 9200:9200 networks: - infrastructure volumes: - esdata:/usr/share/elasticsearch/data kibana: image: docker.elastic.co/kibana/kibana:8.12.1 container_name: kibana restart: always environment: - ELASTICSEARCH_URL=http://127.0.0.1:9200 ports: - "5601:5601" networks: - infrastructure depends_on: - elasticsearch volumes: esdata: networks: infrastructure: name: infrastructure driver: bridge
测试连接代码
[HttpGet("TestConnection")] public async Task<IActionResult> TestConnection() { var connectionSettings = new ConnectionConfiguration(_elasticsearchUri); var lowLevelClient = new ElasticLowLevelClient(connectionSettings); try { var response = await lowLevelClient.PingAsync<StringResponse>(); if (response.Success) { return Ok("Elasticsearch connection successful."); } else { return StatusCode(500, "Failed to connect to Elasticsearch."); } } catch (Exception ex) { return StatusCode(500, $"Error connecting to Elasticsearch: {ex.Message}"); } }
修复步骤
1. 修正Docker网络访问地址
如果API运行在Docker容器中,不能用http://127.0.0.1:9200,因为容器内的127.0.0.1指向自身,而非宿主机的Elasticsearch容器。需改用容器名http://elasticsearch:9200,同一Docker网络内可通过容器名直接解析。
修改appsettings.json中的配置:
"ElasticConfiguration": { "Uri": "http://elasticsearch:9200" }
若API在宿主机运行,确认宿主机9200端口可访问:执行curl http://127.0.0.1:9200,返回健康状态则正常。
2. 修复Serilog Sink配置错误
修正IndexFormat日期格式
原配置中日期部分多了一个连字符yyyy-MM--dd,改为yyyy-MM-dd:
IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name?.ToLower().Replace(".","-")}-{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}-{DateTime.UtcNow:yyyy-MM-dd}",
禁用产品校验(针对v10.0.0版本报错)
Elasticsearch 8.x的产品校验逻辑变化,需在Sink配置中禁用:
private static ElasticsearchSinkOptions ConfigureElasticSink(IConfiguration configuration) { var elasticUri = configuration.GetValue<string>("ElasticConfiguration:Uri"); var sinkOptions = new ElasticsearchSinkOptions(new Uri(elasticUri)) { AutoRegisterTemplate = true, IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name?.ToLower().Replace(".","-")}-{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}-{DateTime.UtcNow:yyyy-MM-dd}", AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7, NumberOfReplicas = 1, NumberOfShards= 2, OverwriteTemplate = true, TemplateName = "DevProject", TypeName = null, BatchAction = ElasticOpType.Create }; // 添加连接配置,禁用产品校验 sinkOptions.ModifyConnectionSettings = conn => conn .DisableProductCheck(); return sinkOptions; }
3. 修正测试连接代码
测试代码中同样需禁用产品校验,并确保使用正确的地址:
[HttpGet("TestConnection")] public async Task<IActionResult> TestConnection() { var connectionSettings = new ConnectionConfiguration(_elasticsearchUri) .DisableProductCheck(); // 添加此行 var lowLevelClient = new ElasticLowLevelClient(connectionSettings); try { var response = await lowLevelClient.PingAsync<StringResponse>(); if (response.Success) { return Ok("Elasticsearch connection successful."); } else { return StatusCode(500, "Failed to connect to Elasticsearch."); } } catch (Exception ex) { return StatusCode(500, $"Error connecting to Elasticsearch: {ex.Message}"); } }
4. 修复Kibana的Elasticsearch地址
Kibana运行在Docker中,同样需用容器名访问Elasticsearch,修改Docker Compose的Kibana配置:
kibana: image: docker.elastic.co/kibana/kibana:8.12.1 container_name: kibana restart: always environment: - ELASTICSEARCH_URL=http://elasticsearch:9200 # 改为容器名 ports: - "5601:5601" networks: - infrastructure depends_on: - elasticsearch
5. 确保版本兼容性
- Elasticsearch 8.x 对应使用 Serilog.Sinks.Elasticsearch v10.x 版本,v8.x版本Sink不兼容Elasticsearch 8.x,建议升级到最新稳定版。
内容的提问来源于stack exchange,提问作者user1417294
相关产品推荐
相关产品推荐

