Как стать автором
Обновить

Занимательная задача с микросервисами в .NET

Время на прочтение3 мин
Количество просмотров8.6K

Необходимо реализовать возможность приёма транзакций от разных клиентов для процессинга и дальнейшей отправки в разные банки. Клиенты могут присылать как равномерно (например, по 1шт в секунду), так и большими пачками (1000шт каждый час или 10000 раз в день), банки обрабатывают транзакции последовательно.

Для простоты интеграции необходимо использовать REST API для приёма транзакций

Необходимо исключить ситуации, когда:

Тысячи клиентов по несколько транзакции ожидают двух, у которых по 10000 транзакций

Несколько клиентов по 10000 ждут тысячи клиентов по несколько транзакций.


Ок, нужно реализовать сервис который обрабатывает транзакции

Первым делом, для клиентов у которых меньше 100 транзакций в запросе использовать отдельный инстанс сервиса, масштабировать горизонтально.

[Route("api/[controller]")]
[ApiController]
public class ProcessController : ControllerBase
{
    [HttpPost("Queue")]
    public async Task<IActionResult> Queue([FromBody] RequestDTO request)
    {
        // Что-то вроде балансировки нагрузки
        var requestUri = request.TransactionsCount < 100
            ? $"http://instance1:81/api/Process/Queue"
            : $"http://instance2:81/api/Process/Queue";

        HttpClient client = new HttpClient();
        var result = await client.PostAsJsonAsync(requestUri, request); 
        var content = await result.Content.ReadAsStringAsync();
        return Ok(content);
    }
}

Да, но в случае, когда есть 3 клиента (Клиент 1: 10000 транзакций), (Клиент 2: 1000 транзакций), (Клиент 3: 100 транзакций) третий клиент будет ожидать пока выполнятся все 11000 транзакций первых двух клиентов

Может обрабатывать сперва запросы у которых меньше транзакций?

Тогда в случае, когда 1000 клиентов (Клиент 1: 10000 транзакций), (Клиент 2-500: 1000 транзакций), (Клиент 501 - 1000: 100 транзакций), Клиент 1 будет ожидать пока обработаются все мелкие запросы. Вариант увеличить мощность машины в котором инстанс для больших запросов, масштабировав вертикально тоже отметается.

Тогда придется добавить все запросы в очередь (или группировать по клиентам, или по другому параметру) и выполнять транзакции по очереди с каждого запроса. Это, по моему мнению, самый справедливый вариант для клиентов, так как клиент не просто ждет пока дойдет его очередь, а постепенно получает callback от выполненных транзакций

if (Requests.Any())
{
    // С каждого запроса выполняем одну транзакцию
    List<Task> tasks = new List<Task>();
    foreach(var request in Requests.ToList())
    {
        // имитируем обработку транзакции
        tasks.Add(TransactionProcess());
        request.TransactionsCount--;
        // имитируем callback
        logger.LogCritical($"[Client: {request.Client}] left {request.TransactionsCount} transactions");
        if(request.TransactionsCount == 0)
        {
            // Если все транзакции клиента выполнены, удаляем запрос из очереди
            Requests.Remove(request);
        }
    }
    // Выполняем транзакции одного цикла параллельно
    await Task.WhenAll(tasks);
}
3 запроса по 1, 3 и 6 транзакций и порядок их выполнения
3 запроса по 1, 3 и 6 транзакций и порядок их выполнения

А потом пакуем приложение с помощью docker compose. Результат тут

Тут мы можем увидеть, что для каждого клиента выполняется по одной транзакции:

3 клиента по 10000, 1000 и 500 транзакций в одном запросе в контейнере instance2-1
3 клиента по 10000, 1000 и 500 транзакций в одном запросе в контейнере instance2-1

А тут, то что "Load balancer" перенаправляет запросы с менее 100 транзакциями в первый инстанс:

Запрос четвертого клиента, у которого всего 90 транзакций (меньше 100) обрабатывается в отдельном контейнере instance1-1
Запрос четвертого клиента, у которого всего 90 транзакций (меньше 100) обрабатывается в отдельном контейнере instance1-1

Предлагайте как еще можно улучшить решение. Также предлагайте другие задачи на тему микросервисов

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 8: ↑2 и ↓6-2
Комментарии31

Публикации

Истории

Работа

Ближайшие события

One day offer от ВСК
Дата16 – 17 мая
Время09:00 – 18:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область