【问题标题】:Sending request to ASP.Net Core Web API running on a specific node in a Service Fabric Cluster向 Service Fabric 群集中特定节点上运行的 ASP.Net Core Web API 发送请求
【发布时间】:2018-07-15 03:51:44
【问题描述】:

我正在开发一个 Service Fabric 应用程序,我在其中运行我的应用程序,其中包含一堆 ASP.NET Core Web API。现在,当我在配置有 5 个节点的本地服务结构集群上运行我的应用程序时,应用程序成功运行,并且我能够发送发布请求公开的 Web API。实际上,我想通过对该特定节点上公开的 API 的不同发布请求来命中在同一集群节点上运行的代码。

为了进一步解释,例如在节点“0”上公开了一个 API,它接受一个发布请求并执行一个作业,还有一个 API 可以中止正在运行的作业。现在,当我请求执行作业时,它开始在节点“0”上执行,但是当我尝试中止作业时,服务结构集群将请求转发到另一个节点,例如节点“1”。结果我无法中止正在运行的作业,因为节点“1”上没有可用的正在运行的作业。我不知道如何处理这种情况。

对于状态,我正在使用 ASP.Net Core Web API 类型的无状态服务,并在我的本地服务结构集群的 5 个节点上运行该应用程序。

请建议最好的方法。

【问题讨论】:

    标签: c# azure-service-fabric service-fabric-stateless


    【解决方案1】:

    您的问题是因为您正在运行 API 来执行 Worker 任务。

    您应该使用您的 API 在后台(Process\Worker)中安排工作,并向用户返回一个令牌或操作 ID。用户将使用此令牌来请求状态或取消任务。

    第一步:当你第一次调用你的API时,你可以生成一个GUID(或插入DB)并将这条消息放入队列中(即:Service Bus),然后将 GUID 返回给调用者。

    第二步:一个工作进程将在您的集群中运行,侦听来自该队列的消息,并在消息到达时处理这些消息。您可以将其设为在循环中逐条处理消息的单线程服务,或者将其设为对每条消息使用一个线程处理多条消息的多线程服务。这将取决于您想要的复杂程度:

    • 在单线程侦听器中,要扩展您的应用程序,您必须跨越多个实例,以便多个任务并行运行,您可以在 SF 中使用简单的缩放命令执行此操作,SF 将分发服务实例跨可用节点。

    • 1234563 /p>

    第三步,取消: 取消过程很简单,有很多方法:

    • 使用类似的方法将取消消息排入队列
      • 您的服务将在单独的线程中侦听取消并取消正在运行的任务(如果正在运行)。
      • 使用不同的队列发送取消消息会更好
      • 如果运行多个侦听器实例,您可能会考虑使用主题而不是队列。
    • 使用缓存键存储作业状态并检查每次迭代是否已请求取消。
    • 带有作业状态的表,您可以在其中检查每次迭代,就像使用缓存键一样。
    • 创建远程端点以直接调用服务并触发取消令牌。

    有很多方法,这些都很简单,您可以结合使用多种方法来更好地控制您的任务。

    【讨论】:

    • 我的服务有两个公开的 Web API,一个正在执行作业,另一个正在中止正在运行的作业。现在,由于异步编程,作业总是在新线程中运行,即 System.Threading.Task。现在,当一个新的中止作业请求到达时,它会被转发到集群中不存在实际运行线程的不同节点。我认为将 guid 存储在 db 或某处并检索将不起作用,因为该作业在单独线程中该节点的本地内存中运行。现在更清楚了吗?
    • 这就是为什么它不起作用,同一个进程必须处理取消请求,因为你有两个 API(如果我理解正确的话)每个都将在不同的进程中运行。
    • 是的,现在我想解决这个问题。我正在考虑可能的解决方案,我可以将来自正在运行的服务实例的请求转发到另一个正在运行的服务实例,即到不同的节点吗?或者我可以向特定节点发送请求吗?在这种情况下,当一个服务实例执行一项作业时,它会将一些特定于节点的数据存储在数据库或某处,当用户想要中止作业时,他/她将发送中止对该特定节点的请求?这是真正的问题。
    • 这个帖子似乎还没有更新结论。 @starklord 你有没有成功实现你的目标?
    • 很遗憾还没有。
    【解决方案2】:

    您需要一些存储空间才能做到这一点。

    创建一个表(例如JobQueue)。在开始处理作业之前,您将存储在数据库中,存储状态(例如 Running,它可以是一个枚举),然后将 ID 返回给调用者。一旦您需要中止/取消作业,您可以从 API 调用 abort 方法,发送您想要中止的 ID。在 abort 方法中,您只需将作业的状态更新为 Aborting。在第一个方法(运行作业)中,您需要在一段时间内检查此表,如果它是 aborting,则停止作业(并将状态更新为 Aborted )。或者,您可以在作业中止或完成后从数据库中删除。

    或者,如果您希望数据是临时的,您可以使用第六台服务器作为缓存服务器并将数据存储在那里。这个缓存服务器也可以是一个集群服务器,但是你需要使用类似Redis的东西。

    【讨论】:

    • 实际上,我已经完全开发了用于运行和中止作业的 REST API,它们不仅可以更新数据库中的状态,还可以维护运行代码中的线程。这里我的意思是,当一个作业正在执行时,它在多个线程上运行,通过中止它,我也想中止那些正在运行的线程。因此,我必须将中止请求发送到该特定节点。我已经开发了我的应用程序,但现在要在其中进行如此大的更改有点困难。
    • @Anonymous 我了解,但我建议您不要尝试访问特定节点,使用集群的目的是将它们用作一台服务器(无论哪个节点正在执行过程)。您应该使运行长时间运行的作业的代码检查数据库中作业的状态(包括在许多线程中运行的代码),如果它被标记为停止,则停止它。
    猜你喜欢
    • 2023-04-04
    • 2017-09-27
    • 2016-05-12
    • 2017-03-13
    • 2016-09-04
    • 2016-09-28
    • 1970-01-01
    • 2020-09-22
    • 2016-12-12
    相关资源
    最近更新 更多