V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  xiangyuecn  ›  全部回复第 107 页 / 共 113 页
回复总数  2242
1 ... 99  100  101  102  103  104  105  106  107  108 ... 113  
2018-09-13 10:01:15 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@xeaglex 测试了一下调大了最小线程数,新开的线程立马就飚了起来。

刚刚,细细思考一下 ThreadPool 这种延迟开新线程的行为存在的意义,发现一个事实:纯粹是微软某个程序员意淫出来的结果。

[1]

一般常见的池类配置存在两个控制参数:MaxActive 最大活跃数、MaxIdle 最大空闲数;你需要连接立即给你,只要不超过最大连接数,并且池内保留已开启的。

.net ThreadPool:只有 MaxThread 最大活跃数;你需要线程?看你设置了 MinThreads 没有,已开线程数量超过 MinThreads ?不好意思,新血液小水管慢慢流,等着业务超时吧。


[2]

ThreadPool 这个延迟功能初衷本来是好的,可以防止程序因为突然不好的原因( bug 或者其他非预期因素)打开大量线程产生的问题 [非业务需求] 。但如果程序确实需要大量线程来处理,不管你怎么延迟,最终还是会开到满足需要的线程数量 [业务实际需求] ;此时 ThreadPool.SetMinThreads 入场。

但是因为程序功能需要,往往需要调用 ThreadPool.SetMinThreads 调大可快速开启的线程数量,由于 ThreadPool.SetMinThreads 算是一个竞争资源(下面 [3] 解释)。最终的设定会趋向于 ThreadPool.SetMinThreads==ThreadPool.SetMaxThreads,并且趋向于全局只初始化设定一次(如程序启动时)。

最终结果就是 ThreadPool.SetMinThreads 失去存在的意义,ThreadPool 延迟开新线程没有任何价值。


[3]

ThreadPool.SetMinThreads 存在竞争因素,不敢随意调用,最终结果趋向于在程序初始化时设定 ThreadPool.SetMinThreads==ThreadPool.SetMaxThreads。

注意:MinThreads 数量并非会保留的空闲( Idle )线程数量,是要新开线程时如果已开启线程数量没有超过 MinThreads 就会立即开启,否则等着吧。新开的线程超过时间没用会自动关闭,具体保留多少个空闲( Idle )线程,没有设置方法。

默认:SetMinThreads 10
事物 A:事物开始时 SetMinThreads 200 (实际需要 100-300 个线程),事物结束还原成 10
事物 B:事物开始时 SetMinThreads 50 (实际需要 50-80 个线程),事物结束还原成 10

竞争情况:AB 都在运行(无需管谁先开始的),A 需要 30 分钟,B 需要 5 分钟,不管谁先结束,MinThreads 都会变成比另外事物开始时设定值小,都 [有可能] 对另外一个事物产生影响。

解决办法:那就不在事物开始时设定,改成每次从线程池中拿线程时设定 MinThreads,问题解决!

然后演变变成了:

MinThreads=谁大谁说了算;

整个程序 MinThreads≈会最大设定那个值。

整个程序 MinThreads≈MaxThreads。


[结论]

当有相对多点的线程需求时,ThreadPool 这种延迟开新线程的行为没有意义。ThreadPool.SetMinThreads 废物,不如换成 SetMaxIdleThreads。

new Thread(run).Start()没这种问题,但线程启动耗时太长(到无法接受的程度)。ThreadPool.QueueUserWorkItem(run)和 Task.Run(run)共享 ThreadPool。

