首页 新闻 会员 周边

如何编写高性能网络访问程序

0
悬赏园豆:30 [已解决问题] 解决于 2015-07-01 14:40

最近在用C# 研究高性能网络访问程序相关方面的内容,发现自己能用上的相关技术比较单一,目前是用HttpwebRequest 多线程发请求,keepalive=true,程序运行的环境也不差,ping网站域名2ms,机器配置也属中上,是一个类似秒杀功能的程序,一次秒杀,需要发4次https请求,缺一不可,如12306抢票,网站是https协议, 功能倒是都能做出来,但效果不是很理想,不知道是不是程序方面还需要更加优化改进,

查了些资料,有说用socket,性能会更好,但具体用socket如何访问https网站,不是很了解,性能方面是否比HttpwebRequest更高,也未可知.

 不知有没做过类似功能的大神, 目前没有太多优化思路,求大神指点.

问题补充:

还有大神能给些意见和建议么

fenghuo的主页 fenghuo | 初学一级 | 园豆:20
提问于:2015-02-11 21:21
< >
分享
最佳答案
1

1,每个请求的大小是多少?

2、每个响应的大小是多少?

3、你家带宽多少?

4、使用形式为 BeginXXX 或 XXXAsync 的 API。

5、将请求对列化。

6、.NET 的 Socket 就不要用了,使用 WinHTTP 类库。

收获园豆:15
Launcher | 高人七级 |园豆:45045 | 2015-02-12 09:37

请求体1KB左右

响应不大200B

带宽10M,ping网站域名2ms

第四点是指使用异步方式吗,抱歉,我忘记说了,整个流程,需要发4次https请求,需要按顺序依次来,并且前后有依赖,请求1未处理完,请求2会失败.

听说socket是工作在传输层,一般httpwebrequest,WinHTTP是在应用层,不会更快些么,

另外,https协议需要三次握手后,在ssl上通信, 有没什么方式能建立一次连接后,多次通信

 

 

fenghuo | 园豆:20 (初学一级) | 2015-02-12 10:34

@fenghuo: 我先说一点你的理解的偏差,HttpWebRequest 和 WinHTTP 最终都是使用 SOCKET 来实现,我不建议你直接使用 SOCKET 的原因是你的基础不好,还不能掌握如何编写正确和高性能的 SOCKET 程序,很可能你连使用 TCP 来实现 HTTPS 协议(你提到的“应用层”)都很困难。另一个你的理解的偏差就是,异步跟你是否需要 4 次 TLS 握手是没有关系的,这在于你的多线程编程能力。

关于带宽中的 10M 同你的请求的 1KB 的单位理解的差别,你知道么?有个 8 倍数关系。

我们可以以 HttpWebRequest 来说明如何提高网络访问的性能,HttpWebRequest 在做 HTTPS 请求时的大致步骤包括:DNS Lookup(如果你没直接提供 IP 的话),建立连接,TLS 握手,发送请求,接收响应。HttpWebRequest 在内部会维护一个默认的 Socket 池,每次 Create 的时候会使用已有的 Socket 来做通信,使用池中的连接请求,可以省去 DNS Lookup、建立连接和 TLS 握手的步骤。提高性能的主要工作就是控制池的大小,让它保持在 2- 5 / 每服务器左右。

 

因此你需要建立一个队列,允许同时在队列上执行的请求数目为 2- 5 左右,每个请求使用 BeginXX 或 XXXAsync 发送,在 EndXXX 或 Continued Task 中再从队列读取需要发送的请求。额外的工作,你需要显示提供 Connection: Keep-Alive 标头,告诉服务器你要重用连接(有可能服务器不会理会该标识,你可以抓包分析下)。

你也应该尽可能的使用 XXXAsync 形式的 API,在建立连接上会有优势,它会在 connect 的同时上传第一个数据块。

Launcher | 园豆:45045 (高人七级) | 2015-02-12 10:56

@Launcher: 多谢大神指点.

误解我意思了,我说的4次,是指完成一次秒杀 需要四步,在程序上看是4次https请求,不是指一次请求中的4次握手.

因4次请求,有先后顺序,前一次请求若未处理完,后一次就失败,所以异步前一次请求后也需要等待其结果,才能发送下次.另外Keep-Alive=true已经设定.

