เรามีสแต็กแบ็กเอนด์ที่เน้นไมโครเซอร์วิส ไมโครเซอร์วิสทั้งหมดที่สร้างขึ้นบน Nancy
และลงทะเบียนเป็นบริการ windows ด้วย topshelf
หนึ่งในบริการที่จัดการการรับส่งข้อมูลส่วนใหญ่ (~ 5,000 ความต้องการ/วินาที) เริ่มมีปัญหาการขาดแคลนเธรดพูลบนเซิร์ฟเวอร์ 3 ใน 8 เครื่อง
นี่คือข้อยกเว้นที่เราได้รับเมื่อเข้าถึงจุดสิ้นสุดเฉพาะ:
System.InvalidOperationException: There were not enough free threads in the ThreadPool to complete the operation.
at System.Net.HttpWebRequest.BeginGetResponse(AsyncCallback callback, Object state)
at System.Net.Http.HttpClientHandler.StartGettingResponse(RequestState state)
at System.Net.Http.HttpClientHandler.StartRequest(Object obj)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at RandomNamedClient.<GetProductBySkuAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ProductService.<GetBySkuAsync>d__3.MoveNext() in ...\ProductService.cs:line 34
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ProductModule.<>c__DisplayClass15.<<.ctor>b__b>d__1d.MoveNext() in ...\ProductModule.cs:line 32
ตำแหน่งข้อมูลนี้เรียกใช้บริการอื่นซึ่งอยู่นอกโดเมนของทีมของฉัน เพื่อรับข้อมูลผลิตภัณฑ์ การนำไปปฏิบัติดังต่อไปนี้:
Get["/product/sku/{sku}", true] = async (parameters, ctx) =>
{
string sku = parameters.sku;
var product = await productService.GetBySkuAsync(sku);
return Response.AsJson(new ProductRepresentation(product));
};
ProductService.GetBySkuAsync(string sku)
การใช้งาน:
public async Task<Product> GetBySkuAsync(string sku)
{
var productDto = await randomNamedClient.GetProductBySkuAsync(sku);
if (productDto == null)
{
throw new ProductDtoNotFoundException("sku", sku);
}
var variantDto = productDto.VariantList.FirstOrDefault(v => v.Sku == sku);
if (variantDto == null)
{
throw new ProductVariantDtoNotFoundException("sku", sku);
}
return MapVariantDtoToProduct(variantDto, productDto);
}
RandomNamedClient.GetProductBySkuAsync(string sku)
การใช้งาน (มาจากแพ็คเกจภายใน):
public async Task<ProductDto> GetProductBySkuAsync(string sku)
{
HttpResponseMessage result = await this._serviceClient.GetAsync("Product?Sku=" + sku);
return result == null || result.StatusCode != HttpStatusCode.OK ? (ProductDto) null : this.Decompress<ProductDto>(result);
}
RandomNamedClient.Decompress<T>(HttpResponseMessage response)
การใช้งาน:
private T Decompress<T>(HttpResponseMessage response)
{
if (!response.Content.Headers.ContentEncoding.Contains("gzip"))
return HttpContentExtensions.ReadAsAsync<T>(response.Content).Result;
using (GZipStream gzipStream = new GZipStream((Stream) new MemoryStream(response.Content.ReadAsByteArrayAsync().Result), CompressionMode.Decompress))
{
byte[] buffer = new byte[8192];
using (MemoryStream memoryStream = new MemoryStream())
{
int count;
do
{
count = gzipStream.Read(buffer, 0, 8192);
if (count > 0)
memoryStream.Write(buffer, 0, count);
}
while (count > 0);
return JsonConvert.DeserializeObject<T>(Encoding.UTF8.GetString(memoryStream.ToArray()));
}
}
}
บริการทั้งหมดของเราสร้างขึ้นเป็น Release/32-bit เราไม่ได้ปรับแต่งอะไรเกี่ยวกับการใช้เธรดพูล