我需要创建一个发出请求(发布、获取等)的多线程应用程序
为此,我选择了 Httpclient
。
默认不支持 Socks 代理。所以我发现 Sockshandler
( https://github.com/extremecodetv/SocksSharp ) 可以用来代替基本的 HttpClientHandler。它允许我使用 socks 。
但是我有一个问题。我所有的请求都应该通过我从互联网上解析的不同代理发送。但是 httpclient 处理程序不支持动态更改代理。如果我没有有效的代理,我需要重新创建一个 httclient,这没问题,但是如果我有 200 个线程,它会占用很多 cpu。那么遇到这种情况我该怎么办呢?
第二个问题。我发现这篇文章 ( https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ ) 谈到将 HttpClient
用作单个实例以提高性能,但这在多线程程序中是不可能的。在这种情况下哪种方式更好?
谢谢帮助
最佳答案
httpclient handler doesn't support changing proxies dynamically.
我不确定这在技术上是否属实。 Proxy是一个读/写属性,所以我相信您可以更改它(除非这会导致运行时错误……老实说,我实际上并没有尝试过)。
更新:我现在已经尝试过了,您的断言在技术上是正确的。在下面的示例中,更新 UseProxy
的行将失败并显示 "System.InvalidOperationException: 'This instance has already started one or more requests. Properties can only be modified before send the first request. '" 在 .NET Core 和完整框架上得到确认。
var hch = new HttpClientHandler { UseProxy = false };
var hc = new HttpClient(hch);
var resp = await hc.GetAsync(someUri);
hch.UseProxy = true; // fail!
hch.Proxy = new WebProxy(someProxy);
resp = await hc.GetAsync(someUri);
但事实是您不能以线程安全的方式根据请求设置不同的属性,这很不幸。
if I have 200 threads, it takes a lot of cpu
并发的异步 HTTP 调用不应消耗额外的线程或 CPU。使用 await Task.WhenAll
或类似的方式和 there is no thread 将它们关闭消耗直到返回响应。
And second problem. I found this article...
这绝对是您需要注意的事情。但是,即使您可以为每个请求设置不同的代理,底层网络堆栈仍需要为每个代理打开一个套接字,因此您不会通过 HttpClient< 获得任何好处
就套接字耗尽问题而言,每个代理实例。
最佳解决方案取决于您在这里谈论的代理数量。在文章中,作者描述了当服务器打开大约 4000-5000 个套接字时遇到问题,而大约 400 个或更少时没有问题。 YMMV,但是如果代理的数量不超过几百个,您应该安全地为每个代理创建一个新的 HttpClient
实例。如果更多,我会看throttling your concurrency并对其进行测试,直到找到一个您的服务器资源可以跟上的数字。在任何情况下,请确保如果您需要对同一个代理进行多次调用,您正在为它们重新使用 HttpClient
实例。 ConcurrentDictionary
可用于延迟创建和重用这些实例。
关于c# - 在不使用硬 CPU 的情况下动态更改 HttpClient 中的代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49818605/