当你在内测IDS发现识别不出的流量的时候

本文分享了两次IDS系统的故障排查经历,一是解决镜像流量识别问题,发现实习生误改防火墙设置;二是通过性能测试定位机器学习模块的瓶颈,优化锁使用导致的数据包阻塞。

1、曾经在测试IDS的时候,有一次发现IDS死活识别不出总交换机上的镜像流量。于是大家齐上阵,查看测试网络的IDS本地日志。查看linux 的coredump看是否有错误。发现没有错误后, 继续排查,重新建立了一个测试网络,还是出现镜像流量识别不出来的问题。排查了1下午,最后灵光一闪,是不是后端那里出了问题,终于排查后端代码的时候,发现实习生将防火墙的设置给改了,无论如何后端都只对特定IP打开而对其他IP屏蔽,所以流量根本无法被发送到IDS上。
2、第二个问题是,IDS中的分析匿名流量用到了机器学习算法,但是测试的时候总能发现丢包现象。和上级说了多次,也没有得到重视。于是就开始了性能测试。 分析到底是哪里出现了问题。首先是查看CPU和内存的状态,top指令,发现一旦开启机器学习模式,cpu利用率就大幅下降。据老师傅说这可能是IDS产生了阻塞,可能和某个线程有关。于是在机器学习模块的每个函数的开始和结尾分别打上时间戳t1,t2. 将每个函数执行完成后t2-t1得到的差值进行比对,最后就发现了确实是机器学习模块中的一个函数的性能和其他的相比非常地差,原因在于这个函数里对锁的运用有问题,导致了大量的数据包流量被阻塞在消息队列中发不出去。
最终解决了该问题。

