代码之家  ›  专栏  ›  技术社区  ›  CaptainHastings

无状态阻塞服务器设计

  •  2
  • CaptainHastings  · 技术社区  · 15 年前

    请帮忙。

    我正在设计一个具有以下功能的无状态服务器:

    1. 客户端向服务器提交作业。
    2. 当服务器尝试执行作业时,客户端被阻止。
    3. 服务器将生成一个或多个线程来执行该作业。
    4. 工作要么完成,要么超时,要么失败。
    5. 创建适当的响应(基于结果),取消阻塞客户机,并将响应传递给客户机。

    这是我迄今为止的想法。

    1. 客户端向服务器提交作业。
    2. 服务器为作业分配一个ID,将作业放在队列上,然后将客户机放在另一个队列上(在该队列中将被阻塞)。
    3. 拥有一个线程池,该线程池将执行作业、获取结果并适当地创建响应。
    4. 根据ID,从队列中选择客户机(从而取消对其的阻塞),给出响应并发送它。

    步骤1、3、4看起来非常直接,但是关于如何将客户机放入队列,然后阻塞它的任何想法。此外,任何能帮助我设计这只小狗的指针都会受到赞赏。

    干杯

    3 回复  |  直到 15 年前
        1
  •  2
  •   ChssPly76    15 年前

    为什么需要阻止客户端?似乎在执行初始验证(如果有的话)后立即返回(几乎)并为客户提供给定作业的唯一ID更容易。然后,客户机将能够使用所述ID进行投票,或者可能提供回调。

    阻塞意味着你要抓住一个套接字,这显然限制了你可以同时服务的客户机的上限。如果这不是您的场景的问题,并且您绝对需要阻止(也许您对客户机代码没有控制权,并且无法对其进行轮询?),除非您可以将其实际划分为并行任务,否则生成执行该作业的线程是没有意义的。在这种情况下,唯一的“队列”是由公共线程池持有的队列。工作流程基本上是:

    1. 创建线程池(例如 ThreadPoolExecutor )
    2. 对于每个客户请求:
      1. 如果作业的任何部分可以并行执行,请将它们委托给池。
      2. 和/或在当前线程中执行这些操作。
      3. 等待直到集合作业部件完成(如果适用)。
      4. 将结果返回给客户端。
    3. 关闭线程池。

    本身不需要ID;尽管您可能需要使用某种类型的 latch 对于上述2.1/2.3。

    超时可能有点棘手。如果你需要它们或多或少的精确,你必须保持你的主线程(收到客户机请求的线程)没有工作,并且当超时时间达到并立即返回时,让它发出提交作业部分的信号(通过翻转标志)。您必须定期检查所述标志,并在其翻转后终止执行;然后池将回收线程。

        2
  •  0
  •   Dark Falcon    15 年前

    你如何与客户沟通?

    我建议您创建一个对象来表示包含作业参数的每个作业,以及用于访问客户机的套接字(或其他通信机制)。然后,线程池将发送响应,以便在作业处理结束时解除对客户端的阻塞。

        3
  •  0
  •   Nicholas Jordan    15 年前

    超时会有点棘手,并且会隐藏gotcha的,但是基本设计似乎很简单,在构造函数中编写一个接受套接字的类。在socket.accept上,我们只是做了一个新的socket处理实例,对可伸缩性有很好的预见性和计划,或者如果这是一个测试实验,那么socket处理类只会处理数据处理类,当它返回时,您会得到一些布尔或数字形式的状态或其他东西,空btw和eth的便利位置。ER从套接字将成功写入输出流,或通知客户端超时或您的业务需要是什么。

    如果你必须有一个可扩展的,有效的设计长期运行重型运输,直接去NIO…像我描述的手工编码的一次性解决方案可能无法很好地扩展,但将为代码正确工作的NIO设计提供基本的概念化基础。

    (抱歉,伙计们,我认为代码设计模式直接应用于代码,然后在代码工作之后。不能阻止的东西会被改写,而不是以前)