Swi*_*386 5 c# restsharp async-await docker asp.net-core-mvc
我正在编写一个搜索 API,它使用 async-await 和 awaiting Task.WhenAll 聚合来自许多微服务 API 的结果。我最多对 Search API 的每个请求进行 11 次微服务 API 调用。但是,我看到性能不一致 - 有时 Search API 需要 400 毫秒(可接受),而其他的则需要 1 秒以上(不可接受),即使我在本地运行/无负载时也是如此。大部分放缓似乎发生在 await Task.WhenAll 周围。
三个观察:
搜索 API 有时会启动对微服务 API 的 1/3 或 1/2 调用,然后等待 600-1000 毫秒以启动下一组调用。这种批处理行为是不一致的。
搜索 API 有时会调用每个微服务 API,获取结果并再等待 500-1000 毫秒。例如,Search API 可能需要 1000 毫秒,所有微服务请求都在 100 毫秒内开始,并在 400 毫秒或更短的时间内在内部完成。但是,在响应全部发回后,搜索 API 只会继续在 WhenAll 上停留 500 毫秒。
这种行为是不一致的。如果我运行 30 次,可能其中 5 或 10 次相对于其他 25 或 20 次需要超长的时间。
所有 API 都是用 ASP.NET Core MVC 编写的,在单个 docker 网络上的 Linux Docker 容器中运行(应该是彼此本地的),并且是异步的。
在每个 API 中,我都会记录传入请求的持续时间,因此我可以全面了解跨应用程序的整个请求的时间和持续时间。
我试过的步骤
http 客户端是 RestSharp,但我尝试用 .NET 的 HttpClient 替换,没有任何实质性区别。
尝试使用 Parallel.ForEach 实际上速度较慢。
尝试将单个微服务 API 控制器更改为不进行任何处理 - 立即返回一个没有正文的 200 - 但仍然获得相同的行为。
控制器
[HttpGet("get-something")]
public async Task<IEnumerable<int>> GetSomethingAsync(int id)
{
//search engine is a scoped dependency injected via DI
return await _searchEngine.Search(id);
}
Run Code Online (Sandbox Code Playgroud)
搜索引擎
public async Task<IEnumerable<int>> Search(int id)
{
//both clients are transient dependencies injected via DI
var iceTasks = _iceClient.FetchTasksAsync(id).ToList();
var fireTasks = _fireClient.FetchTasksAsync(id).ToList();
var results = await Task.WhenAll(iceTasks.Union(fireTasks));
return results.SelectMany(r => r.Data);
}
Run Code Online (Sandbox Code Playgroud)
IceClient 和 FireClient 基类
public List<Task<IRestResponse<IEnumerable<int>>>> FetchTasksAsync(int id)
{
var taskList = new List<Task<IRestResponse<IEnumerable<int>>>>();
var restClient = new RestClient()
{
Timeout = 20000 //in ms
};
foreach (var url in _urlFactory.Create())
{
var task = restClient.ExecuteGetTaskAsync<IEnumerable<int>>(new RestRequest(url));
taskList.Add(task);
}
return taskList;
}
Run Code Online (Sandbox Code Playgroud)
期望 每个 API 调用都应该在 30 ms 内彼此启动,并且总搜索持续时间大约是最长的微服务 API 持续时间的持续时间。
| 归档时间: |
|
| 查看次数: |
974 次 |
| 最近记录: |