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

Posted

技术标签:

【中文标题】如何在 Azure 服务结构中迁移 Windows 服务【英文标题】:How To migrate windows service in Azure service fabric 【发布时间】:2017-05-24 22:54:21 【问题描述】:

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

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

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

请帮助实现这一点。

【问题讨论】:

您可以为您的服务指定实例计数为 1。另请阅读:***.com/a/39786939/5946937 【参考方案1】:

您当然可以将您的服务作为来宾可执行文件运行。确保它只在一个节点上运行可以通过在清单中将实例计数设置为 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 应用程序中创建无状态服务,您最终会得到一个看起来像(已删除 cmets)的服务实现:

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 以了解其起点。

【讨论】:

我知道这是一个有点老的问题,但我在迁移时遇到了同样的问题。缺少的一件事是如何从on shutdown 迁移代码。现在,当我优雅地停止我的服务时,它首先在关闭之前结束它的工作(我打电话给RequestAdditionalTime)。同样的事情适用于面料吗?例如,我希望我的 PDF 在我的服务停止之前完成生成。 SF 不一样。该服务将连续循环运行,直到取消。取消可能有多种原因(SF 正在更改您的副本角色、代码升级、节点崩溃等)。上面代码中的cancellationToken.ThrowIfCancellationRequested() 点是您可以尝试打包并完成正在进行的工作负载(例如PDF 生成)的点。【参考方案2】:

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

【讨论】:

以上是关于如何在 Azure 服务结构中迁移 Windows 服务的主要内容,如果未能解决你的问题,请参考以下文章

MS SQL Server迁移至SQL Azure

如何从 Azure Devops 服务器迁移到 Azure Devops 服务中的现有组织

如何将现有 Azure 资产迁移到 Azure 应用服务

为 CakePHP Web 应用程序将 phpMyAdmin 数据库迁移到 Windows Azure

如何在 Azure 的 ConfigurationManager.ConnectionStrings 上使用 ConnectionStrings 创建 EF 迁移?

如何将 TFVC 项目从 Azure DevOps 服务器迁移到新的 Azure DevOps 帐户作为 Git 存储库