.net core 数据迁移到服务结构有状态服务

.net core 数据迁移到服务结构有状态服务,.net-core,service-fabric-stateful,azure-service-fabric,.net Core,Service Fabric Stateful,Azure Service Fabric,我有一个有状态的服务,它存储了一组关于我用户的数据,这些数据存储在一个可靠的字典中,并且显然也从那里检索数据 然而,我也有一个SQL数据库用来存储这些信息。在初始化新的有状态服务实例时,我需要将该信息从SQL数据库迁移到新的可靠存储机制中。从那时起,有状态的服务就是真理的源泉。理想情况下,我希望延迟有状态服务的可用性,直到初始化过程完成 对于如何做到这一点,有什么建议吗?像does这样的方法可以做到: public interface IStateful1 : IService { Ta

我有一个有状态的服务,它存储了一组关于我用户的数据,这些数据存储在一个可靠的字典中,并且显然也从那里检索数据

然而,我也有一个SQL数据库用来存储这些信息。在初始化新的有状态服务实例时,我需要将该信息从SQL数据库迁移到新的可靠存储机制中。从那时起,有状态的服务就是真理的源泉。理想情况下,我希望延迟有状态服务的可用性,直到初始化过程完成


对于如何做到这一点,有什么建议吗?

像does这样的方法可以做到:

public interface IStateful1 : IService
{
    Task MyMethod();
}

internal sealed class Stateful1 : StatefulService, IStateful1
{
    private bool isReady = false; 

    public Stateful1(StatefulServiceContext context)
        : base(context)
    { }

    public Task MyMethod()
    {
        if(!isReady)
            throw new NotImplementedException(); // Probably throw or return something more meaningful :-) 

        return Task.CompletedTask; // Do your thing here
    }

    protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
    {
        return new ServiceReplicaListener[0];
    }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        await Task.Run(() => {
            // Simulation of some work
            Thread.Sleep((int)TimeSpan.FromMinutes(5).TotalMilliseconds);
        });

        isReady = true;
    }
}  
公共接口IStateful1:iSeries设备
{
任务MyMethod();
}
内部密封类Stateful1:StatefulService,IStateful1
{
私有bool isReady=false;
public Stateful1(StatefulServiceContext上下文)
:基本(上下文)
{ }
公共任务MyMethod()
{
如果(!isReady)
抛出新的NotImplementedException();//可能抛出或返回更有意义的内容:-)
return Task.CompletedTask;//在这里做你的事情
}
受保护的重写IEnumerable CreateServiceReplicaListeners()
{
返回新的ServiceReplicaListener[0];
}
受保护的覆盖异步任务RunAsync(CancellationToken CancellationToken)
{
等待任务。运行(()=>{
//某些工作的模拟
睡眠((int)TimeSpan.FromMinutes(5).Total毫秒);
});
isReady=真;
}
}  
在此设置中,通过
RunAsync
方法将数据库导入可靠集合

不幸的是,抱歉,没有办法在以后插入通信侦听器。这将使事情变得更容易

如果
CreateServiceReplicaListeners
将是一个异步操作,我们可以在这里等待初始化任务,但现在不能。使用
.Wait()
将不起作用,因为它将报告实例运行时间过长,并将实例标记为不健康


有关服务生命周期的完整概述,请参见

我不确定您是否理解正确。但是根据您的评论,我建议使用以下解决方案在迁移期间返回“notready”响应

public interface IMigrationService
{
    bool IsDone();
}

public class MigrationService : IMigrationService
{
    private bool migrating = tu;

    public bool BeginMigration()
    {
        this.migrating = true;
    }
    public bool EndMigration()
    {
        this.migrating = false;
    }
    public bool IsDone()
    {
        return this.migrating;
    }
}

// WebHost startup class
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Register a middle-ware that would short circuit responses
        // while migration is in progress.
        app.Use(
            async (context, next) =>
            {
                var migrationService = 
                    context.RequestServices.GetService<IMigrationService>();
                if (!migrationService.IsDone())
                {
                    /* short circuit the response with approriate error message */
                }

                await next();
            });

        app.UseMvc();
    }
}

public class Stateful : StatefulService
{
    private readonly IMigrationService migrationService;

    public Stateful(StatefulServiceContext context)
      : base(context)
    { 
        this.migrationService = new MigrationService();
    }

    protected override IEnumerable<ServiceReplicaListener>
        CreateServiceReplicaListeners()
    {
        /* 
            Create a listener here with WebHostBuilder

            Use Startup class with the middle-ware defined and 
            add configure services -> .ConfigureServices() 
            with services.AddSingleton<IMigrationService>(this.migrationService)
        */
    }

    protected override async Task 
        RunAsync(CancellationToken cancellationToken)
    {
        this.migrationService.StartMigration();

        /* Migration code */

        this.migrationService.EndMigration();
    }
}
公共接口IMiglationService
{
bool-IsDone();
}
公共类迁移服务:IMiglationService
{
私有bool=tu;
公共bool BeginMigration()
{
这是真的;
}
公共布尔迁移()
{
this.migrating=false;
}
公共广播IsDone()
{
把这个还给我;
}
}
//WebHost启动类
公营创业
{
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
//注册一个会使响应短路的中间件
//在迁移过程中。
应用程序。使用(
异步(上下文,下一步)=>
{
var migrationService=
context.RequestServices.GetService();
如果(!migrationService.IsDone())
{
/*用适当的错误消息短接响应*/
}
等待下一个();
});
app.UseMvc();
}
}
公共类有状态:有状态服务
{
私有只读IMiglationService迁移服务;
public Stateful(StatefulServiceContext上下文)
:基本(上下文)
{ 
this.migrationService=新的migrationService();
}
受保护覆盖IEnumerable
CreateServiceReplicaListeners()
{
/* 
使用WebHostBuilder在此处创建侦听器
在定义了中间件的情况下使用Startup类
添加配置服务->.ConfigureServices()
使用services.AddSingleton(this.migrationService)
*/
}
受保护的重写异步任务
RunAsync(CancellationToken CancellationToken)
{
this.migrationService.StartMigration();
/*迁移代码*/
this.migrationService.EndMigration();
}
}
这将允许您推出新版本的服务,该服务将在迁移过程中使用适当的错误消息短路所有请求


希望这能有所帮助。

如果在尚未导入状态的情况下调用服务时仅返回错误状态或引发异常,是否可以接受?这是迄今为止最容易实现的。或者您可以尝试使用一个任务或TaskCompletionSource,在打开通信侦听器之前等待该任务。@PeterBons-是的,我很乐意该服务返回“未就绪”或类似的异常(如SF当前所做的)。我应该按照您的建议在服务中覆盖哪个功能?