【问题标题】:Best practice for load balanced Web API that uses shared long running processes?使用共享长时间运行进程的负载平衡 Web API 的最佳实践?
【发布时间】:2014-11-05 22:36:19
【问题描述】:

我正在构建一个支持记录来自 IP 连接设备的数据的平台。记录器使用专有 API 与连接的设备进行通信并将数据转储到数据库中。我正在使用 ASP.NET Web API 为每个记录器提供启动/停止功能。

在独立服务器环境中,我只需创建一个包含实时记录器列表的全局变量。但这在负载平衡的环境中不起作用。例如,用户 A 的发布请求进入 Web 2,它在 Web 2 上创建一个新的记录器(在数据库中记录 Web 2 有一个具有 X id 的活动记录器)。然后,用户 B 的删除请求进入 Web 5。该请求需要与 Web 2 通信才能真正关闭记录器。

是否有跟踪长时间运行的进程以及该进程在哪个 IIS 实例上运行的常见做法?是否有在负载平​​衡环境中的实例之间进行通信的最佳实践。我打算使用 SignalR 将状态传达给连接的用户。

如果您有一些指向实际代码示例的链接,那就太好了!

编辑/澄清

我在本地 LAN 上有多个通过第三方 DLL 控制的设备。为了控制特定设备,使用设备的本地 LAN Ip 地址创建第三方 DLL 中定义的类的实例。使用该类实例,可以转动、控制和管理设备。此外,设备通过 TCP/IP 发送可以通过回调方法接收的消息。

我想通过一个负载平衡的网站公开对这些设备的控制和来自这些设备的消息。用户(例如 Greg)可以通过网站请求开始记录设备列表中的任何设备(例如位于 192.168.1.51 的设备)。我的代码将通过 Web API 帖子(比如 devices/51)接收该请求。收到后,我将启动 Device Logger API 类的新实例并注册回调函数。通过回调从设备传入的消息将通过 SignalR 推送到连接的客户端并写入数据库以用于历史记录。另一个用户(比如 Tim)可以附加到 SignalR 集线器以查看来自当前正在记录的设备的消息。 Tim 还可以通过向 Web API(比如 devices/51)提交删除请求来停止设备的实时记录。

我正在寻找一个内部网络服务器通信的示例。由于该网站位于服务器场中并且设备 51 的设备记录器 API 实例位于特定的 Web 服务器上,因此我的设备 Web api 删除将需要在 Web 服务器之间进行通信以关闭日志记录。

也许这就像为网络内通信设置辅助 SignalR 集线器一样简单。让所有 Web 服务器在启动时向集线器注册,然后将命令广播到注册的 Web 服务器。如果接收 Web 服务器有该设备的类实例,它会执行命令,如果没有,它会忽略该命令。

想法?是否有其他方式在 Web 服务器之间进行通信?

【问题讨论】:

    标签: signalr load-balancing asp.net-web-api2 long-running-processes


    【解决方案1】:

    根据我的经验,最好让自动复制的负载平衡服务保持无状态。在您的示例中,Web 2 上的记录器具有 Web 1 没有的状态,因此您所描述的服务不是无状态的。要删除记录器,请求必须转到自动复制服务实例池中的特定实例。

    您可以做的是为日志添加额外的后端(非面向公众)服务。每次您的前端服务的 N 个副本中的一个需要创建、交互或销毁记录器时,它都可以通过单个后端记录服务上的 API 来完成。

    思考:

    • POST /loggers >> 204 创建,位置:/loggers/48913
    • PUT /loggers/daily-statistics
    • POST /loggers/48913/messages
    • 删除 /loggers/48913

    对编辑/澄清的回应:

    现在您正在考虑您的系统,如下图所示:

    A     B     C     D      Web API instances
    |\         /|\    |
    U V   Q   W X Y   Z      Devices
    

    A、B、C 和 D 是负载平衡的 Web API,U、V、W、X、Y 和 Z 是您正在监控的设备。 Web API 实例和设备之间的连接用线表示。

    当 B 请求停止监听设备 Y 时会发生什么?它必须重新路由到 C,因为它是连接的 Web API。

    当一个请求到达 C 开始监听 Q 时会发生什么?它是否在 B 保持空闲时拾取第四个设备?

    我的建议是开始以这种方式考虑您的系统:

    A     B     C     D      Web API instances
    
       1     2     3         Device listeners
      /|\   / \   / \
     U V Q W   X Y   Z       Devices
    

    Web API 实例是 100% 无状态的。对于 Web API 的客户端,A、B、C 或 D 中的哪一个正在处理请求是隐藏的且不相关的。

    另一方面,设备侦听器是明确寻址的。它们可以相互通信,并且知道哪个设备侦听器连接到哪个设备。当请求到达有关记录设备 X 的 Web API 实例时,适当的请求会随机转发到设备侦听器之一。

    • 如果请求开始记录设备 X,则接收请求的设备侦听器会检查其他设备侦听器以查看当时是否有任何工作负载较小的设备。如果是这样,它会响应重定向到该设备侦听器。如果没有,它会为该设备创建记录器。

    • 1234563指定的设备。

    将 Web API 实例和设备侦听器分成两个不同的组允许您保持前端理想的无状态 Web 服务。

    【讨论】:

    • 我同意你的观点“一个安静的 api 应该是无状态的”。我很想让它成为无状态的,但最终,记录器本身就是一个从后端网络上的设备收集信息的实例。前端用户只能启动/停止日志实例。我希望利用每个 Web 服务器上的空闲周期来分散日志记录负载并保留这些记录器的特定实例。
    • @GregGrater 这些“记录器”是否只是写入日志文件?还是它们不是记录器的通常含义?如果您获得了足够的流量来对服务进行负载平衡,我希望您在 Web 服务器上没有空闲周期,而您只是不知道如何处理? :)
    • @GregGrater 另外,如果您扩展您的问题以提供更多详细信息,我可以尝试同样改进答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2011-12-05
    • 2015-04-11
    • 2012-05-26
    • 1970-01-01
    相关资源
    最近更新 更多