This commit is contained in:
zenghongyao 2025-04-23 15:11:27 +08:00
commit fff1ba1a7b
12 changed files with 337 additions and 247 deletions

View File

@ -24,7 +24,6 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts
{ {
_logger = logger; _logger = logger;
_protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>(); _protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>();
} }

View File

@ -1,5 +1,8 @@
namespace JiShe.CollectBus.Host namespace JiShe.CollectBus.Host
{ {
/// <summary>
/// CollectBusHostConst
/// </summary>
public static class CollectBusHostConst public static class CollectBusHostConst
{ {
/// <summary> /// <summary>
@ -23,9 +26,15 @@
public const string HangfireDashboardEndPoint = "/hangfire"; public const string HangfireDashboardEndPoint = "/hangfire";
/// <summary> /// <summary>
/// CAP 端点 /// 健康检查 端点
/// </summary> /// </summary>
public const string CapDashboardEndPoint = "/cap"; public const string HealthEndPoint = "/health";
/// <summary>
/// 健康检查 端点
/// </summary>
public const string HealthDashboardEndPoint = "/health-ui";
} }
} }

View File

@ -2,6 +2,7 @@
using Hangfire; using Hangfire;
using Hangfire.Redis.StackExchange; using Hangfire.Redis.StackExchange;
using JiShe.CollectBus.Host.Hangfire; using JiShe.CollectBus.Host.Hangfire;
using JiShe.CollectBus.Host.HealthChecks;
using JiShe.CollectBus.Host.Swaggers; using JiShe.CollectBus.Host.Swaggers;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
@ -16,6 +17,9 @@ using Volo.Abp.Modularity;
using TouchSocket.Core; using TouchSocket.Core;
using TouchSocket.Sockets; using TouchSocket.Sockets;
using JiShe.CollectBus.Plugins; using JiShe.CollectBus.Plugins;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using JiShe.CollectBus.Cassandra;
namespace JiShe.CollectBus.Host namespace JiShe.CollectBus.Host
@ -206,7 +210,6 @@ namespace JiShe.CollectBus.Host
private void ConfigureCustom(ServiceConfigurationContext context, IConfiguration configuration) private void ConfigureCustom(ServiceConfigurationContext context, IConfiguration configuration)
{ {
context.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); context.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
context.Services.AddHealthChecks();
} }
/// <summary> /// <summary>
@ -241,5 +244,37 @@ namespace JiShe.CollectBus.Host
.SetUdpDataHandlingAdapter(() => new NormalUdpDataHandlingAdapter()); .SetUdpDataHandlingAdapter(() => new NormalUdpDataHandlingAdapter());
}); });
} }
/// <summary>
/// 健康检查
/// </summary>
/// <param name="context"></param>
/// <param name="configuration"></param>
private void ConfigureHealthChecks(ServiceConfigurationContext context, IConfiguration configuration)
{
if (!configuration.GetValue<bool>("HealthChecks:IsEnable")) return;
var cassandraConfig = new CassandraConfig();
configuration.GetSection("Cassandra").Bind(cassandraConfig);
context.Services.AddHealthChecks()
.AddMongoDb(configuration.GetConnectionString("Default"), "MongoDB", HealthStatus.Unhealthy)
.AddRedis(configuration.GetValue<string>("Redis:Configuration") ?? string.Empty, "Redis",
HealthStatus.Unhealthy)
.AddKafka(new Confluent.Kafka.ProducerConfig
{
BootstrapServers = configuration.GetConnectionString("Kafka")
}, "Kafka", failureStatus: HealthStatus.Unhealthy)
.AddCheck<CassandraHealthCheck>("Cassandra")
.AddCheck<IoTdbHealthCheck>("IoTDB");
context.Services
.AddHealthChecksUI(options =>
{
options.AddHealthCheckEndpoint("JiSheCollectBus", "/health"); // 映射本地端点
})
.AddInMemoryStorage();
}
} }
} }

View File

