【问题标题】:Thread safety when different processes access same resources不同进程访问相同资源时的线程安全
【发布时间】:2020-02-25 11:56:50
【问题描述】:

我正在使用 Windows 服务从 API 获取一些数据

service#1 从“http://api.provider.com/Entity1”获取数据

service#2 从“http://api.provider.com/Entity2”获取数据

我在一个 .csproj 中拥有这两个服务,我使用单例 httpClient 从 API 检索数据:

public sealed class Client : HttpClient{

private static readonly object padlock = new object();
private static Client instance = null;
public static Client Instance
{
    get
    {
        if (instance == null)
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Client();
                }
            }
        }
        return instance;
    }
}

private Client()
{
    DefaultRequestHeaders.Accept.Clear();
    DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
    DefaultRequestHeaders.Add("...", "...");
}

public async Task<string> Get(string url)
{
    var result = await GetStringAsync(url);
    return result;
}}

但是这些进程是并行的,所以单例类是两者之间的共享静态类。然后我将这个类作为第一个消费者:

class APIHAndler{

public List<obj1> f1()
{
    var jsonResult = Client.Instance.Get(url1).Result;
    //make list of obj1 out of json
}

public List<obj2> f2()
{
    var jsonResult = Client.Instance.Get(url2).Result;
    //make list of obj2 out of json
}

}

我所做的是在我的每个服务中创建一个 APIHAndler 类的实例,并根据正在进行的业务调用 f1 和 f2,我收到此错误:

响应状态码不表示成功:429(请求过多)。

我认为这可能是由于同时打开了两个不同的连接。但我不知道如何避免这种情况。如果您能帮我解决这个问题或有更好的解决方案,我会很高兴听到的。

【问题讨论】:

  • 您是否在循环中调用 Web 服务?也许你调用端点太频繁了?
  • 不,但我实际上在两个不同的 Windows 服务中调用它,它们同时运行以从 API 访问两个不同的资源

标签: c# multithreading thread-safety singleton httpclient


【解决方案1】:

我不知道如何避免这种情况

您调用的服务应该有说明导致 429 的原因的文档。有时一次只有一个请求;更常见的是在一个时间窗口内的一定数量的请求。无论哪种方式,您都需要限制您的请求,并且您可以使用 SemaphoreSlim 构建限制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多