У нас есть приложение API с использованием dotnet core 2.2, развернутое на сервере Ubuntu с использованием nginx, которое выполняет пакетный запрос к стороннему API. Мы не уверены, что на самом деле происходит за запросом, но наш пользовательский регистратор указывает исключение, которое происходит внутри пакетного модуля, который использует hangfire.
То, что происходит, - это то, что пакет будет выполнять несколько запросов через задачу, и, если задание не будет выполнено, произойдет аварийное завершение всего приложения с ошибкой состояния тайм-аута 502 при каждом запросе к API.
Код
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 снова, но это повторяется. Мы подумали, что строка исключения throw в методе catch функции - это та, которая вызывает аварийное завершение 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)