MES-ETL/Mesdb.DataGenerator/Program.cs
2817212736@qq.com b20c56640f 多项新特性和更改:
- 添加模拟数据生成器;
- GC时添加碎片整理;
- 优化日志输出,添加更多DEBUG监控项目;
- 修复输出时分库配置逻辑的严重错误;
- 优化了少许内存性能,减少Lambda闭包分配;
2024-12-20 10:43:05 +08:00

288 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// See https://aka.ms/new-console-template for more information
using System.Text;
using Mesdb.DataGenerator;
using MesETL.App;
using MesETL.App.Cache;
using MesETL.App.Const;
using MesETL.App.HostedServices;
using MesETL.App.HostedServices.Abstractions;
using MesETL.App.Options;
using MesETL.App.Services;
using MesETL.App.Services.ErrorRecorder;
using MesETL.App.Services.ETL;
using MesETL.App.Services.Loggers;
using MesETL.App.Services.Seq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
await RunProgram();
return;
async Task RunProgram()
{
ThreadPool.SetMaxThreads(200, 200);
var host = Host.CreateApplicationBuilder(args);
var dbGroup = new Dictionary<string, int>()
{
{ "mesdb_1", 5000 },
{ "mesdb_2", 10000 },
{ "mesdb_3", 15000 },
{ "mesdb_4", 20000 },
{ "mesdb_5", 2147483647 },
};
var tenantDbOptions = new TenantDbOptions()
{
TenantKey = "CompanyID",
DbGroup = dbGroup,
UseDbGroup = "Prod",
};
host.Services.Configure<TenantDbOptions>(options =>
{
options.TenantKey = tenantDbOptions.TenantKey;
options.DbGroup = tenantDbOptions.DbGroup;
options.UseDbGroup = tenantDbOptions.UseDbGroup;
});
host.Services.Configure<MockInputOptions>(options =>
{
const float Multiplexer = 0.01F;
var SampleSharedKeys = Enumerable.Range(0, 11).Select(i => (23010 + i * 10).ToString()).Concat(
Enumerable.Range(0, 11).Select(i => (24010 + i * 10).ToString())).ToArray();
options.Rules = new Dictionary<string, TableMockOptions>()
{
{
TableNames.Order, new TableMockOptions((long)(2912406 * Multiplexer), context =>
{
string[] headers =
[
"OrderNo", "ShardKey", "CreateTime", "CompanyID", "SchduleDeliveryDate", "OrderType",
"OrderSort",
"CadDataType", "Deleted", "ProcessState"
];
string[] fields =
[
(20241210000000 + context.Index).ToString(),
SampleSharedKeys[Random.Shared.Next(SampleSharedKeys.Length)],
$"\"{DateTime.Now:yyyy-MM-dd HH:mm:ss}\"",
Random.Shared.Next(1, 28888).ToString(),
$"\"{DateTime.Now.AddDays(Random.Shared.Next(1, 30)):yyyy-MM-dd HH:mm:ss}\"",
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(0, 2).ToString(),
Random.Shared.Next(0, 2).ToString()
];
return new DataRecord(fields, TableNames.Order, headers);
})
},
{
TableNames.OrderItem, new TableMockOptions((long)(820241144 * Multiplexer), context =>
{
string[] headers =
[
"ID", "ShardKey", "OrderNo", "ItemNo", "ItemType", "RoomID", "BoxID", "DataID", "PlanID",
"PackageID", "Num", "CompanyID"
];
string[] fields =
[
context.Index.ToString(),
SampleSharedKeys[Random.Shared.Next(SampleSharedKeys.Length)],
(20241210000000 + Random.Shared.Next(0, 2912406)).ToString(),
(2412000000000 + context.Index).ToString(),
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(1, 1000000).ToString(),
Random.Shared.Next(1, 1000000).ToString(),
Random.Shared.Next(1, 1000000).ToString(),
Random.Shared.Next(1, 1306670366).ToString(),
Random.Shared.Next(1, 10000000).ToString(),
(Random.Shared.Next(1, 2000000) / 1000).ToString("F3"),
Random.Shared.Next(1, 28888).ToString(),
];
return new DataRecord(fields, TableNames.OrderItem, headers);
})
},
{
TableNames.OrderDataBlock, new TableMockOptions((long)(428568719 * Multiplexer), context =>
{
string[] headers =
[
"ID", "ShardKey", "OrderNo", "BoardName", "BoardType", "GoodsID", "Width", "Height",
"Thickness",
"SpliteWidth", "SpliteHeight", "SpliteThickness", "SealedLeft", "SealedRight", "SealedUp",
"SealedDown", "Area", "Wave", "HoleFace", "PaiKong", "RemarkJson", "UnRegularPointCount",
"FrontHoleCount", "BackHoleCount", "SideHoleCount", "FrontModelCount", "BackModelCount",
"IsDoor",
"OpenDoorType", "CompanyID", "BorderLengthHeavy", "BorderLengthLight", "IsHXDJX",
"ModuleTypeID",
"PlanFilterType"
];
string[] BoardNames = ["左侧板", "右侧板", "左开门板", "右开门板", "薄背板", "顶板", "底板", "地脚线", "后地脚", "层板", "立板"];
string[] fields =
[
context.Index.ToString(),
SampleSharedKeys[Random.Shared.Next(SampleSharedKeys.Length)],
(20241210000000 + Random.Shared.Next(0, 2912406)).ToString(),
$"\"{BoardNames[Random.Shared.Next(0, BoardNames.Length)]}\"",
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(1, 1000000).ToString(),
(Random.Shared.Next(1, 2000000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 1200000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 18000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 2000000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 1200000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 18000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 2000) / 1000).ToString("F2"),
(Random.Shared.Next(1, 2000) / 1000).ToString("F2"),
(Random.Shared.Next(1, 2000) / 1000).ToString("F2"),
(Random.Shared.Next(1, 2000) / 1000).ToString("F2"),
(Random.Shared.Next(1, 3000) / 1000).ToString("F3"),
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(0, 3).ToString(),
Random.Shared.Next(0, 3).ToString(),
Convert.ToHexString(Encoding.UTF8.GetBytes(MockHelper.RandomString(100))),
Random.Shared.Next(0, 4).ToString(),
Random.Shared.Next(0, 4).ToString(),
Random.Shared.Next(0, 4).ToString(),
Random.Shared.Next(0, 4).ToString(),
Random.Shared.Next(0, 4).ToString(),
Random.Shared.Next(0, 4).ToString(),
Random.Shared.Next(0, 2).ToString(),
Random.Shared.Next(0, 6).ToString(),
Random.Shared.Next(1, 28888).ToString(),
(Random.Shared.Next(1, 2000000) / 1000).ToString("F3"),
(Random.Shared.Next(1, 2000000) / 1000).ToString("F3"),
Random.Shared.Next(0, 2).ToString(),
Random.Shared.Next(0, 100000).ToString(),
Random.Shared.Next(0, 5).ToString(),
];
return new DataRecord(fields, TableNames.OrderDataBlock, headers);
})
},
{
TableNames.OrderBoxBlock, new TableMockOptions((long)(20163038 * Multiplexer), context =>
{
string[] headers = ["BoxID", "ShardKey", "OrderNo", "Data", "CompanyID"];
string[] fields =
[
context.Index.ToString(),
SampleSharedKeys[Random.Shared.Next(SampleSharedKeys.Length)],
(20241210000000 + Random.Shared.Next(0, 2912406)).ToString(),
OrderBoxBlockHelper.RandomPick(),
Random.Shared.Next(1, 28888).ToString(),
];
return new DataRecord(fields, TableNames.OrderBoxBlock, headers);
})
},
{
TableNames.OrderModuleExtra, new TableMockOptions((long)(33853580 * Multiplexer), context =>
{
string[] headers =
[
"ID", "ShardKey", "OrderNo", "RoomID", "BoxID", "PropType", "JsonStr", "CompanyID"
];
string[] fields =
[
context.Index.ToString(),
SampleSharedKeys[Random.Shared.Next(SampleSharedKeys.Length)],
(20241210000000 + Random.Shared.Next(0, 2912406)).ToString(),
Random.Shared.Next(1, 1000000).ToString(),
Random.Shared.Next(1, 1000000).ToString(),
Random.Shared.Next(0, 14).ToString(),
OrderModuleExtraHelper.PickJson(),
Random.Shared.Next(1, 28888).ToString(),
];
return new DataRecord(fields, TableNames.OrderModuleExtra, headers);
})
}
};
});
host.Services.Configure<DataTransformOptions>(options =>
{
options.DatabaseFilter = record =>
{
var companyId = int.Parse(record[tenantDbOptions.TenantKey]); // 每个实体都应存在CompanyID否则异常
return tenantDbOptions.GetDbNameByTenantKeyValue(companyId);
};
});
host.Services.Configure<DatabaseOutputOptions>(options =>
{
options.ConnectionString = "Server=192.168.1.246;Port=3333;UserId=root;Password=123456;";
options.FlushCount = 10000;
options.MaxAllowedPacket = 67108864;
options.MaxDatabaseOutputTask = 4;
options.ColumnTypeConfig = new Dictionary<string, ColumnType>
{
{ "machine.Settings", ColumnType.Text },
{ "order_block_plan.BlockInfo", ColumnType.Text },
{ "order_block_plan.OrderNos", ColumnType.Json },
{ "order_block_plan_result.PlaceData", ColumnType.Blob },
{ "order_box_block.Data", ColumnType.Blob },
{ "order_data_block.RemarkJson", ColumnType.Text },
{ "order_data_goods.ExtraProp", ColumnType.Json },
{ "order_extra.ConfigJson", ColumnType.Json },
{ "order_module_extra.Data", ColumnType.Blob },
{ "order_module_extra.JsonStr", ColumnType.Text },
{ "order_patch_detail.BlockDetail", ColumnType.Json },
{ "order_process_schdule.AreaName", ColumnType.Text },
{ "order_process_schdule.ConsigneeAddress", ColumnType.Text },
{ "order_process_schdule.ConsigneePhone", ColumnType.Text },
{ "order_process_schdule.CustomOrderNo", ColumnType.Text },
{ "order_process_schdule.OrderProcessStepName", ColumnType.Text },
{ "order_scrap_board.OutLineJson", ColumnType.Text },
{ "order_wave_group.ConfigJson", ColumnType.Json },
{ "process_info.Users", ColumnType.Text },
{ "process_item_exp.ItemJson", ColumnType.Text },
{ "report_template.SourceConfig", ColumnType.Text },
{ "report_template.Template", ColumnType.Text },
{ "simple_package.Items", ColumnType.Json },
{ "sys_config.JsonStr", ColumnType.Text },
{ "sys_config.Value", ColumnType.Text }
};
});
host.Services.AddLogging(builder =>
{
builder.ClearProviders();
builder.AddSerilog(new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"./Log/Error/{ErrorRecorder.UID}.log"),
restrictedToMinimumLevel: LogEventLevel.Error)
// .WriteTo.File("./Log/Info/{ErrorRecorder.UID}.log", restrictedToMinimumLevel:LogEventLevel.Information) //性能考虑暂不使用
.CreateLogger()
);
});
host.Services.AddDataSourceFactory();
host.Services.AddErrorRecorderFactory();
host.Services.AddSingleton<ProcessContext>();
host.Services.AddSingleton<SeqService>();
var prodLen = host.Configuration.GetRequiredSection("RecordQueue").GetValue<int>("ProducerQueueLength");
var consLen = host.Configuration.GetRequiredSection("RecordQueue").GetValue<int>("ConsumerQueueLength");
var maxCharCount = host.Configuration.GetRequiredSection("RecordQueue").GetValue<long>("MaxByteCount") / 2;
host.Services.AddKeyedSingleton<DataRecordQueue>(ConstVar.Producer, new DataRecordQueue(prodLen, maxCharCount));
host.Services.AddRecordQueuePool(dbGroup.Keys
.Select(key => (key: key, queue: new DataRecordQueue(consLen, maxCharCount))).ToArray());
// host.Services.AddSingleton<ITaskMonitorLogger, CacheTaskMonitorLogger>();
host.Services.AddSingleton<ITaskMonitorLogger, LoggerTaskMonitorLogger>();
host.Services.AddHostedService<MainHostedService>();
host.Services.AddSingleton<IInputService, MockInputService>();
host.Services.AddSingleton<ITransformService, TransformService>();
host.Services.AddSingleton<IOutputService, OutputService>();
host.Services.AddSingleton<TaskMonitorService>();
// host.Services.AddRedisCache(redisOptions);
host.Services.AddSingleton<ICacher, MemoryCache>();
var app = host.Build();
await app.RunAsync();
}