前言
参考博文:
https://www.cnblogs.com/xiaomowang/p/12400440.html
测试代码
[HttpGet] public async Task<MessageModel<string>> UseConDic(int index, string key, string value) { var r = await _utilBLL.UseConDic(index, key, value); return new MessageModel<string>(true, "Success") { Data = r }; }
public interface IUtilBLL { Task<string> UseConDic(int index, string key, string value); }
public class UtilBLL : IUtilBLL { private static readonly ConcurrentDictionary<string, string> pairs = new ConcurrentDictionary<string, string>(); public async Task<string> UseConDic(int index, string key, string value) { var pId = System.Diagnostics.Process.GetCurrentProcess().Id; int count = pairs.Count; var val = pairs.GetOrAdd(key, value); return $"pId:{pId},执行前:{count}个,执行后:{pairs.Count}个。val:{val}"; } }
/// <summary> /// 将接口导入到SqlServer /// </summary> /// <returns></returns> static async Task TestAddConDicLogs() { Console.WriteLine($"{DateTime.Now}开始执行"); SqlSugarScope sqlSugarScope = new SqlSugarScope(new ConnectionConfig() { DbType = SqlSugar.DbType.SqlServer, ConnectionString = "server=.;database=ConTest;uid=sa;pwd=123456;", IsAutoCloseConnection = true, }); string filePath = @"D:\Logs\2021-11-30\warn.txt"; List<ConDicLogs> lst = new List<ConDicLogs>(); var fileContent = File.ReadAllLines(filePath, Encoding.UTF8); for (int i = 0; i < fileContent.Length; i++) { string str = fileContent[i]; if (str.Contains("Util.UseConDic") == false) continue; ConDicLogs conDicLogs = new ConDicLogs(); { string p = str[str.IndexOf("参数:")..]; string para = p[p.IndexOf("【")..p.IndexOf("】")]; para = para.Replace("【", ""); para = para.Replace("query:", ""); para = para.Replace(".", ""); para = para.Replace("】", ""); string[] s1 = para.Split("&"); conDicLogs.p_index = s1[0]; conDicLogs.p_key = s1[1]; conDicLogs.p_value = s1[2]; conDicLogs.p_index = conDicLogs.p_index.Replace("index=", ""); conDicLogs.p_key = conDicLogs.p_key.Replace("key=", ""); conDicLogs.p_value = conDicLogs.p_value.Replace("value=", ""); } { string p = str[str.IndexOf("Data")..]; string para = p[p.IndexOf("pId")..p.IndexOf("}")]; para = para.Replace("\"", ""); para = para.Replace("}", ""); conDicLogs.r_pId = para[para.IndexOf("pId:")..para.IndexOf(",", para.IndexOf("pId:"))]; conDicLogs.r_ExecBefore = para[para.IndexOf("执行前:")..para.IndexOf("个", para.IndexOf("执行前:"))]; conDicLogs.r_ExecAfter = para[para.IndexOf("执行后:")..para.IndexOf("个", para.IndexOf("执行后:"))]; conDicLogs.r_val = para[para.IndexOf("val:")..]; conDicLogs.r_pId = conDicLogs.r_pId.Replace("pId:", ""); conDicLogs.r_ExecBefore = conDicLogs.r_ExecBefore.Replace("执行前:", ""); conDicLogs.r_ExecAfter = conDicLogs.r_ExecAfter.Replace("执行后:", ""); conDicLogs.r_val = conDicLogs.r_val.Replace("val:", ""); } Console.WriteLine($"第{i}个"); lst.Add(conDicLogs); } Console.WriteLine("加载导入数据的集合完成"); var r = sqlSugarScope.Insertable(lst).ExecuteCommand(); Console.WriteLine($"{DateTime.Now}结束执行"); }
/*创建接口日志表*/ CREATE TABLE [dbo].[ConDicLogs]( [p_index] [varchar](10) NULL, [p_key] [varchar](10) NULL, [p_value] [varchar](10) NULL, [r_pId] [varchar](10) NULL, [r_ExecBefore] [varchar](10) NULL, [r_ExecAfter] [varchar](10) NULL, [r_val] [varchar](10) NULL ) ON [PRIMARY] GO
/*
select count(1)
from ConDicLogs
where r_pId='31356'
select count(1)
from ConDicLogs
where r_val='18836'
select *
from ConDicLogs
where r_pId='31356' and r_ExecBefore=0
*/
测试工具
使用Jmeter进行并发测试
1.线程属性
2.HTTP请求信息
IIS信息
最大工作进程数调整为:3
测试结果
Jmeter结果
1000*50=50000个样本
NLog日志
总共49998条日志,与Jmeter样本对比,少了2条日志,未找到原因
其中有效日志,49992条记录,存在6条无效的日志记录
IIS进程
Process进程Id分别为:
进程1=>31356
进程2=>2632
进程3=>10152
请求结果分析
1.pId:31356
记录数:14899条,执行前0个:2条,最终结果:18836,最终结果记录数:14899
2.pId:2632
记录数:15834条,执行前0个:2条,最终结果:26475,最终结果记录数:15834
3.pId:10152
记录数:19259条,执行前0个:3条,最终结果:14205,最终结果记录数:19259
总结
并发时,测试ConcurrentDictionary的写入值正常,虽然有极限情况下写之前的字典元素个数为0,但是最终写到字典之后返回的结果都是同一个