实现线程池比实现 HttpClient 简单 99 倍,是时候自己实现一个.net 的线程池了(大哭

-----

洋洋洒洒又写作文,测试+码字耗时 1 小时,学习就是这样的 @karllynn #70
2018-09-12 20:50:30 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@rwecho @paranoiagu @xeaglex 从发起到完成一个请求,.net 背后套入太多。


顺带发现一个好玩的:

昨天开 50 个线程(Task 实现的)去请求数据,请求数据中用到了 GetResponseAsync,会发现开始时速度极慢,而且会产生超时请求,2 分钟后请求速度达到最高速率并且稳定,最后发现是线程池的锅。

.net 4.5 中线程池中最小线程数饱和后,会新开新线程。但不是需要多少立即开多少,基本上 1 秒开一个新线程,启动异常缓慢。导致突然增加的 50 个线程只有少量在工作,其他排队。进而导致 GetResponseAsync 没有线程来处理,导致超时。

https://bbs.csdn.net/topics/390454205?page=1。

感觉用.net 来做定时采集任务是要废了,请求不好用,线程池还不能进行突发操作,略略略。。。
2018-09-12 10:13:43 +08:00
回复了 tangler 创建的主题 程序员 心如一滩死水,激不起半点涟漪
检查结果:缺乏目标,没有进取心,没有自律的表现,根源:懒
2018-09-11 12:03:21 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@oyjc @hibobby 想要的功能实现不了,新手吐槽一下而已,别这么认真
2018-09-11 12:00:04 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
#66 还有 #29 我站着不动,你们去拿刀。

要用 socket 实现 httpclient,不否认可以实现,里面的工作量有多大,写出来比框架自带的是好还是坏,我就不知道了。老是诱导我们这群小白去磨一些很基础但很重要,深入发现里面异常庞大的东西。
2018-09-11 11:13:04 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@wizardforcel 98%情况下是有用的,我需要那 2%,嘿嘿
2018-09-11 10:36:20 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@nannanziyu 嗯嗯,还在学,新收到 Task.WhenAny、Task.Delay 新知识。

查询了一下 Task.Delay,https://blog.csdn.net/wushang923/article/details/41015063 本质上是开了一个计时器。

试了一下 WebRequest 的 GetRequestStreamAsync、GetResponseAsync,昨天测试没发现这两个方法,和 BeginGetRequestStream 和 BeginGetResponse 一样是异步方法,功能差不多,前面的两个简洁多了。

现在已经换掉了昨天写的 BeginGetRequestStream、BeginGetResponse,直接用的 BeginGetRequestStream().Wait(timeout),这部分代码少了一半。

隐约发现 HttpWebRequest 好像已经过时了。。

-----------

#45 这几点如果抛开上下文来看,确实很滑稽,我现在看一遍我自己也发笑。

--

ConnectTimeout 是 WebRequest 没有提供的,看文档这个应该是和 GetRequestStream 超时差不多,所以 ConnectTimeout≈Timeout(GetRequestStream 之前设置值),但 Timeout 有点小缺陷( dns 查询部分)。

所以就有了“拿到请求 Stream 才能处理 ConnectTimeout ”

--

GetRequestStream 方法 GET、HEAD method 是禁止调用的,就有了“ get 里发 body ”,并非真要往 stream 里面塞数据。

--

一个 task 对象背后的具体实现由于不明确,认定有 0-50ms 延时不为过,参考 Task.Delay,测试过程中发会多出 30ms 左右。

done.


------------------


其实写这个帖子根源还是我想要一个 ConnectTimeout 设定,因为请求一个 url,如果连接不上服务器应该立即返回错误,而 ConnectTimeout 应该远远小于 GetResponse 的超时。比如:ConnectTimeout=2 秒能满足 99.9%的需求,但 GetResponseTimeout 就需要根据不同业务来定,如访问 V2EX,会 GetResponseTimeout=10 秒,虽然很多情况下 1 秒就能拿到响应,但很多时候 V2 会卡很久才会开始返回响应头(经常刷 V2 就是这个感觉)。

应用场景:用户提交任意 URL,尽快速度测试 URL 是否有效,URL 中 50%可能是被墙地址,比如 google.com ,先决条件:需要让 V2EX 等可能会响应慢的地址尽可能通过测试。

简单有效的解决方案就是使用 ConnectTimeout=2 秒,如果连接不上服务器 2 秒就超时了,不管是被墙还是服务器宕机。GetResponseTimeout=10 秒,让响应慢的地址尽可能通过测试。

回到.net ,POST 可以用 GetRequestStream 来支持 ConnectTimeout。GET 目前学习发现暂时无解,只能等到 GetResponseTimeout 超时。


又洋洋洒洒的写了一篇作文,耗时半小时,划水,划水



----

@passerbytiny 好吧,发现帖子正文和上面楼层自己回复的和想要的功能有点出入,这个里在详细重新描述了一下。缺乏一个功能肯定会带来某些功能的丧失,我这个请求功能是从 java 里写的一个类中移植过来的,java 里面 HttpURLConnection 可控制的参数多些,有 setConnectTimeout。
2018-09-10 23:51:34 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@forerunner .net framework 4.5

----
.net core 的实现瞄了一下文档发现没什么区别好像,dns 查询部分都是没纳入 timeout 中
2018-09-10 22:32:33 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@verrickt 嗯,学习了。IAsyncResult 估计是历史包袱。
2018-09-10 22:26:48 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@liuguang public abstract class WebRequest

abstract 需要查实现 public class HttpWebRequest : System.Net.WebRequest 然后会发现帖子正文中的引用内容
2018-09-10 19:32:02 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@verrickt 嗯嗯,HttpClient 和 WebRequest 一个尿性:it may take 15 seconds or more before a WebException is thrown to indicate a timeout on your request,timeout 是不管 dns 解析部分超时

用 CancallationTokenSource 和 @ZhLTE #16 的建议一个意思,HttpClient 有相应方法支持,WebRequest 有点不好办
2018-09-10 18:15:11 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@fwee 研究 get request body 的时候发现的一篇文章: https://blog.csdn.net/q_an1314/article/details/51298073,我不是要用 GET 来发请求体,而是遇上了需要拿到请求 Stream 才能处理 ConnectTimeout,但 GET 不让拿 RequestStream,导致 GET 部分无解,真遇上了“ GET 不让发请求体”,有点为难
2018-09-10 18:06:21 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@xupefei 不要在意其他人的回复,我回复 19 楼是很认真的,task 你没有遇到 task 的线程池占满的情况,不排除永远等待的可能

其他楼层杠的我脾气很暴躁,包涵包涵~
2018-09-10 18:01:38 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@luozic
@zkd8907
@cdwyd

我也是一个杠精,何况在我自己写的帖子里面,百毒不侵,(doge+滑稽+辣稽
2018-09-10 17:57:34 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@xupefei 隔壁 java 笑了,哈哈哈,一些简单功能的缺失,用大的代价来弥补一下的做法,不到万不得已,不开相对重量级的 task,毕竟大部分请求 50ms 以内就完成了,一个 task 下来可能额外需要等待 0-50ms 才会做实际的任务

@daigouspy 一样

网络请求这种耗费时间的,按理应该提供比较精细的超时控制,jdk 就没有这个问题。
想到正则表达式都有超时控制,一个网络请求基本的东西,还要开线程控制超时,就是底层太简陋了。
.net 明显的缺陷看 dns 查询部分,太不靠谱
2018-09-10 17:42:14 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@yulitian888 字面意思 HttpClient extend WebClient,WebClient using HttpWebRequest,仅字面意思

@ZhLTE 差不多这意思,从请求创建开始,不管是哪里卡了,只要到时间还么有最终结果就是超时
2018-09-10 17:37:40 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@catcn 刀呢
2018-09-10 17:34:27 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@ZhLTE 比如 get 一下 www.dropbox.com ,能达到预期( 2 秒超时就是 2 秒超时)的语言就是 ok,.net 就是渣渣
2018-09-10 17:29:52 +08:00
回复了 xiangyuecn 创建的主题 程序员 C#中的废物 WebRequest
@cjw1115 @daigouspy 用什么都无所谓,关键是需要的功能有没有,有 System.Net.Http.HttpClient 这个框架自带的,配置设置基本没有,因为够简单,满足 98%的需求吧,2%就呵呵,仅此而已
辣眼睛 绝对是没有经过设计,然后没有前端写 css,100%是后端人员临时写的 html 代码

备案:
http://wx4.sinaimg.cn/large/a32300cdgy1fv2x1nwpnmj20zha4eb2g.jpg
1 ... 99  100  101  102  103  104  105  106  107  108 ... 113  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2522 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 33ms · UTC 02:28 · PVG 10:28 · LAX 19:28 · JFK 22:28
Developed with CodeLauncher
♥ Do have faith in what you're doing.