私はScalaを初めて使用するので、問題を解決するためにしばらく時間を費やしましたが、質問は非常に単純かもしれません。私は単純なScalaTCPサーバーを持っています(アクターなし、シングルスレッド):
import java.io._
import java.net._
object Application {
def readSocket(socket: Socket): String = {
val bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream))
var request = ""
var line = ""
do {
line = bufferedReader.readLine()
if (line == null) {
println("Stream terminated")
return request
}
request += line + "\n"
} while (line != "")
request
}
def writeSocket(socket: Socket, string: String) {
val out: PrintWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream))
out.println(string)
out.flush()
}
def main(args: Array[String]) {
val port = 8000
val serverSocket = new ServerSocket(port)
while (true) {
val socket = serverSocket.accept()
readSocket(socket)
writeSocket(socket, "HTTP/1.1 200 OK\r\n\r\nOK")
socket.close()
}
}
}
サーバーは着信要求をリッスンし、本文に1つの単語localhost:8000
を含むHTTP応答を送信します。OK
次に、次のようにApacheBenchmarkを実行します。
ab -c 1000 -n 10000 http://localhost:8000/
これは初めてうまく機能します。2回目に起動ab
するとハングし、次の出力が生成されnetstat -a | grep 8000
ます。
....
tcp 0 0 localhost.localdo:43709 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43711 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43717 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43777 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43722 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43725 localhost.localdom:8000 FIN_WAIT2
tcp6 0 0 [::]:8000 [::]:* LISTEN
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43724 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43786 CLOSE_WAIT
tcp6 1 0 localhost.localdom:8000 localhost.localdo:43679 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43735 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43757 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43754 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43723 CLOSE_WAIT
....
それ以降、サーバーはこれ以上リクエストを処理しません。もう1つの詳細:ab
同じパラメーターを持つ同じスクリプトは、同じマシン上で単純なNode.jsサーバーをスムーズにテストします。したがって、この問題は、再利用可能に設定した、開いているTCP接続の数とは関係ありません。
sudo sysctl -w net.ipv4.tcp_tw_recycle=1
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
誰かが私が欠けているものについての手がかりを私に与えることができますか?
編集:ストリーム処理の終了が上記のコードに追加されました:
if (line == null) {
println("Stream terminated")
return request
}