4

私は手で構築したファイル サーバーのストレス テストにsiegeを使用しています。小さなファイル (1KB 未満) ではかなりうまく機能しますが、1MB のファイルでテストすると、期待どおりに機能しません。

以下は、小さなファイルを使用したテストの結果です。

neevek@~$ siege -c 1000 -r 10 -b http://127.0.0.1:9090/1KB.txt
** SIEGE 2.71
** Preparing 1000 concurrent users for battle.
The server is now under siege..      done.

Transactions:              10000 hits
Availability:             100.00 %
Elapsed time:               9.17 secs
Data transferred:           3.93 MB
Response time:              0.01 secs
Transaction rate:        1090.51 trans/sec
Throughput:             0.43 MB/sec
Concurrency:                7.29
Successful transactions:       10000
Failed transactions:               0
Longest transaction:            1.17
Shortest transaction:           0.00

以下は、1MB のファイルを使用したテストの結果です。

neevek@~$ siege -c 1000 -r 10 -b http://127.0.0.1:9090/1MB.txt
** SIEGE 2.71
** Preparing 1000 concurrent users for battle.
The server is now under siege...[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer
[error] socket: unable to connect sock.c:222: Connection reset by peer
[error] socket: unable to connect sock.c:222: Connection reset by peer
[error] socket: unable to connect sock.c:222: Connection reset by peer
[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer
[error] socket: unable to connect sock.c:222: Connection reset by peer
[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer
[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer
[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer
[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer

siege上記のエラーで終了しても、ファイル サーバーは固定数のWRITABLESelectionKey でスピンします。つまりSelector.select()、50 などの固定数を返し続けます。

上記のテストでは、ファイル サーバーが 50 を超える同時接続を受け入れることができないように見えます。これは、小さなファイルでテストを実行すると、サーバーが 1 つまたは 2 つの SelectionKeys であることに気付き、大きなselectファイルで実行すると、select毎回50まで。

仕方なく増やそうとしbacklogましたSocket.bind()

問題の原因は何ですか?

編集

より詳しい情報:

1MB のファイルでテストしたところ、エラーでsiege終了し、ファイル サーバーは198の接続しか受け入れないことに気付きましたが、 1000 の同時接続 x 10 ラウンド (1000*10=10000) を指定してサーバーをフラッディングしました。Broken pipe

編集2

同じ問題を再現するために、次のコード (単一のクラス) でテストしました。このコードでは、接続のみを受け入れ読み取り書き込みsiege行いません。また、Selector が選択できるキーは 1000 個未満であることにも気付きました。以下のコードを試して問題を確認してください。Connection resetBroken pipe

public class TestNIO implements Runnable {
    ServerSocketChannel mServerSocketChannel;
    Selector mSelector;

    public static void main(String[] args) throws Exception {
        new TestNIO().start();
    }

    public TestNIO () throws Exception {
       mSelector = Selector.open();
    }

    public void start () throws Exception {
        mServerSocketChannel = ServerSocketChannel.open();
        mServerSocketChannel.configureBlocking(false);
        mServerSocketChannel.socket().bind(new InetSocketAddress(9090));
        mServerSocketChannel.socket().setSoTimeout(150000);
        mServerSocketChannel.register(mSelector, SelectionKey.OP_ACCEPT);

        int port = mServerSocketChannel.socket().getLocalPort();
        String serverName = "http://" + InetAddress.getLocalHost().getHostName() + ":" + port;
        System.out.println("Server start listening on " + serverName);

        new Thread(this).start();

    }

    @Override
    public void run() {
        try {
            Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
            while (true) {
                int num = mSelector.select();

                System.out.println("SELECT = " + num + "/" + mSelector.keys().size());
                if (num > 0) {
                    Iterator<SelectionKey> keys = mSelector.selectedKeys().iterator();

                    while (keys.hasNext()) {
                        final SelectionKey key = keys.next();

                        if (key.isValid() && key.isAcceptable()) {
                            accept(key);
                        }

                    }
                    // clear the selected keys
                    mSelector.selectedKeys().clear();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void accept (SelectionKey key) throws IOException {
        SocketChannel socketChannel = mServerSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.socket().setSoTimeout(1000000);
        socketChannel.socket().setKeepAlive(true);
        // since we are connected, we are ready to READ
        socketChannel.register(mSelector, SelectionKey.OP_READ);
    }
}
4

3 に答える 3

0

開いているファイル (ファイル記述子) の数の ulimit とハード リミットを確認します。

Linuxを使用していると思います。limits.conf /etc/security/limits.conf を見ることができます

于 2012-07-09T09:48:38.507 に答える
0

この問題は私のコードに関連していない可能性があります。ローカルで実行されている nginx サーバー (MacOSX) に対して同じテストを実行すると、同じエラーが発生しました。そのため、ハードウェアまたはsiegeクライアントに関連している可能性が最も高いです。

于 2012-07-09T16:44:23.173 に答える