我在ASP.NET核心运行Hangfire。对于我们的其他项目,我们有在进行API调用时传递的CorrelationIds,以便能够链接调用者和被调用者。我们在TraceIdentifier内核中使用IHttpContextAccessor的ASP.NET。
不幸的是,ASP.NET Core在瞬态IHttpContextAccessor中获取作用域CorrelationId的技巧看起来并不适用于Hangfire作业执行。使用限定作用域的状态关联对象不能工作,因为它必须是瞬态的,才能与系统的其他部分(日志记录等)一起工作。
过去,我可以使用ServiceLocator反模式并在瞬态服务中解析作用域状态对象。在最新的ASP.NET内核中,它不再受支持,并且抛出了一个异常,这使得系统速度太慢,因为抛出了大量的异常。
有没有Hangfire已经提供的东西可以给我每个作业执行一个唯一的ID?
干杯。
发布于 2022-02-15 13:26:00
感谢jbl的评论,我再次审视了自己正在做的事情,并设法让它通过一个模棱两可的方法来工作。
我得到了瞬态保持器(基本上是重命名的HttpContextAccessor类):
public class StateHolder
{
private static AsyncLocal<ContextHolder> _contextCurrent = new AsyncLocal<ContextHolder>();
public string State {
get {
return _contextCurrent.Value?.Context;
}
set {
var holder = _contextCurrent.Value;
if (holder != null)
{
holder.Context = null;
}
if (value != null)
{
_contextCurrent.Value = new ContextHolder { Context = value };
}
}
}
private class ContextHolder
{
public string Context;
}
}然后在Hangfire我把它连接到激活
public class LoggingActivator : JobActivator
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ContextAccessor _contextAccessor;
public LoggingActivator([NotNull] IServiceScopeFactory serviceScopeFactory, ContextAccessor contextAccessor)
{
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
_contextAccessor = contextAccessor;
}
public override JobActivatorScope BeginScope(JobActivatorContext context)
{
return new LoggingActivatorScope(_serviceScopeFactory.CreateScope(), _contextAccessor);
}
}和
public class LoggingActivatorScope : JobActivatorScope
{
private readonly IServiceScope _serviceScope;
private readonly ContextAccessor _contextAccessor;
public LoggingActivatorScope(
[NotNull] IServiceScope serviceScope,
ContextAccessor contextAccessor)
{
_serviceScope = serviceScope ?? throw new ArgumentNullException(nameof(serviceScope));
_contextAccessor = contextAccessor;
}
public override object Resolve(Type type)
{
_contextAccessor.Context = Guid.NewGuid().ToString();
return ActivatorUtilities.GetServiceOrCreateInstance(_serviceScope.ServiceProvider, type);
}
public override void DisposeScope()
{
_serviceScope.Dispose();
}
}看上去挺好的。
https://stackoverflow.com/questions/71122602
复制相似问题