代码之家  ›  专栏  ›  技术社区  ›  Marcio Aguiar

限时服务

  •  1
  • Marcio Aguiar  · 技术社区  · 16 年前

    我正在开发一个向MusicBrainz Web服务发出请求的应用程序。我在MusicBrainz手册中读到,每秒不要向Web服务发出超过一个请求,否则客户端IP将被阻塞。

    为了使这个限制对服务客户机透明,您建议使用什么体系结构。

    • 我想调用一个方法(例如getalbuns),它应该只在最后一个请求后1sec发出请求。
    • 我还想一次调用10个请求,服务应该处理队列,在可用时返回结果(非阻塞)。

    谢谢!

    2 回复  |  直到 16 年前
        1
  •  1
  •   erickson    16 年前

    由于两次呼叫之间需要延迟,我建议 java.util.Timer java.util.concurrent.ScheduledThreadPoolExecutor . Timer 非常简单,非常适合 用例。但是如果以后确定了额外的调度需求,那么 Executor 可以处理所有的问题。在这两种情况下,使用固定延迟方法,而不是固定速率方法。

    定期任务 polls 请求对象的并发队列。如果有一个挂起的请求,任务将执行它,并通过回调返回结果。服务的查询和要调用的回调是请求对象的成员。

    应用程序保留对共享队列的引用。要安排请求,只需将其添加到队列中。


    只是为了澄清一下,如果在执行计划任务时队列是空的,则不会发出请求。简单的方法只是结束任务,调度程序将在一秒钟后调用该任务再次进行检查。

    但是,这意味着启动任务可能需要一秒钟,即使最近没有处理任何请求。如果这种不必要的延迟是不可容忍的,那么编写自己的线程可能比使用 ScheduledThreadPoolExecutor

    run() blocking sleep

    take() poll() queue BlockingQueue<? extends Request>

        Collection<Request> bundle = new ArrayList<Request>();
        bundle.add(queue.take());
        while (bundle.size() < BUNDLE_MAX) {
          Request req = queue.poll(EXTRA, TimeUnit.MILLISECONDS);
          if (req == null)
            break;
          bundle.add(req);
        }
        /* Now make one service request with contents of "bundle". */
    
        2
  •  1
  •   James Anderson    16 年前