2016-07-07 1 views
1

多くのWebリクエスト(〜300000)を作成するスクリプトがあります。これは、問題は、各関数は非同期でファイルディスクリプタを使用してそれぞれの要求、何千ものを作っているので、私はToo many open files例外に実行されるということです。このplay.api.libs.wsを使用したバッチリクエスト

// Setup a new wsClient 
val config = new NingAsyncHttpClientConfigBuilder(DefaultWSClientConfig()).build 
val builder = new AsyncHttpClientConfig.Builder(config) 
val wsClient = new NingWSClient(builder.build) 

// Each of these use the wsClient 
def getAs: Future[Seq[A]] = { ... } 
def getBs: Future[Seq[B]] = { ... } 
def getCs: Future[Seq[C]] = { ... } 
def getDs: Future[Seq[D]] = { ... } 

(for { 
    as <- getAs 
    bs <- getBs 
    cs <- getCs 
    ds <- getDs 
} yield (as, bs, cs, ds)).map(tuple => println("done")) 

ようになります。

私はそれぞれが独自のクライアントとのバッチを作るなるように、私の機能を再編成しようとした:

def getAs: Future[Seq[A]] = { 
    someCollection.group(1000).map(batch => { 
     val client = new NingWSClient(builder.build) // Make a new client for every batch 
     Future.sequence(batch.map(thing => { 
      wsClient.url(...).map(...) 
     })).map(things => { 
      wsClient.close // Close the client 
      things 
     }) 
    }) 
} 

しかし、これは早期に終了するため、理解させる(すべてのエラーメッセージまたは例外なし):

(for { 
    as <- getAs 
    bs <- getBs // This doesn't happen 
    cs <- getCs // Or any of the following ones 
    ds <- getDs 
} yield (as, bs, cs, ds)).map(tuple => println("done")) 

私はあまりにも多くのファイル記述子を開くことなく、HTTPリクエストを大量に作るための正しい方法を探しています。

答えて

2

1つのWebサービス(〜500 +)に対する要求が多すぎます。 グループ化したコード例はほぼ正しいですが、Iterator[Future[List[Int]]]、またはFuture.sequence -dの場合はFuture[Iterator[List[Int]]]となります。しかし、私は彼らがすべては非同期に実行されると思う。あなたは最初のバッチを起動してからflatMap(完了するまで待ってください)し、次のバッチを起動する必要があります。これはthis answer以下、私が書くことに成功してきたものである:

val futureIterator = list.grouped(50).foldLeft(Future.successful[List[Int]](Nil)) { 
    (fItems, items) => 
    fItems flatMap { processed => 
     println("PROCESSED: " + processed); println("SPAWNED: " + items); 
     Future.traverse(items)(getFuture) map (res => processed ::: res) 
    } 
} 
println(Await.result(futureIterator, Duration.Inf)) 

は、この情報がお役に立てば幸い!

0

あなたはOctopartsを使用することができます。

https://m3dev.github.io/octoparts/

いますが、wsClient外に呼び出しを行っているので、パターンを逆にするようにそれは本当に鳴り、その後、あなたが未来[WSResponse]戻ってくるflatmapでる。 AsyncHttpClientで使用される内部Nettyスレッドプールへの先物の数が制限され、設定を変更してNettyチャネルプールのスレッド数を増減できます。

関連する問題