@ -1,4 +1,5 @@
using Hangfire; using Hangfire;
using HealthChecks.UI.Client;
using JiShe.CollectBus.Host.Extensions; using JiShe.CollectBus.Host.Extensions;
using JiShe.CollectBus.Host.HealthChecks; using JiShe.CollectBus.Host.HealthChecks;
using JiShe.CollectBus.Host.Swaggers; using JiShe.CollectBus.Host.Swaggers;
@ -45,9 +46,9 @@ namespace JiShe.CollectBus.Host
ConfigureNetwork(context, configuration); ConfigureNetwork(context, configuration);
ConfigureJwtAuthentication(context, configuration); ConfigureJwtAuthentication(context, configuration);
ConfigureHangfire(context); ConfigureHangfire(context);
//ConfigureKafkaTopic(context, configuration);
ConfigureAuditLog(context); ConfigureAuditLog(context);
ConfigureCustom(context, configuration); ConfigureCustom(context, configuration);
ConfigureHealthChecks(context, configuration);
Configure<AbpClockOptions>(options => { options.Kind = DateTimeKind.Local; }); Configure<AbpClockOptions>(options => { options.Kind = DateTimeKind.Local; });
} }
@ -89,11 +90,16 @@ namespace JiShe.CollectBus.Host
}); });
app.UseConfiguredEndpoints(endpoints => app.UseConfiguredEndpoints(endpoints =>
{ {
if (!configuration.GetValue<bool>("HealthChecks:IsEnable")) return;
endpoints.MapHealthChecks("/health", new HealthCheckOptions endpoints.MapHealthChecks("/health", new HealthCheckOptions
{ {
Predicate = _ => true, Predicate = _ => true,
ResponseWriter = HealthCheckResponse.Writer ResponseWriter = HealthCheckResponse.Writer
}); });
endpoints.MapHealthChecksUI(options =>
{
options.UIPath = "/health-ui";
});
}); });
} }
} }

View File

@ -0,0 +1,57 @@
using Cassandra;
using JiShe.CollectBus.Cassandra;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace JiShe.CollectBus.Host.HealthChecks
{
/// <summary>
/// CassandraHealthCheck
/// </summary>
/// <seealso cref="Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck" />
public class CassandraHealthCheck : IHealthCheck
{
private readonly IConfiguration _configuration;
/// <summary>
/// Initializes a new instance of the <see cref="CassandraHealthCheck"/> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
public CassandraHealthCheck(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// Runs the health check, returning the status of the component being checked.
/// </summary>
/// <param name="context">A context object associated with the current execution.</param>
/// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> that can be used to cancel the health check.</param>
/// <returns>
/// A <see cref="T:System.Threading.Tasks.Task`1" /> that completes when the health check has finished, yielding the status of the component being checked.
/// </returns>
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var cassandraConfig = new CassandraConfig();
_configuration.GetSection("Cassandra").Bind(cassandraConfig);
try
{
var clusterBuilder = Cluster.Builder();
foreach (var node in cassandraConfig.Nodes)
{
clusterBuilder.AddContactPoint(node.Host)
.WithPort(node.Port);
}
clusterBuilder.WithCredentials(cassandraConfig.Username, cassandraConfig.Password);
var cluster = clusterBuilder.Build();
using var session = await cluster.ConnectAsync();
var result = await Task.FromResult(session.Execute("SELECT release_version FROM system.local"));
var version = result.First().GetValue<string>("release_version");
return HealthCheckResult.Healthy($"Cassandra is healthy. Version: {version}");
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, $"Cassandra is unhealthy: {ex.Message}", ex);
}
}
}
}

View File

@ -0,0 +1,51 @@
using System.Net.Sockets;
using JiShe.CollectBus.Cassandra;
using JiShe.CollectBus.IoTDB.Interface;
using JiShe.CollectBus.IoTDB.Options;
using JiShe.CollectBus.IoTDB.Provider;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace JiShe.CollectBus.Host.HealthChecks
{
/// <summary>
/// IoTDBHealthCheck
/// </summary>
/// <seealso cref="Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck" />
public class IoTdbHealthCheck : IHealthCheck
{
private readonly IConfiguration _configuration;
/// <summary>
/// Initializes a new instance of the <see cref="IoTdbHealthCheck"/> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
public IoTdbHealthCheck(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// Runs the health check, returning the status of the component being checked.
/// </summary>
/// <param name="context">A context object associated with the current execution.</param>
/// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> that can be used to cancel the health check.</param>
/// <returns>
/// A <see cref="T:System.Threading.Tasks.Task`1" /> that completes when the health check has finished, yielding the status of the component being checked.
/// </returns>
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
var ioTDbOptions = new IoTDbOptions();
_configuration.GetSection("IoTDBOptions").Bind(ioTDbOptions);
var pool = new SessionPoolAdapter(ioTDbOptions);
await pool.OpenAsync();
return HealthCheckResult.Healthy($"IoTDB is healthy.");
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, $"IoTDB不健康: {ex.Message}", ex);
}
}
}
}