不过提高性能的主要工作就是控制池的大小,让它保持在 2- 5 / 每服务器左右,在建立连接上会有优势,这两点倒是值得研究.

fenghuo | 园豆:20 (初学一级) | 2015-02-12 11:51

@fenghuo: 那是我粗心了,我跟你道歉。如果你指的是 4 次请求的话,我觉得这里的问题在于你如何编写并行代码的事,同使用 Socket 或是 HttpWebRequest 没有关系。因此我不知道你强调这一点有什么用意?

Launcher | 园豆:45045 (高人七级) | 2015-02-12 14:12

@Launcher: 没事,大家一起交流.

因为完成一次秒杀需要发4次请求,而又不能仅仅秒杀一次就能成功,所以需要不断的发请求,直到成功或者它结束.

我提到socket,是认为它在建立连接或发送请求时能比httpwebrequest更快.性能更高. 所以看看能否在这方面做些优化.

因请求间数据有依赖,第一次响应有一个id,后续3次请求都需要带上它,并且前一次请求未处理完之前,后一次直接失败.

fenghuo | 园豆:20 (初学一级) | 2015-02-12 15:11

@fenghuo: 那你就用 Socket 写吧,记得要用 BeginXXX 或 XXXAsync 形式的 API,记得要缓存 DNS Lookup 结果,最好再有个 BufferManager,小心处理 Shutdown 和 Close,HTTPS 握手失败,记得 Close Socket。

另外你请求的那个依赖关系什么的,跟你提的这些问题都没有关系,纯粹是并行编程的技术。比如在 TPL 中的 Task.ContinueWith(1).ContinueWith(2) 实现控制流编程模型,或者使用 Concurrency Runtime 中采用的数据流编程模型。

Launcher | 园豆:45045 (高人七级) | 2015-02-12 15:37

@Launcher: 受教了 谢谢!

fenghuo | 园豆:20 (初学一级) | 2015-02-15 15:27
其他回答(3)
0

线程的开销很大的,用多线程来增大并发数效果不好,改用异步请求吧。  使用HttpClient。

收获园豆:5
天方 | 园豆:5407 (大侠五级) | 2015-02-11 21:41

抱歉,我忘记说了,整个流程,需要发4次https请求,需要按顺序依次来,并且前后有依赖,请求1未处理完,请求2会失败.  现在是只开了2个线程发请求

支持(0) 反对(0) fenghuo | 园豆:20 (初学一级) | 2015-02-12 10:35
0

你要的答案在这里都可以找到 http://www.cnblogs.com/cxwx/archive/2011/10/25/2224105.html

收获园豆:10
上帝之城 | 园豆:2549 (老鸟四级) | 2015-02-11 21:46

这个版本的socket访问https ,他是用tcpclient, 我测试过,同样访问100次,效果还没httpwebrequest好,很奇怪.

支持(0) 反对(0) fenghuo | 园豆:20 (初学一级) | 2015-02-11 21:49

@fenghuo: 试下release模式

支持(0) 反对(0) 上帝之城 | 园豆:2549 (老鸟四级) | 2015-02-11 22:07

@上帝之城: 对 是release出来后,运行的.哦

支持(0) 反对(0) fenghuo | 园豆:20 (初学一级) | 2015-02-11 22:25

@fenghuo: 这种频繁IO的东西,没有池就不要谈性能,更别说高性能。

支持(0) 反对(0) 上帝之城 | 园豆:2549 (老鸟四级) | 2015-02-11 22:54

@上帝之城: 额 感觉这个应该还是有讲究的吧,不然那些秒火车票的童鞋,是咋做到的

支持(0) 反对(0) fenghuo | 园豆:20 (初学一级) | 2015-02-11 22:59
0

瓶颈在4次来回请求这里,只能看是否能优化流程,减少请求次数,若是请求间没有数据依赖,可以先一步发送各个请求,最后综合来判断。

arg | 园豆:1047 (小虾三级) | 2015-02-12 13:02

请求间数据有依赖,第一次响应有一个id,后续3次请求都需要带上它. 

4次请求 缺一不可.

支持(0) 反对(0) fenghuo | 园豆:20 (初学一级) | 2015-02-12 13:05
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册