c# - 在不使用硬 CPU 的情况下动态更改 HttpClient 中的代理

标签 c# multithreading httpclient socks proxies

我需要创建一个发出请求(发布、获取等)的多线程应用程序 为此,我选择了 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/

相关文章:

c# - 使用 c# 程序为 Canon EOS Rebel XS 创建 usb 延时

c# - 如何从 Windows 8 Metro 应用程序中的 WebView 获取 HTML 元素 onClick?

c# - 套接字错误 : An existing connection was forcibly closed by the remote host

java - 如何通过 HTTP 代理连接 Socket 服务器

Angular 4 HttpInterceptor : show and hide loader

xml - Node.js HTTP 客户端中的自动 UTF-8 编码

c# - 如何禁用 Controller 上的按钮?

java - 为每个线程创建一个非线程安全对象并使用 happens-before 保证

java - java中原始整数值的同步

python 3.5 - asyncio - 运行并发连接池