- 读取输入文件。输入文件按行排列,包含成千上万行数据。
- 对输入文件进行预处理并转换为中间文件。中间文件具有相同数量的行。
- 逐行从中间文件中读取一行,形成Web请求并将其发送到Web服务器。
- 逐个请求从Web服务器读取响应,对其进行处理(解析)并将其写入输出文件。输出文件与输入文件具有相同数量的行。
有人能告诉我可能在这种情况下使用的各种方法吗?
如果多线程是解决问题的答案,有人能建议几个起点吗?
有人能告诉我可能在这种情况下使用的各种方法吗?
如果多线程是解决问题的答案,有人能建议几个起点吗?
关于多线程的简单而正确的回答是:是的,只要 1)算法可行,2)它涉及 I/O-bound 操作或者你有几个 CPU-bound 操作的核心。
Web 请求是 I/O-bound 操作。您可以获得最大的好处。由于您正在对同一服务器执行请求,无论是否容错,都必须限制查询速率。需要适当地调整并发请求的数量,但如果在代码中使用常量(如 const int NUMBER_OF_THREADS = 4;
),则有一个良好的起点。
使用信号量来处理并发请求。
像以前一样从文件读取并转换为中间文件开始程序。
完成后,创建一个固定大小的数组(您说最终文件具有相同数量的行,因此可以分配它),然后为每行启动一个循环:
NUMBER_OF_THREADS
常量,这将允许主线程激活 4 个并发线程。循环结束后,在 AutoResetEvent
上等待,我会简要讨论一下。
在线程中,执行以下操作:
Interlocked.Increment()
方法增加一个跨线程共享的变量(此处未讨论)if
共享变量 equals
行数,则 then
发布我提到的 AutoResetEvent
,以便解锁主线程从 4 个并发线程开始。尝试将它们增加到 8 并查看性能。我建议您不要超过 12 个线程,但其他人可能会说那可能太多了...这只是尝试和失败。
在读取文件的同时,您也在写入文件。首先想到的是使用大块(BufferedReader)读取文件,以确保磁盘不会过多寻道。
至于您的服务器,在我的经验中,大多数Web服务器对每秒多个请求都相当宽容。如果您自己托管服务器,我建议简单地使用异步Web请求并找出发生了什么... 但是,从听起来的声音来看,您正在创建一个简单的网络爬虫,在这种情况下,我强烈建议要有耐心:在别人的服务器上引起麻烦绝不是一个好主意。为了给您一个指示:我们的网络爬虫总是限制每个服务器每秒1个请求。
我将创建一个基于内部消息队列和生产者-消费者链的应用程序。
* -> * -> * -> *
其中每个*
线程执行以下操作:读取、处理、查询WS、后处理。当*
节点的生产队列已满或消费队列为空时,它会进入睡眠状态。
如果需要,在每个点上可以创建多个消费者(最可能在WS处理程序中),如下所示:
/ * \
* -> * -> * -> *
\ * /
架构准备好后,您可以通过更改每个点的队列大小来调整应用程序。
此外 - 您可以使用线程池来处理每个处理节点,从而确保充分利用处理器。