HttpClient DocumentClient 不同线程会发生啥。 Azure 函数
Posted
技术标签:
【中文标题】HttpClient DocumentClient 不同线程会发生啥。 Azure 函数【英文标题】:HttpClient DocumentClient What Happens With Different Threads. Azure FunctonsHttpClient DocumentClient 不同线程会发生什么。 Azure 函数 【发布时间】:2019-06-28 08:52:29 【问题描述】:我在一篇关于 HttpClient/DocumentClient 的文章中读到,最好的做法是为应用程序创建一个单例并将其注入到对象中,这样就不会因继续重新创建而耗尽底层资源。这是如何工作的?如果一个 HttpClient 被多个线程访问并同时调用可能不同的端点,我看不出这是如何工作的。
我读过这个
https://medium.com/@nuno.caneco/c-httpclient-should-not-be-disposed-or-should-it-45d2a8f568bc
感兴趣。如果我有一个使用 DocumentClient 调用 cosmosDb 的 Azure 函数,我应该如何使用 DocumentClient?应该是静态实例吗?
我的 Azure 函数是这样设置的。我假设每个请求都会创建一个新的 DocmentClient 实例,在高负载下可能会导致资源问题。
[FunctionName("MyGetFunc")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
[CosmosDB("ct","ops", ConnectionStringSetting ="cosmosConn")]
DocumentClient docClient,
ILogger log)
//use docClient here...
【问题讨论】:
HttpClient 是线程安全的。除此之外,为什么不调用不同的 URL? HttpClient 不是 HttpWebRequest 只能用于一个 URL,实际上是一个调用。 【参考方案1】:有关您问题的 DocumentClient 部分,请参见此处:https://docs.microsoft.com/en-us/sandbox/functions-recipes/cosmos-db?tabs=csharp#customize-a-documentclient-and-reuse-it-between-executions
他们谈论不同的场景。所以是的,如果你有很多函数调用,我会使用一个静态实例——它也是线程安全的。
private static DocumentClient client = GetCustomClient();
private static DocumentClient GetCustomClient()
DocumentClient customClient = new DocumentClient(
new Uri(ConfigurationManager.AppSettings["CosmosDBAccountEndpoint"]),
ConfigurationManager.AppSettings["CosmosDBAccountKey"],
new ConnectionPolicy
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
MaxRetryAttemptsOnThrottledRequests = 10,
MaxRetryWaitTimeInSeconds = 30
);
// Customize PreferredLocations
customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.CentralUS);
customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.NorthEurope);
return customClient;
[FunctionName("CosmosDbSample")]
public static async Task<HttpResponseMessage> Run(
【讨论】:
【参考方案2】:如果
HttpClient
正被多个线程访问并同时调用可能不同的端点,我看不出这是如何工作的。
为什么? HttpClient
是线程安全的,这意味着它可以同时在多个并发线程中使用。
Is HttpClient safe to use concurrently?
【讨论】:
谢谢。一个实例如何同时调用不同的端点? @PaulStanley 为什么不应该这样做?您是否将它与 HttpWebRequest 混淆了?还是使用只调用一个端点的 WCF 代理? @PaulStanley:例如通过来自两个不同线程的不同参数调用其GetAsync
方法。
@PanagiotisKanavos 不,我没有把它与 HttpWebRequest 混淆,我只是不了解类的异步性质。
@PaulStanley 它与异步通信无关。它是线程安全的。在任何类中,任何不依赖于修改共享数据的方法都可以在多个线程中使用而无需锁定。如果你想看看幕后发生了什么,你可以inspect the source code。【参考方案3】:
如果您使用的是 .NET Core,另请参阅Use HttpClientFactory to implement resilient HTTP requests。
HttpClient
旨在被实例化一次并在应用程序的整个生命周期中重复使用。为每个请求实例化HttpClient
类将耗尽重负载下可用的套接字数量。该问题将导致SocketException
错误。解决该问题的可能方法是基于将HttpClient
对象创建为单例或静态对象,如Microsoft article on HttpClient usage 中所述。但是当您将
HttpClient
用作单例或静态对象时,您可能会遇到第二个问题。在这种情况下,单例或静态 HttpClient 不考虑 DNS 更改,如本期 .NET Core GitHub repo 中所述。为了解决上述问题并简化
HttpClient
实例的管理,.NET Core 2.1 引入了一个新的HttpClientFactory
,它还可以通过将 Polly 与其集成来实现弹性 HTTP 调用。
【讨论】:
【参考方案4】:[CosmosDB("ct","ops", ConnectionStringSetting ="cosmosConn")]
DocumentClient docClient,
这是使用 Cosmos DB 绑定。 Binding不会创建 DocumentClient 的多个实例,它会创建一个并在所有执行中重用它。
您可以在此处查看源代码:https://github.com/Azure/azure-webjobs-sdk-extensions/blob/dev/src/WebJobs.Extensions.CosmosDB/Bindings/CosmosDBClientBuilder.cs。
它调用GetService
并获取该特定连接字符串的 DocumentClient 实例(如果在之前的执行中已经创建了一个)。
类似于维护您自己的静态/惰性 DocumentClient(请参阅https://docs.microsoft.com/en-us/azure/azure-functions/manage-connections#documentclient-code-example-c)。
【讨论】:
以上是关于HttpClient DocumentClient 不同线程会发生啥。 Azure 函数的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:AWS.DynamoDB.DocumentClient 不是构造函数
使用 jest 模拟 AWS.DynamoDB.DocumentClient 的构造函数