質問: ○問題 node.jsでプロキシを書いています。 重いPOSTコンテンツをプロキシすると途中で切断されるという現象が起きました。 1クライアント → 2node.jsプロキシ → 3Webサーバー プロキシの方法としては、2のところでdataイベントで受けたchankを少しずつWebサーバーへ送っています。 この方法だと途中でnode.jsが耐え切れなくなるのか、重いコンテンツをPOSTすると切断されてしまいます。軽いコンテンツのPOSTはうまくいきます。 ちなみに、一度クライアントからPOSTデータを全て受け取ってからWebサーバーへリクエストを送信するとうまく動きます。 うまくいかないのは、dataイベントで受信しつつWebサーバーへ送信を繰り返す処理の場合です。 色々調べたところ、 node.jsのstreamは内部にhighWaterMarkというバッファを持っていて、この総量に限界が来ているのではないかと思っています。 このhighWaterMarkを増やす方法はありますか? Httpサーバーは普通の作法で以下のように作成しています。 ``` https.createServer(options, function (request, response) { ``` このrequestとresponseのそれぞれのhighWaterMarkを増やすことができれば解決すると考えています。 steramのコンストラクタでhighWaterMarkを増やせるのは調べてわかりましたが、上記のような生成されたオブジェクトで増やすことは可能なのでしょうか? ソースコードは理由があって全て載せられないですが、 基本的に無理な負荷をかけなければ正しく快適に動くのでプログラムのどこかが間違っているということは無い前提で答えていただいてかまいません。 補足 書き忘れましたが、node.jsの公式サイトを見るとPIPEで繋げば内部バッファを気にしなくていいみたいなことが書かれていましたが、PIPEで繋いでもやはり負荷によるエラーが発生します。 ですので、内部バッファを増やすことができないかと考えました。
回答: 試したことは無いのですが > > highWaterMarkを増やす方法 > > > は が参考になるでしょうか? 上記だと `fs.createReadStream` を利用していますが `highWaterMark` を調整できているようです。 以下追記です。 調べてみたところ以下のような方法でできそうな感じでした。 ``` 'use strict'; const fs = require('fs'); const https = require('https'); https.createServer({ key: fs.readFileSync('./certs/server.key'), cert: fs.readFileSync('./certs/server.crt') }, (request, response) => { request._readableState.highWaterMark = 16 * 1024 * 2; console.log(request._readableState.highWaterMark); response.writeHead(200, { 'Content-Type': 'text/plain' }); response.write('Hello World'); response.end(); }) .listen(8888); ``` 調べ方ですが以下のような感じでみてみました。 highWaterMark は Readable.prototype.read の中で this._state.highWaterMark という値を取り出して利用されているようでしたので、この this._state.highWaterMark を書き換えることができれば https.createServer でも可能な感じでした。 this._state.highWaterMark は _stream_readable モジュールの Readable が new されたタイミングで ReadableState に設定されており、 最終的に Readable._state.highWaterMark へアクセスできれば書き換えが可能そうでした。 createServer の requestListener で受け取る ClientRequest は OutgoingMessage を継承しており、OutgoingMessage は Stream を継承しているようでしたので ClientRequest の _state.highWaterMark が書き換え可能かなと判断して上記のサンプルコードを書いてみました。