背景:下单流程里面,生成发货单是在独立线程池完成的,有些批发订单数据巨大,频繁拆包生成多个发货单
排查:由于ES刷新是在一个独立的api里面,一开始怀疑是异步线程频繁请求api导致中断的
- SemaphoreSlim:对同时访问资源或资源池的线程数加以限制,结果:无效
- lock:顺序执行,使线程等待,结果:无效
- 日记调试:在api里面打上日记,发现中止线程的时候根本没有进入api,现在基本可以断定是调用端的问题
查看调用端代码
// 改造前
//var client = new RestClient($"{ElasticsearchBaseApi}/api/Elasticsearch/UpdateElasticsearchOrder");
//var resp = client.Execute(request);
// 改造后(使用单例/静态变量)
var resp = client.Execute(request);
发现该项目好多地方都习惯是直接new一个RestClient来使用,正常业务量不大的时候是没问题的,如果业务量大了这里就会导致线程数过高最终导致线程中止
延伸:静态变量与单例
静态变量:众所周知静态变量只会初始化一次,声明时开辟内存空间知道程序结束,所有单例共享该空间
单例:所有实例指针地址都是同一个,是同一块内存空间
测试:
using System;
namespace ERP.JK.Util
{
class Student
{
private static Student _Instance;
public static Student Instance
{
get
{
if (_Instance==null)
{
_Instance = new Student();
}
return _Instance;
}
}
public int Age;
}
class Program
{
private static Student student = new Student();
private static Student student2 = new Student();
static void Main(string[] args)
{
try
{
Student s1 = Student.Instance;
s1.Age = 10;
unsafe
{
fixed (int* p = &s1.Age)
{
Console.WriteLine("Address:0x{0:x},value:{1}", (int)p,s1.Age);
}
}
Student s2 = Student.Instance;
s1.Age = 20;
unsafe
{
fixed (int* p = &s2.Age)
{
Console.WriteLine("Address:0x{0:x},value:{1}", (int)p, s2.Age);
}
}
student.Age = 30;
unsafe
{
fixed (int* p = &student.Age)
{
Console.WriteLine("Address:0x{0:x},value:{1}", (int)p, student.Age);
}
}
student2.Age = 40;
unsafe
{
fixed (int* p = &student2.Age)
{
Console.WriteLine("Address:0x{0:x},value:{1}", (int)p, student2.Age);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
}
}
运行结果:
- 可以看出s1,s2里面的Aage地址都是一样的
- student 与student2 因为分别实例并且存储在静态变量中,所以地址不一样