HttpClient с проблемой параллелизма данных HttpMessageHandlerC#

Место общения программистов C#
Anonymous
HttpClient с проблемой параллелизма данных HttpMessageHandler

Сообщение Anonymous »

У меня есть микросервис, который интегрируется со сторонним сервисом посредством вызовов API. Чтобы справиться с интеграцией, я создал типизированный HttpClient с HttpMessageHandler, зарегистрированный как временный сервис для установки заголовков на основе входящего запроса (поскольку заголовки специфичны для вызывающего объекта). микросервис).
Вот поток:
  • Микросервис получает запрос в контроллер, где заголовки (определяющие учетная запись — система и клиент).
  • Контроллер вызывает типизированный HttpClient.
  • HttpClient отправляет запрос сторонней службе.
    HttpMessageHandler определяет информацию об учетной записи на основе полученного запроса и устанавливает заголовки для исходящего запроса.
  • Все запросы и ответы, включая информацию об учетной записи, передаются вошел в базу данных микросервиса.
Проблема:
Когда мы развернули микросервис в рабочей среде и начали обрабатывать несколько клиентов , мы столкнулись с проблемой параллелизма: данные для учетной записи X были зарегистрированы, но запрос к третьей стороне был обработан под учетной записью Y.
Чтобы разобраться в этой ситуации, я попробовал:
  • Я зарегистрировал информацию заголовков (учетную запись) в HttpMessageHandler до и непосредственно после отправки запроса
  • Я использую Serilog в качестве средства ведения журнала, поэтому я установил пакет NuGet serilog-httpclient и все записал в журнал.
  • Я использовал одноэлементный экземпляр HttpClient непосредственно из контроллера и использовал его в одном из API.
первый и второй способы всегда давали один и тот же результат, т.е. до и после запроса, отправленного третьей стороне, заголовки были правильными, но третья сторона отвечает ошибкой, что данные не существуют в аккаунте, хотя на самом деле они существуют . Однако, когда я выбрал третье решение, проблема перестала возникать в этом конкретном API, но в других API по-прежнему возникает та же проблема.
Я не уверен, связана ли проблема с параллелизм в моем коде или что-то еще. В журналах постоянно отображаются правильные заголовки, но каким-то образом запрос доходит до стороннего сервиса с неверной информацией об учетной записи. Может ли это быть проблемой параллелизма в моей службе или проблема связана со сторонней службой?
Вот мой код:
Startup.cs
services.AddScoped();

services.AddScoped();

services.AddTransient();

services.AddHttpClient(c =>
{
c.BaseAddress = new Uri(configuration["MyAPIUrl"]);
})
.LogRequestResponse(p =>
{
p.LogMode = LogMode.LogAll;
p.RequestHeaderLogMode = LogMode.LogAll;
p.RequestBodyLogMode = LogMode.LogAll;
p.ResponseHeaderLogMode = LogMode.LogAll;
p.ResponseBodyLogMode = LogMode.LogAll;
p.MaskedProperties.Clear();
})
.AddHttpMessageHandler();

MyController.cs
public class MyController : MyControllerBase
{
private readonly MyAPI _myAPI;

public MyController(MyAPI myAPI)
: base(serviceProvider)
{
_myAPI = myAPI;
}

[HttpGet("Status")]
public async Task GetStatusAsync(int myId)
{
try
{
var response = await _myAPI.GetContractAsync();

//rest of the code
}
catch (Exception ex)
{
return PrepareFailedCallResult(ex);
}
}
}

MyAuthenticationMessagehandler.cs
public class MyAuthenticationMessageHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;

public MyAuthenticationMessageHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}

protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var accountService = _httpContextAccessor.HttpContext.RequestServices.GetRequiredService();
var accountInfo = await accountService.GetAccountInfo();

request.Headers.Add(APIKeys.APIId, accountInfo.APIId);
request.Headers.Add(APIKeys.APIKey, accountInfo.APIKey);
request.Headers.Add(APIKeys.APIAuthorizationToken, accountInfo.APIAuthorizationToken);

return await base.SendAsync(request, cancellationToken);
}
}

AccountService.cs
public class AccountService : ApplicationServiceBase, IAccountService
{
private readonly IRepository _accountRepository;

public AccountService(IRepository accountRepository, IMapper mapper, IServiceProvider serviceProvider) : base(mapper, serviceProvider)
{
_accountRepository = accountRepository;
}

public async Task GetAccountInfo()
{
Expression predicate =
account =>
account.TenantId == Session.TenantId &&
account.SystemId == Session.SystemId;

var account = (await _accountRepository.All(predicate)).Select(a => _mapper.Map(a)).FirstOrDefault();
if (account == null)
throw new Exception($"Account with TenantId:{Session.TenantId}, SystemId:{Session.SystemId} is invalid");

return account;
}
}


Подробнее здесь: https://stackoverflow.com/questions/790 ... ency-issue

Вернуться в «C#»