简体   繁体   English

如何在多线程环境中实现有限的API调用?

[英]How to implement limited API calls in a multithread environment?

I have a lot of requests to send to a server (Amazon Product Advertising API), however this server doesn't allow me to send more than 1 request each second. 我有很多请求要发送到服务器(Amazon Product Advertising API),但是该服务器不允许我每秒发送超过1个请求。 I am looking for a free solution, based on C# abilities. 我正在寻找基于C#功能的免费解决方案。

I tried to code it like this: 我试图这样编码:

public static WebResponse Request(Dictionary<string, string> parameters) {
  var response = LaunchRequest(parameters);
  Sleep(1000);
  return response;
}

The problem is that multiple threads are entering in the method "Request" at the same time. 问题在于,多个线程同时进入“请求”方法。 If there are 4 threads, then there will be 4 requests per second. 如果有4个线程,则每秒将有4个请求。

How can my threads wait each other ? 我的线程如何互相等待?

EDIT: I tried with a lock. 编辑:我尝试了一把锁。

So I wrote this code : 所以我写了这段代码:

public class RequestHandler {
  private static readonly RequestHandler instance = new RequestHandler();

  private Object thisLock = new Object();

  private RequestHandler() { }

  public static RequestHandler Instance {
    get {
      return instance;
    }
  }

  public WebResponse Request(Dictionary<string, string> parameters) {
    lock (thisLock) {
      Log();
      var response = LaunchRequest(parameters);
      Sleep(1000);
      return response;
    }
  }
}

So I call my method like this : 所以我这样调用我的方法:

// ...
RequestHandler requestHandler = RequestHandler.Instance;
WebResponse response = requestHandler.Request(requestHelper, parameters);
// ...

It seems to work most of the time, but sometimes, my "LaunchRequest" method is fired almost at the same time. 它似乎在大多数时间都有效,但是有时,我的“ LaunchRequest”方法几乎同时被触发。

EDIT 2: Here are the log results, the arrows are showing the calls where there is less than 1 second: 编辑2:这是记录结果,箭头显示了少于1秒的呼叫:

Request: 09:52:50.230  - Thread 22
Request: 09:52:48.830  - Thread 5
Request: 09:52:47.468  - Thread 10 <---
Request: 09:52:47.331  - Thread 13 <---
Request: 09:52:45.971  - Thread 12
Request: 09:52:44.767  - Thread 11
Request: 09:52:43.230  - Thread 5
Request: 09:52:30.546  - Thread 21 <--- 
Request: 09:52:30.357  - Thread 20 <---
Request: 09:52:29.232  - Thread 13
Request: 09:52:27.908  - Thread 11
Request: 09:52:26.471  - Thread 5
Request: 09:52:25.138  - Thread 11
Request: 09:52:23.835  - Thread 12

Create an SQS queue. 创建一个SQS队列。 In your controller, put the data to the queue. 在您的控制器中,将数据放入队列。 Create a .net service which would poll the queue and process messages one-by-one, ensuring that only one message is sent at any given time. 创建一个.net服务,该服务将轮询队列并一一处理消息,确保在任何给定时间仅发送一条消息。

UPD Not sure why you'd tag the post as AWS if you don't like AWS services, but still. UPD如果您不喜欢AWS服务,则不确定为什么将帖子标记为AWS。

Instead of SQS you can use any of the varying queues available, eg MSMQ, RabbitMQ etc. The cost would be in the need to install and maintain those yourself. 除了SQS,您可以使用任何可用的可变队列,例如MSMQ,RabbitMQ等。所需的成本是需要自己安装和维护这些队列。

Absolute worst case scenario, use a ConcurrentQueue type from C#, and have a background thread running that will pop from that queue. 绝对最坏的情况,请使用C#中的ConcurrentQueue类型,并运行一个将从该队列弹出的后台线程。 That will ensure that only one message is processed at a time. 这样可以确保一次只处理一条消息。 However, this solution is not resilient as the app pool recycling would wipe your data. 但是,此解决方案没有弹性,因为回收应用程序池会擦除您的数据。

Store the last call details in session or a local variable. 将最后一次通话的详细信息存储在会话或本地变量中。 Then you can call sleep if there is a call. 然后,如果有电话,您可以呼叫睡眠。

public static WebResponse Request(Dictionary<string, string> parameters) 
{
    lock (thisLock)
    {
        string lastCalled = Session["LastCalledTime"] as string;
        if (!string.IsNullOrEmpty(lastCalled) && DateTime.Parse(lastCalled) >= DateTime.Now.AddSeconds(-1))
        {
            Sleep(1000);
        }
        var response = LaunchRequest(parameters);
        Session["LastCalledTime"] = DateTime.Now.ToString("O");
    }

    return response;
 }

Added lock to make it threadsafe as highlighted by trailmax . 添加了锁定以使其具有线程安全性,如Trailmax所突出显示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM