我正在尝试使用RxJS编写一个脚本来处理数百个日志文件,每个文件大约1GB。脚本的骨架看起来像
Rx.Observable.from(arrayOfLogFilePath)
.flatMap(function(logFilePath){
return Rx.Node.fromReadStream(logFilePath)
.filter(filterLogLine)
})
.groupBy(someGroupingFunc)
.map(someFurtherProcessing)
.subscribe(...)
代码有效,但请注意所有日志文件的过滤步骤将同时启动。但是,从文件系统IO性能的角度来看,最好一个接一个地处理一个文件(或者至少将并发限制为几个文件而不是同时打开所有数百个文件)。在这方面,我如何以“功能反应方式”实施?
我曾想过调度程序,但无法弄清楚它是如何帮助的。
答案 0 :(得分:13)
您可以使用.merge(maxConcurrent)
来限制并发性。因为.merge(maxConcurrent)
将metaobservable(可观察的可观察对象)展平为可观察对象,所以需要将.flatMap
替换为.map
,以便输出是metaobservable(“unflat”),然后调用.merge(maxConcurrent)
。
Rx.Observable.from(arrayOfLogFilePath)
.map(function(logFilePath){
return Rx.Node.fromReadStream(logFilePath)
.filter(filterLogLine)
})
.merge(2) // 2 concurrent
.groupBy(someGroupingFunc)
.map(someFurtherProcessing)
.subscribe(...)
此代码尚未经过测试(因为我无法访问您拥有的开发环境),但这是如何继续进行的。 RxJS没有很多具有并发参数的运算符,但您几乎总能通过.merge(maxConcurrent)
执行所需的操作。
答案 1 :(得分:1)
我刚刚用RxJs 5解决了类似的问题,所以我希望解决方案可以帮助其他人解决类似的问题。
// Simulate always processing 2 requests in parallel (when one is finished it starts processing one more),
// retry two times, push error on stream if retry fails.
//const Rx = require('rxjs-es6/Rx');
// -- Global variabel just to show that it works. --
let parallelRequests = 0;
// --------------------------------------------------
function simulateRequest(req) {
console.log("Request " + req);
// --- To log retries ---
var retry = 0;
// ----------------------
// Can't retry a promise, need to restart before the promise is made.
return Rx.Observable.of(req).flatMap(req => new Promise((resolve, reject) => {
var random = Math.floor(Math.random() * 2000);
// -- To show that it works --
if (retry) {
console.log("Retrying request " + req + " ,retry " + retry);
} else {
parallelRequests++;
}
// ---------------------------
setTimeout(() => {
if (random < 900) {
retry++;
return reject(req + " !!!FAILED!!!");
}
return resolve(req);
}, random);
})).retry(2).catch(e => Rx.Observable.of(e));
}
Rx.Observable.range(1, 10)
.flatMap(e => simulateRequest(e), null, 2)
// -- To show that it works --
.do(() => {
console.log("ParallelRequests " + parallelRequests);
parallelRequests--;
})
// ---------------------------
.subscribe(e => console.log("Response from request " + e), e => console.log("Should not happen, error: " + e), e => console.log("Finished"));
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.6/dist/global/Rx.umd.js"></script>