reactphp / socket

Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP.
https://reactphp.org/socket/
MIT License
1.21k stars 157 forks source link

Looks like there are too many opened sockets... Leak? #21

Closed qfox closed 8 years ago

qfox commented 9 years ago

Ref: https://github.com/reactphp/http/issues/27

Versions:

$ uname -a
Linux dev.qfox.ru 3.2.0-4-486 #1 Debian 3.2.51-1 i686 GNU/Linux
$ php -v
PHP 5.4.38-1~dotdeb.1 (cli) (built: Feb 19 2015 22:21:23)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with Xdebug v2.3.1, Copyright (c) 2002-2015, by Derick Rethans

I have a simple file app.php:

require 'vendor/autoload.php';

$app = function ($request, $response) {
    $response->writeHead(200, array('Content-Type' => 'text/plain'));
    $response->end("Hello World\n");
};

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);

$http->on('request', $app);
echo "Server running at http://0.0.0.0:1337\n";

$socket->listen(1337, '0.0.0.0');
$loop->run();

With installed react/http (here is my composer.json):

{
    "require": {
        "react/http": "0.3.*"
    }
}

Running it:

$ php app.php
Server running at http://127.0.0.1:1337

And sending 10k requests:

$ ab -n 10000 -c 500 http://localhost:1337/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
apr_socket_recv: Connection reset by peer (104)
Total of 9953 requests completed

Why some of requests was reseted by peer? Something is wrong?

skedone commented 9 years ago

Same issue using socket instead of http server.

<?php
require 'vendor/autoload.php';

    $loop = React\EventLoop\Factory::create();

    $socket = new React\Socket\Server($loop);
    $socket->on('connection', function ($conn) {
        $conn->write("Hello there!\n");
        $conn->write("Welcome to this amazing server!\n");
        $conn->write("Here's a tip: don't say anything.\n");

        $conn->on('data', function ($data) use ($conn) {
            $conn->close();
        });
    });
    $socket->listen(1338);

    $loop->run();
WyriHaximus commented 9 years ago

Issue happens on both 0.3 and 0.4 of react with both the default stream_select loop and libevent loop. When running ab with verbose level 4 (ab -n 10000 -c 500 -v 4 http://localhost:1337/) these are the last few lines for me, showing it gets a response status code header:

LOG: Response code = 200
LOG: header received:
HTTP/1.1 200 OK
X-Powered-By: React/alpha
Content-Type: text/plain
Transfer-Encoding: chunked

c
Hello World

0

LOG: Response code = 200
apr_socket_recv: Connection reset by peer (104)
Total of 9662 requests completed

Another interesting thing is that one ab closes I can just start it up again and got another 9500ish request out of it. Also doing two at the same time gets 9000+ on one and 5000+ on the other but usally better.

clue commented 8 years ago

I've tried to reproduce this by creating a socket server and then start several batches of 500 client connections each, but memory consumption stayed constant.

Can anybody give any steps to reproduce this (possibly without using the HTTP component)?

migmam commented 8 years ago

Hi, I'd like to know the current status of this issue. Regards.

clue commented 8 years ago

Can anybody give any steps to reproduce this (possibly without using the HTTP component)?

We have yet to reproduce this. Unless anybody can come up with some steps to reproduce, I'm not even sure we actually have an issue here.

migmam commented 8 years ago

Hi again clue. I have tested using socket and it works ok, so I think is not related to socket. But I have performed the same test with Http and it fails.

Here is my code and results:

Code socket:

#!/usr/bin/php
<?php
require 'vendor/autoload.php';

    $loop = React\EventLoop\Factory::create();

    $socket = new React\Socket\Server($loop);
    $socket->on('connection', function ($conn) {
        $conn->write("Hello there!\n");
        $conn->write("Welcome to this amazing server!\n");
        $conn->write("Here's a tip: don't say anything.\n");

        $conn->on('data', function ($data) use ($conn) {
            $conn->close();
        });
    });
    $socket->listen(5000);

    $loop->run();
?>

Results:

ab -n 10000 -c 500 http://localhost:5000/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests

Server Software:
Server Hostname:        localhost
Server Port:            5000

Document Path:          /
Document Length:        0 bytes

Concurrency Level:      500
Time taken for tests:   0.890 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      9164 bytes
HTML transferred:       0 bytes
Requests per second:    11239.67 [#/sec] (mean)
Time per request:       44.485 [ms] (mean)
Time per request:       0.089 [ms] (mean, across all concurrent requests)
Transfer rate:          10.06 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.3      0      15
Processing:     2    3   6.9      2     435
Waiting:        0    0   0.2      0       4
Total:          2    3   7.1      2     437

Percentage of the requests served within a certain time (ms)
  50%      2
  66%      3
  75%      3
  80%      3
  90%      3
  95%      4
  98%      4
  99%     14
 100%    437 (longest request)

With http. Code:

#!/usr/bin/php
<?php
require 'vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);

$http->on('request', function ($req, $res) {

print_r($req);

    $req->on('data', function($data) use ($req, $res) {

            $res->writeHead(200,
            array(
                    'Access-Control-Allow-Origin'=>'*',
                     'Content-Type' => 'text/plain'
             ));

            $res->end("Ok\n");
    });
});

$socket->listen(5000);
$loop->run();
?>

Result:

 ab -n 10000 -c 500 http://localhost:5000/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
**apr_socket_recv: Connection reset by peer (104)**
Total of 5179 requests completed

Regards.


Edit by @clue: Updated formatting to use code blocks.

clue commented 8 years ago

Thanks for reporting back @migmam! It looks like there might indeed be a memory issue in react/http, may I ask you to file a new issue in the relevant component so we can close this? :+1:

nazarnovak commented 8 years ago

@clue is the issue confirmed? Could someone please report back on the current state of HTTP in regards to mass requests?

clue commented 8 years ago

@arnode nope, we have yet to confirm any kind of memory leak.

Looking at this thread more carefully, this seems to be a socket error which we have yet to look into. Note that this doesn't necessarily have to be an issue in this library, this could also be your OS, firewall, whatever that's limiting the number of new or concurrent connections.

clue commented 8 years ago

Closing this due to a lack of feedback, as we can not reproduce this. Please come back with more details if this problem persists and we can reopen this :+1:

Also, perhaps file a new issue in react/http if this only happens in the HTTP component?

arunnabraham commented 2 years ago

This could be related to ulimit. you can check the ulimit based ulimit -n . Probably increasing would fix the issue