如何在Azure服务结构中迁移Windows服务

时间:2017-01-10 12:36:02

标签: azure azure-service-fabric

我想使用Service fabric将使用.net编写的典型Windows服务迁移到Azure。

为了实现这一点,我创建了一个服务结构应用程序,其中包含一个微服务作为来宾可执行文件,它使用.exe的Windows服务并将应用程序包部署到服务结构集群。

在群集上部署服务架构应用程序后,我希望Windows服务应该安装&然后在所有节点上自动启动,但应用程序在任何单个节点上运行。我希望Windows服务一次只能在一个节点上运行。

请帮助实现这一点。

2 个答案:

答案 0 :(得分:3)

您当然可以将您的服务作为来宾可执行文件运行。确保它只在一个节点上运行可以通过在清单中将实例计数设置为1来完成,如下所示:

  <Parameters>
    <Parameter Name="GuestService_InstanceCount" DefaultValue="-1" />
  </Parameters>
  ...
  <DefaultServices>
    <Service Name="GuestService">
      <StatelessService ServiceTypeName="GuestServiceType" 
                        InstanceCount="[GuestService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>

或者,您实际上可以迁移它,而不仅仅是在SF环境中重新托管它......

如果您的Windows服务是用.NET编写的,并且您不想从Service Fabric中受益,那么将代码从Windows服务迁移到Service Fabric中的可靠服务的工作不应该太大。

基本服务示例:

如果您首先在Service Fabric应用程序中创建无状态服务,最终会得到一个看起来像的服务实现(删除注释):

internal sealed class MigratedService : StatelessService
{
    public MigratedService(StatelessServiceContext context)
        : base(context)
    { }

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new ServiceInstanceListener[0];
    }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        // TODO: Replace the following sample code with your own logic 
        //       or remove this RunAsync override if it's not needed in your service.
        long iterations = 0;
        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ServiceEventSource.Current.ServiceMessage(this.Context, "Working-{0}", ++iterations);
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
        }
    }

只要服务启动并在群集中的节点上运行,RunAsync方法就会开始运行。它将继续运行,直到群集由于某种原因决定停止服务,或将其移动到另一个节点。

在Windows服务代码中,您应该有一个在启动时运行的方法。这通常是您设置Timer或类似内容以开始连续执行某些操作的地方:

protected override void OnStart(string[] args)
{
  System.Timers.Timer timer = new System.Timers.Timer();
  timer.Interval = 60000; // 60 seconds
  timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
  timer.Start();
}

public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
    ...
    DoServiceStuff();
    Console.WriteLine("Windows Service says hello");
}

现在抓取OnTimer中的代码并将其放入RunAsync方法(以及您需要的任何其他代码)中:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();
        DoServiceStuff();
        ServiceEventSource.Current.ServiceMessage(this.Context, 
            "Reliable Service says hello");
        await Task.Delay(TimeSpan.FromSeconds(60), cancellationToken);
    }
}

请注意Task.Delay(...),它应设置为与Windows服务Timer相同的时间间隔。

现在,如果您已登录Windows服务并使用ETW,那么这应该是开箱即用的。您现在只需设置一些从Azure查看这些日志的方法,例如使用Log Analytics(https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-service-fabric)。

您可能必须迁移的其他事项是,如果您在关闭,继续时运行特定代码,并且在启动时有任何参数发送到服务(例如连接字符串到数据库)。那些需要转换为服务的配置设置,请查看SO 33928204作为起点。

答案 1 :(得分:1)

服务结构背后的理念是管理您的服务,从部署和运行。一旦将服务/应用程序部署到服务结构实例,它就像运行Windows服务(有点),因此您不需要安装Windows服务。如果您正在使用类似TopShelf的东西,您可以运行exe,一切都将在服务结构中完全运行。