我们有一个使用dotnet core 2.2的API应用程序,该应用程序使用nginx部署在ubuntu服务器中,该服务器对第3方api进行批量请求。我们不确定请求背后到底发生了什么,但是我们的自定义记录器指出了使用hangfire的批处理模块中发生的异常。
发生的事情是,批处理将通过任务执行多个请求,并且当作业失败时,无论何时我们向API提出请求,都会使整个应用程序崩溃,并出现502网关超时状态错误。
代码
FetchPrices
try
{
var tasks = new List<Task<Price>>
{
//BTC
Task.Run(async () => { return await GetPrice(CurrencyType.USD, CryptoCurrencyType.BTC); }),
Task.Run(async () => { return await GetPrice(CurrencyType.EUR, CryptoCurrencyType.BTC); }),
Task.Run(async () => { return await GetPrice(CurrencyType.JPY, CryptoCurrencyType.BTC); }),
Task.Run(async () => { return await GetPrice(CurrencyType.CNY, CryptoCurrencyType.BTC); }),
//ETH
Task.Run(async () => { return await GetPrice(CurrencyType.USD, CryptoCurrencyType.ETH); }),
Task.Run(async () => { return await GetPrice(CurrencyType.EUR, CryptoCurrencyType.ETH); }),
Task.Run(async () => { return await GetPrice(CurrencyType.JPY, CryptoCurrencyType.ETH); }),
Task.Run(async () => { return await GetPrice(CurrencyType.CNY, CryptoCurrencyType.ETH); }),
};
var results = await Task.WhenAll(tasks);
using (var transaction = _priceRepository.BeginTransaction())
{
Saving to DB
}
}
catch (Exception e)
{
//The exception from GetPrice will be logged here
_logger.WriteLogs(_appSettings.AssetRootPath, _appSettings.LogFilePrefix, "Batch", "AggregateExchange", null, e.Message, e.StackTrace, null);
}
GetPrice函数
var tasks = new List<Task<PriceDetails>>();
var ticker = new Ticker();
var currencyStr = Enum.GetName(typeof(CurrencyType), type);
var btcStr = Enum.GetName(typeof(CryptoCurrencyType), CryptoCurrencyType.BTC);
var ethStr = Enum.GetName(typeof(CryptoCurrencyType), CryptoCurrencyType.ETH);
var currency = c_type == CryptoCurrencyType.BTC ? $"{btcStr}-{currencyStr}" : c_type == CryptoCurrencyType.ETH ? $"{ethStr}-{currencyStr}" : $"{bceStr}-{currencyStr}";
tasks.Add(Task.Run(async () => { return await GetPriceDetails(currency, PriceType.Spot); }));
if (c_type != CryptoCurrencyType.BCE)
{
tasks.Add(Task.Run(async () => { return await GetPriceDetails(currency, PriceType.Sell); }));
tasks.Add(Task.Run(async () => { return await GetPriceDetails(currency, PriceType.Buy); }));
}
var results = await Task.WhenAll(tasks); //An error occurs here
GetPriceDetails函数
var JsonObj = string.Empty;
var partialUrl = string.Empty;
if (type == PriceType.Buy)
{
partialUrl = string.Format(_appSettings.BuyPriceApi, currency);
}
else if (type == PriceType.Sell)
{
partialUrl = string.Format(_appSettings.SellPriceApi, currency);
}
else
{
partialUrl = string.Format(_appSettings.SpotPriceApi, currency);
}
JsonObj = await _apiRequest.SendCoinbaseRequest(
HttpMethod.Get,
_appSettings.CoinbaseRoot,
partialUrl,
_appSettings.ApiKey,
_appSettings.ApiSecret
);
var res = JsonConvert.DeserializeObject<PriceReceiver>(JsonObj);
return res.Data;
是否需要考虑任何可能导致服务器超时的输入?
我们要做的是再次重建并重新发布api,但是它再次发生。我们认为该函数的catch方法中的throw异常行是导致API崩溃的那一行,但是即使将其删除,它仍然会崩溃。
这是实际的例外情况。
System.IO.IOException
Too many open files
System.IO.IOException: Too many open files
at Infrastructure.Base.ErrorLogger.WriteLogs(String rootPath, String filePrefix, String controller, String action, String request, String exceptionType, String logErrorMessage, String jwtToken) in /home/exchange/exchange-api/staging/bigcatman-api/BOE.Core/Infrastructure/Base/ErrorLogger.cs:line 48
at Service.Batch.Implementation.AggregateExchange.FetchPrices() in /home/exchange/exchange-api/staging/bigcatman-api/BOE.Core/Service/Batch/Implementation/AggregateExchange.cs:line 179
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)