using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace ScaffoldMaterialStatistics { public class ScaffoldStatsCommands { // 定义材料类型枚举 private enum MaterialType { HorizontalBar, // 横杆 VerticalBar, // 立杆 DiagonalBrace, // 水平斜拉杆 SteelTread, // 钢踏板 SteelSection, // 型钢 WallConnector, // 连墙件 Fastener // 扣件 } // 定义材料信息结构 private struct MaterialInfo { public MaterialType Type; public string Name; public double Length; // 单位:毫米 public int Quantity; } // 预编译正则表达式以提高性能 private static readonly Regex _lengthRegex = new Regex( @"(\d+\.?\d*)\s*(mm|米|m)|^(\d+\.?\d*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase ); private static readonly Regex _diagonalBraceRegex = new Regex( @"水平斜拉杆", RegexOptions.Compiled | RegexOptions.IgnoreCase ); // 缓存常用字符串比较 private static readonly string[] FastenerKeywords = { "扣件" }; private static readonly string[] SteelTreadKeywords = { "钢踏板" }; private static readonly string[] SteelSectionKeywords = { "型钢", "工字钢", "XCG", "悬挑", "90度", "90°", "45度", "45°", "角型钢" }; private static readonly string[] HorizontalBarKeywords = { "横杆" }; private static readonly string[] VerticalBarKeywords = { "立杆" }; private static readonly string[] WallConnectorKeywords = { "连墙件" }; [CommandMethod("MCS", CommandFlags.Modal)] public void ScaffoldMaterialStatistics() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 提示用户选择对象 PromptSelectionOptions opts = new PromptSelectionOptions(); opts.MessageForAdding = "请框选外架材料: "; PromptSelectionResult selRes = ed.GetSelection(opts); if (selRes.Status != PromptStatus.OK) { ed.WriteMessage("\n操作已取消。"); return; } // 显示处理进度 ed.WriteMessage("\n正在处理选中的对象,请稍候..."); // 使用Stopwatch监控性能 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); List<MaterialInfo> materials; using (Transaction tr = db.TransactionManager.StartTransaction()) { // 获取选择集 SelectionSet selSet = selRes.Value; // 根据对象数量选择合适的处理方法 if (selSet.Count > 10000) { ed.WriteMessage("\n检测到大量对象,启用批量处理模式..."); materials = CountMaterialsBatch(selSet, tr, ed); } else { materials = CountMaterials(selSet, tr, ed); } // 检查是否有统计数据 if (materials.Count == 0) { ed.WriteMessage("\n未找到可统计的材料!"); return; } stopwatch.Stop(); ed.WriteMessage($"\n材料统计完成,耗时: {stopwatch.Elapsed.TotalSeconds:F2}秒"); // 创建统计表格 CreateStatisticsTable(doc, materials, ed); tr.Commit(); } ed.WriteMessage("\n外架材料统计完成!"); } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}\n{ex.StackTrace}"); } } private List<MaterialInfo> CountMaterials(SelectionSet selSet, Transaction tr, Editor ed) { // 使用字典直接存储MaterialInfo结构 Dictionary<string, MaterialInfo> materialDict = new Dictionary<string, MaterialInfo>(); int unrecognizedCount = 0; int processedCount = 0; int totalCount = selSet.Count; // 使用Stopwatch控制进度更新频率 Stopwatch progressTimer = new Stopwatch(); progressTimer.Start(); // 批量处理对象,减少事务开销 ObjectId[] objectIds = selSet.GetObjectIds(); // 预处理图层和块名映射 var layerCache = new Dictionary<ObjectId, string>(); var blockNameCache = new Dictionary<ObjectId, string>(); // 预先获取所有图层和块名 foreach (ObjectId id in objectIds) { if (!id.IsValid) continue; Entity entity = tr.GetObject(id, OpenMode.ForRead) as Entity; if (entity == null) continue; layerCache[id] = entity.Layer.ToUpper(); if (entity is BlockReference blockRef) { BlockTableRecord btr = tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; blockNameCache[id] = btr.Name.ToUpper(); } } // 处理每个对象 foreach (ObjectId id in objectIds) { if (!id.IsValid) continue; processedCount++; // 每处理1000个对象或每2秒更新一次进度(减少频繁更新) if (processedCount % 1000 == 0 || progressTimer.ElapsedMilliseconds > 2000) { ed.WriteMessage($"\n已处理 {processedCount}/{totalCount} 个对象..."); progressTimer.Restart(); } string layerName = layerCache.ContainsKey(id) ? layerCache[id] : ""; string blockName = blockNameCache.ContainsKey(id) ? blockNameCache[id] : ""; MaterialInfo? info = null; if (!string.IsNullOrEmpty(blockName)) { // 解析块名和图层名并获取材料信息 info = ParseBlockAndLayerName(blockName, layerName); } else { // 非块对象 info = ParseLayerName(layerName); } if (info.HasValue) { MaterialInfo material = info.Value; // 应用乘数规则 if (material.Type == MaterialType.SteelTread && !material.Name.Contains("单片")) { // 非单片钢踏板数量×3 material.Quantity = 3; } else if (material.Type == MaterialType.Fastener && material.Name == "900mm扣件") { // 900mm扣件数量×2 material.Quantity = 2; } else { material.Quantity = 1; } // 创建唯一标识键 string key = $"{material.Type}_{material.Name}_{material.Length:F1}"; // 更新材料数量 if (materialDict.TryGetValue(key, out MaterialInfo existing)) { existing.Quantity += material.Quantity; materialDict[key] = existing; } else { materialDict[key] = material; } } else { unrecognizedCount++; } } // 输出未识别对象数量 if (unrecognizedCount > 0) { ed.WriteMessage($"\n警告: 有 {unrecognizedCount} 个对象未被识别"); } return materialDict.Values.ToList(); } // 批量处理方法,用于处理超大量数据 private List<MaterialInfo> CountMaterialsBatch(SelectionSet selSet, Transaction tr, Editor ed, int batchSize = 5000) { Dictionary<string, MaterialInfo> materialDict = new Dictionary<string, MaterialInfo>(); int unrecognizedCount = 0; ObjectId[] allObjectIds = selSet.GetObjectIds(); int totalCount = allObjectIds.Length; // 使用Stopwatch控制进度更新频率 Stopwatch progressTimer = new Stopwatch(); progressTimer.Start(); for (int i = 0; i < totalCount; i += batchSize) { int endIndex = Math.Min(i + batchSize, totalCount); int batchCount = endIndex - i; ed.WriteMessage($"\n正在处理批次 {i / batchSize + 1}/{(totalCount + batchSize - 1) / batchSize} ({batchCount}个对象)..."); // 处理当前批次 for (int j = i; j < endIndex; j++) { ObjectId id = allObjectIds[j]; if (!id.IsValid) continue; Entity entity = tr.GetObject(id, OpenMode.ForRead) as Entity; if (entity == null) continue; string layerName = entity.Layer.ToUpper(); string blockName = ""; if (entity is BlockReference blockRef) { BlockTableRecord btr = tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; blockName = btr.Name.ToUpper(); } MaterialInfo? info = !string.IsNullOrEmpty(blockName) ? ParseBlockAndLayerName(blockName, layerName) : ParseLayerName(layerName); if (info.HasValue) { MaterialInfo material = info.Value; // 应用乘数规则 if (material.Type == MaterialType.SteelTread && !material.Name.Contains("单片")) { // 非单片钢踏板数量×3 material.Quantity = 3; } else if (material.Type == MaterialType.Fastener && material.Name == "900mm扣件") { // 900mm扣件数量×3 material.Quantity = 3; } else { material.Quantity = 1; } // 创建唯一标识键 string key = $"{material.Type}_{material.Name}_{material.Length:F1}"; // 更新材料数量 if (materialDict.TryGetValue(key, out MaterialInfo existing)) { existing.Quantity += material.Quantity; materialDict[key] = existing; } else { materialDict[key] = material; } } else { unrecognizedCount++; } } // 每处理完一个批次,更新进度 if (progressTimer.ElapsedMilliseconds > 2000) { ed.WriteMessage($"\n已处理 {endIndex}/{totalCount} 个对象..."); progressTimer.Restart(); } // 可选:定期提交事务以释放内存(但会降低整体性能) // if (i % 10000 == 0) { tr.Commit(); tr.Start(); } } // 输出未识别对象数量 if (unrecognizedCount > 0) { ed.WriteMessage($"\n警告: 有 {unrecognizedCount} 个对象未被识别"); } return materialDict.Values.ToList(); } // 主要解析函数(块和图层) private MaterialInfo? ParseBlockAndLayerName(string blockName, string layerName) { // 1. 处理扣件 (包含900mm扣件识别) if (ContainsAny(blockName, FastenerKeywords) || ContainsAny(layerName, FastenerKeywords)) { bool is900mm = blockName.Contains("900") || layerName.Contains("900"); return new MaterialInfo { Type = MaterialType.Fastener, Name = is900mm ? "900mm扣件" : "标准扣件", Length = 0 }; } // 2. 处理钢踏板 (包含单片识别) if (ContainsAny(blockName, SteelTreadKeywords) || ContainsAny(layerName, SteelTreadKeywords)) { double length = ExtractLengthFromString(blockName); if (length <= 0) { length = ExtractLengthFromString(layerName); } bool isSingle = blockName.Contains("单片") || layerName.Contains("单片"); return new MaterialInfo { Type = MaterialType.SteelTread, Name = isSingle ? "单片钢踏板" : "钢踏板", Length = length }; } // 3. 增强型钢识别 if (IsSteelSection(blockName, layerName)) { double length = ExtractSteelLength(blockName, layerName); string name = "型钢"; if (blockName.Contains("工字钢连梁") || layerName.Contains("工字钢连梁")) name = "工字钢连梁"; else if (blockName.Contains("悬挑") || layerName.Contains("悬挑")) name = "悬挑型钢"; else if (blockName.Contains("90") || layerName.Contains("90")) name = "90度型钢"; else if (blockName.Contains("右45") || layerName.Contains("右45")) name = "右45°角型钢"; else if (blockName.Contains("左45") || layerName.Contains("左45")) name = "左45°角型钢"; return new MaterialInfo { Type = MaterialType.SteelSection, Name = name, Length = length }; } // 4. 其他材料类型 if (ContainsAny(blockName, HorizontalBarKeywords) || ContainsAny(layerName, HorizontalBarKeywords)) { double length = ExtractLengthFromString(blockName); if (length <= 0) { length = ExtractLengthFromString(layerName); } return new MaterialInfo { Type = MaterialType.HorizontalBar, Name = "横杆", Length = length }; } if (_diagonalBraceRegex.IsMatch(blockName) || _diagonalBraceRegex.IsMatch(layerName)) { double length = ExtractLengthFromString(blockName); if (length <= 0) { length = ExtractLengthFromString(layerName); } return new MaterialInfo { Type = MaterialType.DiagonalBrace, Name = "水平斜拉杆", Length = length }; } if (ContainsAny(blockName, VerticalBarKeywords) || ContainsAny(layerName, VerticalBarKeywords)) { return new MaterialInfo { Type = MaterialType.VerticalBar, Name = "立杆", Length = 0 }; } if (ContainsAny(blockName, WallConnectorKeywords) || ContainsAny(layerName, WallConnectorKeywords)) { double length = ExtractWallConnectorLength(blockName, layerName); return new MaterialInfo { Type = MaterialType.WallConnector, Name = "连墙件", Length = length }; } // 未识别 return null; } // 图层解析(独立对象) private MaterialInfo? ParseLayerName(string layerName) { // 1. 钢踏板 if (ContainsAny(layerName, SteelTreadKeywords)) { bool isSingle = layerName.Contains("单片"); return new MaterialInfo { Type = MaterialType.SteelTread, Name = isSingle ? "单片钢踏板" : "钢踏板", Length = ExtractLengthFromString(layerName) }; } // 2. 型钢 if (IsSteelSection("", layerName)) { double length = ExtractSteelLength("", layerName); string name = "型钢"; if (layerName.Contains("工字钢连梁")) name = "工字钢连梁"; else if (layerName.Contains("悬挑")) name = "悬挑型钢"; else if (layerName.Contains("90")) name = "90度型钢"; else if (layerName.Contains("右45")) name = "右45°角型钢"; else if (layerName.Contains("左45")) name = "左45°角型钢"; return new MaterialInfo { Type = MaterialType.SteelSection, Name = name, Length = length }; } // 3. 连墙件 if (ContainsAny(layerName, WallConnectorKeywords)) { return new MaterialInfo { Type = MaterialType.WallConnector, Name = "连墙件", Length = ExtractWallConnectorLength("", layerName) }; } // 4. 扣件 if (ContainsAny(layerName, FastenerKeywords)) { bool is900mm = layerName.Contains("900"); return new MaterialInfo { Type = MaterialType.Fastener, Name = is900mm ? "900mm扣件" : "标准扣件", Length = 0 }; } return null; } // 判断是否为型钢 private bool IsSteelSection(string blockName, string layerName) { string combined = $"{blockName} {layerName}".ToUpper(); return ContainsAny(combined, SteelSectionKeywords); } // 从字符串中提取长度信息 private double ExtractLengthFromString(string input) { if (string.IsNullOrEmpty(input)) return 0; var match = _lengthRegex.Match(input); if (!match.Success) return 0; // 处理带单位的数字 if (double.TryParse(match.Groups[1].Value, out double result)) { string unit = match.Groups[2].Value.ToLower(); // 使用传统的switch语句替换switch表达式 switch (unit) { case "米": case "m": return result * 1000; // 米转毫米 default: return result; } } // 处理纯数字 if (double.TryParse(match.Groups[3].Value, out result)) return result; return 0; } // 提取型钢长度(优先考虑图层名) private double ExtractSteelLength(string blockName, string layerName) { // 优先从图层名提取 double length = ExtractLengthFromString(layerName); if (length > 0) return length; // 然后从块名提取 return ExtractLengthFromString(blockName); } // 提取连墙件长度 private double ExtractWallConnectorLength(string blockName, string layerName) { // 优先从图层名提取 double length = ExtractLengthFromString(layerName); if (length > 0) return length; // 然后从块名提取 return ExtractLengthFromString(blockName); } // 创建统计表格 private void CreateStatisticsTable(Document doc, List<MaterialInfo> materials, Editor ed) { Database db = doc.Database; // 获取插入点 PromptPointResult ppr = ed.GetPoint("\n请指定统计表插入点: "); if (ppr.Status != PromptStatus.OK) { ed.WriteMessage("\n未指定插入点,取消创建表格。"); return; } Point3d insertPoint = ppr.Value; using (Transaction tr = db.TransactionManager.StartTransaction()) { // 创建表格 Table table = new Table(); table.SetDatabaseDefaults(db); table.Position = insertPoint; // 设置表格尺寸 table.NumRows = materials.Count + 3; // 标题+表头+数据行+说明行 table.NumColumns = 4; // 设置列宽 table.SetColumnWidth(0, 10); // 序号 table.SetColumnWidth(1, 25); // 材料名称 table.SetColumnWidth(2, 25); // 杆件长度 table.SetColumnWidth(3, 15); // 数量 // 设置标题行 table.Cells[0, 0].Value = "外架材料统计表"; table.Cells[0, 0].Alignment = CellAlignment.MiddleCenter; table.Cells[0, 0].TextHeight = 3.0; // 合并标题行单元格 table.MergeCells(CellRange.Create(table, 0, 0, 0, 3)); // 设置表头 string[] headers = { "序号", "材料名称", "杆件长度(mm)", "数量" }; for (int i = 0; i < headers.Length; i++) { table.Cells[1, i].Value = headers[i]; table.Cells[1, i].Alignment = CellAlignment.MiddleCenter; table.Cells[1, i].TextHeight = 2.5; } // 填充数据 int row = 2; int index = 1; foreach (var material in materials.OrderBy(m => m.Type).ThenBy(m => m.Length)) { table.Cells[row, 0].Value = index++.ToString(); // 序号 table.Cells[row, 1].Value = material.Name; // 材料名称 table.Cells[row, 2].Value = material.Length > 0 ? material.Length.ToString("F0") : ""; // 杆件长度(取整) table.Cells[row, 3].Value = material.Quantity; // 数量 // 设置数据单元格样式 for (int j = 0; j < 4; j++) { table.Cells[row, j].Alignment = CellAlignment.MiddleCenter; table.Cells[row, j].TextHeight = 2.0; } row++; } // 添加说明行 table.Cells[row, 0].Value = "说明:①本表中钢踏板除单钢踏板外其余钢踏板已乘3计算数量;本表中钢踏板按一步一设计算数量。②连墙件按楼层计算数量;扣件按每根连墙件4个扣件计算数量;③本表中横杆计算数量含外侧两道护腰横杆内侧未涉及在内;本表中材料用量为预估算用量;具体实际用量按现场实际施工用量为准。"; table.Cells[row, 0].Alignment = CellAlignment.MiddleLeft; table.Cells[row, 0].TextHeight = 1.2; // 合并说明行单元格 table.MergeCells(CellRange.Create(table, row, 0, row, 3)); // 将表格添加到当前空间 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); tr.Commit(); } } // 辅助方法:检查字符串是否包含任何关键字 private bool ContainsAny(string input, string[] keywords) { if (string.IsNullOrEmpty(input)) return false; foreach (string keyword in keywords) { if (input.Contains(keyword)) return true; } return false; } } } 1、增加统计步骤: 步骤1:命令栏显示:“请框选外架材料”改成“请框选平面已布置构件” 步骤2:命令栏显示:“请框选第一组立杆”点击鼠标右键可忽略这一步(组件图块名称:ScaffoldPole立杆200mm.dwg,ScaffoldPole立杆350mm.dwg,ScaffoldPole立杆500mm.dwg,ScaffoldPole立杆1000mm.dwg,ScaffoldPole立杆1500mm.dwg,ScaffoldPole立杆2000mm.dwg,ScaffoldPole立杆2500mm.dwg,ScaffoldPole固定桩.dwg,ScaffoldPole底托.dwg) 步骤3:命令栏显示:“请框选第二组立杆”点击鼠标右键可忽略这一步(组件图块名称:ScaffoldPole立杆200mm.dwg,ScaffoldPole立杆350mm.dwg,ScaffoldPole立杆500mm.dwg,ScaffoldPole立杆1000mm.dwg,ScaffoldPole立杆1500mm.dwg,ScaffoldPole立杆2000mm.dwg,ScaffoldPole立杆2500mm.dwg,ScaffoldPole固定桩.dwg,ScaffoldPole底托.dwg) 步骤4:命令栏显示:“请框选立横杆”;点击鼠标右键可忽略这一步 步骤5:命令栏显示:“请框选外架斜拉杆”;点击鼠标右键可忽略这一步 步骤6:命令栏显示:“请框选或点选楼层线”;点击鼠标右键可忽略这一步 2、以上原代码严禁更改只修改以上相关要求的修改部分;统计计算要求如下: ①步骤2和步骤3统计计算要求:按步骤1统计的立杆数量乘以步骤2框选的第一组立杆如2500mm两根除以2倍加上步骤3框选的第二组立杆如2500mm两根除以2倍,按规格统计到表中;举例: 材料名称 杆件长度(mm) 数量 立杆 2500 100 ②步骤4统计计算要求:按步骤1统计的横杆数量乘以(步骤4框选立横杆数量除以3) ③步骤5统计计算要求:按步骤1统计的水平斜拉杆数量乘以步骤5框选外架斜拉杆数量 ④步骤6统计计算要求:按步骤1统计的连墙件及扣件数量乘以步骤6框选或点选的楼层线数量 ⑤若步骤2至步骤6点击鼠标右键忽略后只统计步骤1平面布置的构件数量;如原代码中计算
最新发布
09-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值