View File

@ -20,9 +20,14 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.Kafka" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.MongoDb" Version="8.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="9.0.0" />
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.4" /> <PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.4" />
<PackageReference Include="MassTransit" Version="8.4.0" />
<PackageReference Include="MassTransit.Kafka" Version="8.4.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.0" /> <PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.0" />
<PackageReference Include="Serilog" Version="4.1.0" /> <PackageReference Include="Serilog" Version="4.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />

View File

@ -11,59 +11,59 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet"/> <link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<title>后端服务</title> <title>后端服务</title>
</head> </head>
<body> <body>
<div class="container projects"> <div class="container projects">
<div class="projects-header page-header"> <div class="projects-header page-header">
<h2>后端服务列表</h2> <h2>后端服务列表</h2>
@* <p>这些项目或者是对Bootstrap进行了有益的补充或者是基于Bootstrap开发的</p> *@ @* <p>这些项目或者是对Bootstrap进行了有益的补充或者是基于Bootstrap开发的</p> *@
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-6 col-md-4 col-lg-3"> <div class="col-sm-6 col-md-4 col-lg-3">
<div class="thumbnail" style="height: 180px"> <div class="thumbnail" style="height: 180px">
<a href="@CollectBusHostConst.SwaggerUiEndPoint" target="_blank"> <a href="@CollectBusHostConst.SwaggerUiEndPoint" target="_blank">
<img class="lazy" src="/images/swagger.png" width="300" height="150"/> <img class="lazy" src="/images/swagger.png" width="300" height="150" />
</a> </a>
<div class="caption"> <div class="caption">
<h3> <h3>
<a href="@CollectBusHostConst.SwaggerUiEndPoint" target="_blank">SwaggerUI</a> <a href="@CollectBusHostConst.SwaggerUiEndPoint" target="_blank">SwaggerUI</a>
</h3> </h3>
</div>
</div> </div>
</div> </div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3"> <div class="col-sm-6 col-md-4 col-lg-3">
<div class="thumbnail" style="height: 180px"> <div class="thumbnail" style="height: 180px">
<a href="@CollectBusHostConst.HangfireDashboardEndPoint" target="_blank"> <a href="@CollectBusHostConst.HangfireDashboardEndPoint" target="_blank">
<img class="lazy" src="/images/hangfire.png" width="300" height="150"/> <img class="lazy" src="/images/hangfire.png" width="300" height="150" />
</a> </a>
<div class="caption"> <div class="caption">
<h3> <h3>
<a href="@CollectBusHostConst.HangfireDashboardEndPoint" target="_blank">Hangfire面板</a> <a href="@CollectBusHostConst.HangfireDashboardEndPoint" target="_blank">Hangfire面板</a>
</h3> </h3>
</div>
</div> </div>
</div> </div>
</div> <div class="col-sm-6 col-md-4 col-lg-3">
<div class="col-sm-6 col-md-4 col-lg-3"> <div class="thumbnail" style="height: 180px">
<div class="thumbnail" style="height: 180px"> <a href="@CollectBusHostConst.HealthDashboardEndPoint" target="_blank">
<a href="@CollectBusHostConst.CapDashboardEndPoint" target="_blank"> <img class="lazy" src="/images/hangfire.png" width="300" height="150" />
<img class="lazy" src="/images/cap.png" width="300" height="150"/> </a>
</a> <div class="caption">
<div class="caption"> <h3>
<h3> <a href="@CollectBusHostConst.HealthEndPoint" target="_blank">健康检查API</a> |
<a href="@CollectBusHostConst.CapDashboardEndPoint" target="_blank">CAP</a> <a href="@CollectBusHostConst.HealthDashboardEndPoint" target="_blank">UI</a>
</h3> </h3>
</div>
</div> </div>
</div> </div>
</div> @* <div class="col-sm-6 col-md-4 col-lg-3">
@* <div class="col-sm-6 col-md-4 col-lg-3">
<div class="thumbnail" style="height: 180px"> <div class="thumbnail" style="height: 180px">
<a href="@CollectBusHostConst.MoreEndPoint" target="_blank"> <a href="@CollectBusHostConst.MoreEndPoint" target="_blank">
<img class="lazy" src="/images/more.png" width="300" height="150"/> <img class="lazy" src="/images/more.png" width="300" height="150"/>
@ -75,99 +75,113 @@
</div> </div>
</div> </div>
</div> *@ </div> *@
</div>
</div> </div>
</div>
</body> </body>
</html> </html>
<style> <style>
*:before, *:before,
*:after { *:after {
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
} }
.container {
width: 1170px;
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
}
.projects-header {
width: 60%;
text-align: center;
font-weight: 200;
display: block;
margin: 60px auto 40px !important;
}
.page-header {
padding-bottom: 9px;
margin: 40px auto;
border-bottom: 1px solid #eee;
}
.projects-header h2 {
font-size: 42px;
letter-spacing: -1px;
}
h2 {
margin-top: 20px;
margin-bottom: 10px;
font-weight: 500;
line-height: 1.1;
color: inherit;
/* text-align: center; */
}
p {
margin: 0 0 10px;
}
.row {
margin-right: -15px;
margin-left: -15px;
}
.col-lg-3 {
width: 25%;
}
.projects .thumbnail {
display: block;
margin-right: auto;
margin-left: auto;
text-align: center;
margin-bottom: 30px;
border-radius: 0;
}
.thumbnail {
display: block;
padding: 4px;
line-height: 1.42857143;
background-color: #fff;
border: 1px solid #ddd;
.transition(border 0.2s ease-in-out);
}
a {
color: #337ab7;
text-decoration: none;
background-color: transparent;
}
.projects .thumbnail img {
max-width: 100%;
height: auto;
}
.thumbnail a > img,
.thumbnail > img {
margin-right: auto;
margin-left: auto;
}
img {
vertical-align: middle;
}
/* .projects .thumbnail .caption {
overflow-y: hidden;
color: #555;
} */
.caption { .container {
padding: 9px; width: 1170px;
overflow-y: hidden; padding-right: 15px;
color: #555; padding-left: 15px;
} margin-right: auto;
margin-left: auto;
}
.projects-header {
width: 60%;
text-align: center;
font-weight: 200;
display: block;
margin: 60px auto 40px !important;
}
.page-header {
padding-bottom: 9px;
margin: 40px auto;
border-bottom: 1px solid #eee;
}
.projects-header h2 {
font-size: 42px;
letter-spacing: -1px;
}
h2 {
margin-top: 20px;
margin-bottom: 10px;
font-weight: 500;
line-height: 1.1;
color: inherit;
/* text-align: center; */
}
p {
margin: 0 0 10px;
}
.row {
margin-right: -15px;
margin-left: -15px;
}
.col-lg-3 {
width: 25%;
}
.projects .thumbnail {
display: block;
margin-right: auto;
margin-left: auto;
text-align: center;
margin-bottom: 30px;
border-radius: 0;
}
.thumbnail {
display: block;
padding: 4px;
line-height: 1.42857143;
background-color: #fff;
border: 1px solid #ddd;
.transition(border 0.2s ease-in-out);
}
a {
color: #337ab7;
text-decoration: none;
background-color: transparent;
}
.projects .thumbnail img {
max-width: 100%;
height: auto;
}
.thumbnail a > img,
.thumbnail > img {
margin-right: auto;
margin-left: auto;
}
img {
vertical-align: middle;
}
/* .projects .thumbnail .caption {
overflow-y: hidden;
color: #555;
} */
.caption {
padding: 9px;
overflow-y: hidden;
color: #555;
}
</style> </style>

View File

@ -4,6 +4,7 @@ namespace JiShe.CollectBus.Host.Pages
{ {
public class Monitor : PageModel public class Monitor : PageModel
{ {
public void OnGet() public void OnGet()
{ {

View File

@ -1,12 +1,16 @@
using JiShe.CollectBus.Host; using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Hosting;
using Serilog; using Serilog;
using Volo.Abp.Modularity.PlugIns; using Volo.Abp.Modularity.PlugIns;
namespace JiShe.CollectBus.Host;
/// <summary>
/// Program
/// </summary>
public class Program public class Program
{ {
/// <summary> /// <summary>
/// /// Main
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
@ -19,47 +23,13 @@ public class Program
loggerConfiguration.ReadFrom.Configuration(context.Configuration); loggerConfiguration.ReadFrom.Configuration(context.Configuration);
}) })
.UseAutofac(); .UseAutofac();
var configuration = builder.Configuration;
await builder.AddApplicationAsync<CollectBusHostModule>(options => await builder.AddApplicationAsync<CollectBusHostModule>(options =>
{ {
// 加载插件,固定模式,可热插拔 options.PlugInSources.AddFolder((configuration["PlugInFolder"].IsNullOrWhiteSpace()? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins"): configuration["PlugInFolder"]) ?? string.Empty);
options.PlugInSources.AddFolder(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins"));
}); });
var app = builder.Build(); var app = builder.Build();
await app.InitializeApplicationAsync(); await app.InitializeApplicationAsync();
await app.RunAsync(); await app.RunAsync();
//await CreateHostBuilder(args).Build().RunAsync();
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseSerilog((context, loggerConfiguration) =>
{
loggerConfiguration.ReadFrom.Configuration(context.Configuration);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac();
private static IHostBuilder CreateConsoleHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => { ConfigureServices(services, hostContext); })
.UseAutofac()
.UseSerilog((context, loggerConfiguration) =>
{
loggerConfiguration.ReadFrom.Configuration(context.Configuration);
});
private static async Task ConfigureServices(IServiceCollection services, HostBuilderContext hostContext)
{
await services.AddApplicationAsync<CollectBusHostModule>();
} }
} }

View File

@ -1,53 +0,0 @@
using TouchSocket.Core;
using Volo.Abp.Modularity.PlugIns;
namespace JiShe.CollectBus.Host
{
/// <summary>
/// Startup
/// </summary>
public class Startup
{
private readonly IConfiguration _configuration;
/// <summary>
/// Initializes a new instance of the <see cref="Startup"/> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// Configures the services.
/// </summary>
/// <param name="services">The services.</param>
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<CollectBusHostModule>(options =>
{
// 加载插件,固定模式,可热插拔
options.PlugInSources.AddFolder(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins"));
});
}
/// <summary>
/// Configures the specified application.
/// </summary>
/// <param name="app">The application.</param>
/// <param name="lifetime">The lifetime.</param>
public void Configure(IApplicationBuilder app, IHostApplicationLifetime lifetime)
{
app.Use(async (context, next) =>
{
// 在请求处理之前调用 InitializeApplicationAsync
await app.InitializeApplicationAsync();
// 继续请求管道中的下一个中间件
await next();
});
}
}
}

View File

@ -51,16 +51,11 @@
"Issuer": "JiShe.CollectBus", "Issuer": "JiShe.CollectBus",
"ExpirationTime": 2 "ExpirationTime": 2
}, },
"HealthCheck": { "HealthChecks": {
"IsEnable": true, "IsEnable": true,
"MySql": { "HealthCheckDatabaseName": "HealthChecks",
"IsEnable": true "EvaluationTimeInSeconds": 10,
}, "MinimumSecondsBetweenFailureNotifications": 60
"Pings": {
"IsEnable": true,
"Host": "https://www.baidu.com/",
"TimeOut": 5000
}
}, },
"SwaggerConfig": [ "SwaggerConfig": [
{ {
@ -84,7 +79,7 @@
"SaslPassword": "lixiao1980", "SaslPassword": "lixiao1980",
"KafkaReplicationFactor": 3, "KafkaReplicationFactor": 3,
"NumPartitions": 30, "NumPartitions": 30,
"ServerTagName": "JiSheCollectBus99", "ServerTagName": "JiSheCollectBus30",
"FirstCollectionTime": "2025-04-22 16:07:00" "FirstCollectionTime": "2025-04-22 16:07:00"
}, },
"IoTDBOptions": { "IoTDBOptions": {
@ -144,5 +139,6 @@
"SerialConsistencyLevel": "Serial", "SerialConsistencyLevel": "Serial",
"DefaultIdempotence": true "DefaultIdempotence": true
} }
} },
"PlugInFolder": ""
} }