Giter Site home page Giter Site logo

php-cp's Introduction

Swoole Logo
Swoole is an event-driven, asynchronous, coroutine-based concurrency library with high performance for PHP.

lib-swoole ext-swoole test-linux Frameworks Tests codecov

Twitter Discord Latest Release License Coverity Scan Build Status

⚙️ Quick Start

Run Swoole program by Docker

docker run --rm phpswoole/swoole "php --ri swoole"

For details on how to use it, see: How to Use This Image.

Documentation

https://wiki.swoole.com/

HTTP Service

$http = new Swoole\Http\Server('127.0.0.1', 9501);
$http->set(['hook_flags' => SWOOLE_HOOK_ALL]);

$http->on('request', function ($request, $response) {
    $result = [];
    Co::join([
        go(function () use (&$result) {
            $result['google'] = file_get_contents("https://www.google.com/");
        }),
        go(function () use (&$result) {
            $result['taobao'] = file_get_contents("https://www.taobao.com/");
        })
    ]);
    $response->end(json_encode($result));
});

$http->start();

Concurrency

Co\run(function() {
    Co\go(function() {
        while(1) {
            sleep(1);
            $fp = stream_socket_client("tcp://127.0.0.1:8000", $errno, $errstr, 30);
            echo fread($fp, 8192), PHP_EOL;
        }
    });

    Co\go(function() {
        $fp = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
        while(1) {
            $conn = stream_socket_accept($fp);
            fwrite($conn, 'The local time is ' . date('n/j/Y g:i a'));
        }
    });

    Co\go(function() {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        while(true) {
            $redis->subscribe(['test'], function ($instance, $channelName, $message) {
                echo 'New redis message: '.$channelName, "==>", $message, PHP_EOL;
            });
        }
    });

    Co\go(function() {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $count = 0;
        while(true) {
            sleep(2);
            $redis->publish('test','hello, world, count='.$count++);
        }
    });
});

Runtime Hook

Swoole hooks the blocking io function of PHP at the bottom layer and automatically converts it to a non-blocking function, so that these functions can be called concurrently in coroutines.

Supported extension/functions

  • ext-curl (Support symfony and guzzle)
  • ext-redis
  • ext-mysqli
  • ext-pdo_mysql
  • ext-pdo_pgsql
  • ext-pdo_sqlite
  • ext-pdo_oracle
  • ext-pdo_odbc
  • stream functions (e.g. stream_socket_client/stream_socket_server), Supports TCP/UDP/UDG/Unix/SSL/TLS/FileSystem API/Pipe
  • ext-sockets
  • ext-soap
  • sleep/usleep/time_sleep_until
  • proc_open
  • gethostbyname/shell_exec/exec
  • fread/fopen/fsockopen/fwrite/flock

🛠 Develop & Discussion

💎 Awesome Swoole

Project Awesome Swoole maintains a curated list of awesome things related to Swoole, including

  • Swoole-based frameworks and libraries.
  • Packages to integrate Swoole with popular PHP frameworks, including Laravel, Symfony, Slim, and Yii.
  • Books, videos, and other learning materials about Swoole.
  • Debugging, profiling, and testing tools for developing Swoole-based applications.
  • Coroutine-friendly packages and libraries.
  • Other Swoole related projects and resources.

✨ Event-based

The network layer in Swoole is event-based and takes full advantage of the underlying epoll/kqueue implementation, making it really easy to serve millions of requests.

Swoole 4.x uses a brand new engine kernel and now it has a full-time developer team, so we are entering an unprecedented period in PHP history which offers a unique possibility for rapid evolution in performance.

⚡ Coroutine

Swoole 4.x or later supports the built-in coroutine with high availability, and you can use fully synchronized code to implement asynchronous performance. PHP code without any additional keywords, the underlying automatic coroutine-scheduling.

Developers can understand coroutines as ultra-lightweight threads, and you can easily create thousands of coroutines in a single process.

MySQL

Concurrency 10K requests to read data from MySQL takes only 0.2s!

$s = microtime(true);
Co\run(function() {
    for ($c = 100; $c--;) {
        go(function () {
            $mysql = new Swoole\Coroutine\MySQL;
            $mysql->connect([
                'host' => '127.0.0.1',
                'user' => 'root',
                'password' => 'root',
                'database' => 'test'
            ]);
            $statement = $mysql->prepare('SELECT * FROM `user`');
            for ($n = 100; $n--;) {
                $result = $statement->execute();
                assert(count($result) > 0);
            }
        });
    }
});
echo 'use ' . (microtime(true) - $s) . ' s';

Mixed server

You can create multiple services on the single event loop: TCP, HTTP, Websocket and HTTP2, and easily handle thousands of requests.

function tcp_pack(string $data): string
{
    return pack('N', strlen($data)) . $data;
}
function tcp_unpack(string $data): string
{
    return substr($data, 4, unpack('N', substr($data, 0, 4))[1]);
}
$tcp_options = [
    'open_length_check' => true,
    'package_length_type' => 'N',
    'package_length_offset' => 0,
    'package_body_offset' => 4
];
$server = new Swoole\WebSocket\Server('127.0.0.1', 9501, SWOOLE_BASE);
$server->set(['open_http2_protocol' => true]);
// http && http2
$server->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) {
    $response->end('Hello ' . $request->rawcontent());
});
// websocket
$server->on('message', function (Swoole\WebSocket\Server $server, Swoole\WebSocket\Frame $frame) {
    $server->push($frame->fd, 'Hello ' . $frame->data);
});
// tcp
$tcp_server = $server->listen('127.0.0.1', 9502, SWOOLE_TCP);
$tcp_server->set($tcp_options);
$tcp_server->on('receive', function (Swoole\Server $server, int $fd, int $reactor_id, string $data) {
    $server->send($fd, tcp_pack('Hello ' . tcp_unpack($data)));
});
$server->start();

Coroutine clients

Whether you DNS query or send requests or receive responses, all of these are scheduled by coroutine automatically.

go(function () {
    // http
    $http_client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9501);
    assert($http_client->post('/', 'Swoole Http'));
    var_dump($http_client->body);
    // websocket
    $http_client->upgrade('/');
    $http_client->push('Swoole Websocket');
    var_dump($http_client->recv()->data);
});
go(function () {
    // http2
    $http2_client = new Swoole\Coroutine\Http2\Client('localhost', 9501);
    $http2_client->connect();
    $http2_request = new Swoole\Http2\Request;
    $http2_request->method = 'POST';
    $http2_request->data = 'Swoole Http2';
    $http2_client->send($http2_request);
    $http2_response = $http2_client->recv();
    var_dump($http2_response->data);
});
go(function () use ($tcp_options) {
    // tcp
    $tcp_client = new Swoole\Coroutine\Client(SWOOLE_TCP);
    $tcp_client->set($tcp_options);
    $tcp_client->connect('127.0.0.1', 9502);
    $tcp_client->send(tcp_pack('Swoole Tcp'));
    var_dump(tcp_unpack($tcp_client->recv()));
});

Channel

Channel is the only way for exchanging data between coroutines, the development combination of the Coroutine + Channel is the famous CSP programming model.

In Swoole development, Channel is usually used for implementing connection pool or scheduling coroutine concurrent.

The simplest example of a connection pool

In the following example, we have a thousand concurrently requests to redis. Normally, this has exceeded the maximum number of Redis connections setting and will throw a connection exception, but the connection pool based on Channel can perfectly schedule requests. We don't have to worry about connection overload.

class RedisPool
{
    /**@var \Swoole\Coroutine\Channel */
    protected $pool;

    /**
     * RedisPool constructor.
     * @param int $size max connections
     */
    public function __construct(int $size = 100)
    {
        $this->pool = new \Swoole\Coroutine\Channel($size);
        for ($i = 0; $i < $size; $i++) {
            $redis = new \Swoole\Coroutine\Redis();
            $res = $redis->connect('127.0.0.1', 6379);
            if ($res == false) {
                throw new \RuntimeException("failed to connect redis server.");
            } else {
                $this->put($redis);
            }
        }
    }

    public function get(): \Swoole\Coroutine\Redis
    {
        return $this->pool->pop();
    }

    public function put(\Swoole\Coroutine\Redis $redis)
    {
        $this->pool->push($redis);
    }

    public function close(): void
    {
        $this->pool->close();
        $this->pool = null;
    }
}

go(function () {
    $pool = new RedisPool();
    // max concurrency num is more than max connections
    // but it's no problem, channel will help you with scheduling
    for ($c = 0; $c < 1000; $c++) {
        go(function () use ($pool, $c) {
            for ($n = 0; $n < 100; $n++) {
                $redis = $pool->get();
                assert($redis->set("awesome-{$c}-{$n}", 'swoole'));
                assert($redis->get("awesome-{$c}-{$n}") === 'swoole');
                assert($redis->delete("awesome-{$c}-{$n}"));
                $pool->put($redis);
            }
        });
    }
});

Producer and consumers

Some Swoole's clients implement the defer mode for concurrency, but you can still implement it flexible with a combination of coroutines and channels.

go(function () {
    // User: I need you to bring me some information back.
    // Channel: OK! I will be responsible for scheduling.
    $channel = new Swoole\Coroutine\Channel;
    go(function () use ($channel) {
        // Coroutine A: Ok! I will show you the github addr info
        $addr_info = Co::getaddrinfo('github.com');
        $channel->push(['A', json_encode($addr_info, JSON_PRETTY_PRINT)]);
    });
    go(function () use ($channel) {
        // Coroutine B: Ok! I will show you what your code look like
        $mirror = Co::readFile(__FILE__);
        $channel->push(['B', $mirror]);
    });
    go(function () use ($channel) {
        // Coroutine C: Ok! I will show you the date
        $channel->push(['C', date(DATE_W3C)]);
    });
    for ($i = 3; $i--;) {
        list($id, $data) = $channel->pop();
        echo "From {$id}:\n {$data}\n";
    }
    // User: Amazing, I got every information at earliest time!
});

Timer

$id = Swoole\Timer::tick(100, function () {
    echo "⚙️ Do something...\n";
});
Swoole\Timer::after(500, function () use ($id) {
    Swoole\Timer::clear($id);
    echo "⏰ Done\n";
});
Swoole\Timer::after(1000, function () use ($id) {
    if (!Swoole\Timer::exists($id)) {
        echo "✅ All right!\n";
    }
});

The way of coroutine

go(function () {
    $i = 0;
    while (true) {
        Co::sleep(0.1);
        echo "📝 Do something...\n";
        if (++$i === 5) {
            echo "🛎 Done\n";
            break;
        }
    }
    echo "🎉 All right!\n";
});

🔥 Amazing runtime hooks

As of Swoole v4.1.0, we added the ability to transform synchronous PHP network libraries into co-routine libraries using a single line of code.

Simply call the Swoole\Runtime::enableCoroutine() method at the top of your script. In the sample below we connect to php-redis and concurrently read 10k requests in 0.1s:

Swoole\Runtime::enableCoroutine();
$s = microtime(true);
Co\run(function() {
    for ($c = 100; $c--;) {
        go(function () {
            ($redis = new Redis)->connect('127.0.0.1', 6379);
            for ($n = 100; $n--;) {
                assert($redis->get('awesome') === 'swoole');
            }
        });
    }
});
echo 'use ' . (microtime(true) - $s) . ' s';

By calling this method, the Swoole kernel replaces ZendVM stream function pointers. If you use php_stream based extensions, all socket operations can be dynamically converted to be asynchronous IO scheduled by coroutine at runtime!

How many things you can do in 1s?

Sleep 10K times, read, write, check and delete files 10K times, use PDO and MySQLi to communicate with the database 10K times, create a TCP server and multiple clients to communicate with each other 10K times, create a UDP server and multiple clients to communicate with each other 10K times... Everything works well in one process!

Just see what the Swoole brings, just imagine...

Swoole\Runtime::enableCoroutine();
$s = microtime(true);
Co\run(function() {
    // i just want to sleep...
    for ($c = 100; $c--;) {
        go(function () {
            for ($n = 100; $n--;) {
                usleep(1000);
            }
        });
    }

    // 10K file read and write
    for ($c = 100; $c--;) {
        go(function () use ($c) {
            $tmp_filename = "/tmp/test-{$c}.php";
            for ($n = 100; $n--;) {
                $self = file_get_contents(__FILE__);
                file_put_contents($tmp_filename, $self);
                assert(file_get_contents($tmp_filename) === $self);
            }
            unlink($tmp_filename);
        });
    }

    // 10K pdo and mysqli read
    for ($c = 50; $c--;) {
        go(function () {
            $pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8', 'root', 'root');
            $statement = $pdo->prepare('SELECT * FROM `user`');
            for ($n = 100; $n--;) {
                $statement->execute();
                assert(count($statement->fetchAll()) > 0);
            }
        });
    }
    for ($c = 50; $c--;) {
        go(function () {
            $mysqli = new Mysqli('127.0.0.1', 'root', 'root', 'test');
            $statement = $mysqli->prepare('SELECT `id` FROM `user`');
            for ($n = 100; $n--;) {
                $statement->bind_result($id);
                $statement->execute();
                $statement->fetch();
                assert($id > 0);
            }
        });
    }

    // php_stream tcp server & client with 12.8K requests in single process
    function tcp_pack(string $data): string
    {
        return pack('n', strlen($data)) . $data;
    }

    function tcp_length(string $head): int
    {
        return unpack('n', $head)[1];
    }

    go(function () {
        $ctx = stream_context_create(['socket' => ['so_reuseaddr' => true, 'backlog' => 128]]);
        $socket = stream_socket_server(
            'tcp://0.0.0.0:9502',
            $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx
        );
        if (!$socket) {
            echo "$errstr ($errno)\n";
        } else {
            $i = 0;
            while ($conn = stream_socket_accept($socket, 1)) {
                stream_set_timeout($conn, 5);
                for ($n = 100; $n--;) {
                    $data = fread($conn, tcp_length(fread($conn, 2)));
                    assert($data === "Hello Swoole Server #{$n}!");
                    fwrite($conn, tcp_pack("Hello Swoole Client #{$n}!"));
                }
                if (++$i === 128) {
                    fclose($socket);
                    break;
                }
            }
        }
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client("tcp://127.0.0.1:9502", $errno, $errstr, 1);
            if (!$fp) {
                echo "$errstr ($errno)\n";
            } else {
                stream_set_timeout($fp, 5);
                for ($n = 100; $n--;) {
                    fwrite($fp, tcp_pack("Hello Swoole Server #{$n}!"));
                    $data = fread($fp, tcp_length(fread($fp, 2)));
                    assert($data === "Hello Swoole Client #{$n}!");
                }
                fclose($fp);
            }
        });
    }

    // udp server & client with 12.8K requests in single process
    go(function () {
        $socket = new Swoole\Coroutine\Socket(AF_INET, SOCK_DGRAM, 0);
        $socket->bind('127.0.0.1', 9503);
        $client_map = [];
        for ($c = 128; $c--;) {
            for ($n = 0; $n < 100; $n++) {
                $recv = $socket->recvfrom($peer);
                $client_uid = "{$peer['address']}:{$peer['port']}";
                $id = $client_map[$client_uid] = ($client_map[$client_uid] ?? -1) + 1;
                assert($recv === "Client: Hello #{$id}!");
                $socket->sendto($peer['address'], $peer['port'], "Server: Hello #{$id}!");
            }
        }
        $socket->close();
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client("udp://127.0.0.1:9503", $errno, $errstr, 1);
            if (!$fp) {
                echo "$errstr ($errno)\n";
            } else {
                for ($n = 0; $n < 100; $n++) {
                    fwrite($fp, "Client: Hello #{$n}!");
                    $recv = fread($fp, 1024);
                    list($address, $port) = explode(':', (stream_socket_get_name($fp, true)));
                    assert($address === '127.0.0.1' && (int)$port === 9503);
                    assert($recv === "Server: Hello #{$n}!");
                }
                fclose($fp);
            }
        });
    }
});
echo 'use ' . (microtime(true) - $s) . ' s';

⌛️ Installation

As with any open source project, Swoole always provides the most reliable stability and the most powerful features in the latest released version. Please ensure as much as possible that you are using the latest version.

Compiling requirements

  • Linux, OS X or Cygwin, WSL
  • PHP 7.2.0 or later (The higher the version, the better the performance.)
  • GCC 4.8 or later

1. Install via PECL (beginners)

pecl install swoole

2. Install from source (recommended)

Please download the source packages from Releases or:

git clone https://github.com/swoole/swoole-src.git && \
cd swoole-src

Compile and install at the source folder:

phpize && \
./configure && \
make && make install

Enable extension in PHP

After compiling and installing to the system successfully, you have to add a new line extension=swoole.so to php.ini to enable Swoole extension.

Extra compiler configurations

for example: ./configure --enable-openssl --enable-sockets

  • --enable-openssl or --with-openssl-dir=DIR
  • --enable-sockets
  • --enable-mysqlnd (need mysqlnd, it just for supporting $mysql->escape method)
  • --enable-swoole-curl

Upgrade

⚠️ If you upgrade from source, don't forget to make clean before you upgrade your swoole

  1. pecl upgrade swoole
  2. cd swoole-src && git pull && make clean && make && sudo make install
  3. if you change your PHP version, please re-run phpize clean && phpize then try to compile

Major change since version 4.3.0

Async clients and API are moved to a separate PHP extension swoole_async since version 4.3.0, install swoole_async:

git clone https://github.com/swoole/ext-async.git
cd ext-async
phpize
./configure
make -j 4
sudo make install

Enable it by adding a new line extension=swoole_async.so to php.ini.

🍭 Benchmark

  • On the open source Techempower Web Framework benchmarks Swoole used MySQL database benchmark to rank first, and all performance tests ranked in the first echelon.
  • You can just run Benchmark Script to quickly test the maximum QPS of Swoole-HTTP-Server on your machine.

🔰️ Security issues

Security issues should be reported privately, via email, to the Swoole develop team [email protected]. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

🖊️ Contribution

Your contribution to Swoole development is very welcome!

You may contribute in the following ways:

❤️ Contributors

This project exists thanks to all the people who contribute. [Contributors].

🎙️ Official Evangelist

Demin has been playing with PHP since 2000, focusing on building high-performance, secure web services. He is an occasional conference speaker on PHP and Swoole, and has been working for companies in the states like eBay, Visa and Glu Mobile for years. You may find Demin on Twitter or GitHub.

📃 License

Apache License Version 2.0 see http://www.apache.org/licenses/LICENSE-2.0.html

php-cp's People

Contributors

bukn avatar condingyz avatar gxhua avatar kilmas avatar reallovelei avatar xluohome avatar yiliaofan avatar yinzheng5 avatar yjqg6666 avatar zgs225 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-cp's Issues

一些明显的错误

cpNetwork.c:130中 handlesEPOLL_CLOSE
根本没有设置EPOLL_CLOSE方法
建议这里直接continue;

config.m4中没有检测epoll,造成未定义have_epoll,编译的时候报错的
加上 AC_CHECK_LIB(c, epoll_create, AC_DEFINE(HAVE_EPOLL, 1, [have epoll]))

使用redisProxy后,会收到错误Connection reset by peer错误

配置如下

 [common]
log_file = /tmp/phpcp.log

;the num of TCP connections release every idel_time cycles(连接空闲后的回收力度,值越大回>
收的越快,但是会造成更多的消耗)
recycle_num = 2

;In this period of time,if no process use this connection ,the TCP connection will release
(空闲连接回收的发呆时间 单位秒)
idel_time = 60

;;max query package len,exceed will throw exception(最大转发的数据包,超过跑异常5M)
max_read_len = 5242880

;run as daemonize(是否开启守护进程化)
daemonize = 1

;If the num of connection to max, whether to use the queue buffer, set to 0 throw an excep
tion(连接都被占用后,再获取连接是否使用队列缓冲,设置为0直接抛异常)
use_wait_queue = 1

max_fail_num = 1

;just the pool_server process port(端口)
port = 6253

['127.0.0.1:9200:0'];redis配置 ip:port:db号
pool_min = 3
pool_max = 60

['127.0.0.1:9201:0'];redis配置 ip:port:db号
pool_min = 3
pool_max = 60

不使用redisProxy后,立马就收不到这个错误了。

get_disable_list

get_disable_list提示未定义,其他函数可以使用,最新稳定版本1.5

想问下支持php7.1的版本吗

现在用的是php-cp1.5.0 目前看服务是正常运行的。但是用gd调试的时候发现有些异常。跟php-cp有关。所以想问问你们有测过php7.1下的兼容吗

php7下重装了php-cp失败

NOTICE: PHP message: PHP Warning: PHP Startup: Unable to load dynamic library '/data/program/php/lib/php/extensions/no-debug-non-zts-20141001/connect_pool.so' - /data/program/php/lib/php/extensions/no-debug-non-zts-20141001/connect_pool.so: undefined symbol: zval_used_for_init in Unknown on line 0

who can help me ?

请问redis 支持 multi() 吗?

$redis = new redis_connect_pool();
$redis->connect('127.0.0.1', 6379, 0.5);
$ret = $redis->multi()
->lrange($k1, 0, -1)
->lrange($k2, 0, -1)
->lrange($k3, 0, -1)
->exec();

报错PHP Fatal error: Call to a member function lrange() on a non-object in ********

redis pipe

目前的版本貌似不支持pipe,希望完善,谢谢

General error,可以读,不能写

PDOProxy:

10.0.0.2 via TCP/IPobject(pdoProxy)#50 (6) {
["use_ms"]=>
bool(false)
["config"]=>
array(1) {
["master"]=>
array(3) {
["data_source"]=>
string(55) "mysql:dbname=order;host=10.0.0.2;port=3306"
["username"]=>
string(10) "write"
["pwd"]=>
string(16) "632tKNDMdSyWM3v4"
}
}
["in_tran"]=>
bool(false)
["enable_slave"]=>
bool(true)
["data_source"]=>
string(55) "mysql:dbname=order;host=10.0.0.2;port=3306"
["cli"]=>
resource(54) of type (ConPoolClient)
}

STMT:

object(pdo_connect_pool_PDOStatement)#51 (2) {
["cli"]=>
resource(54) of type (ConPoolClient)
["data_source"]=>
string(55) "mysql:dbname=order;host=10.0.0.2;port=3306"
}

STMT->fetchAll Throws Exception:

exception 'PDOException' with message 'SQLSTATE[HY000]: General error' in /usr/sbin/pool-server:18
Stack trace:
#0 [internal function]: PDOStatement->fetchAll(2)
#1 /usr/sbin/pool-server(18): pool_server_create('/etc/pool-serve...')
#2 {main}

SQL:

    UPDATE order SET `user_id` = ?  WHERE `order_id` = ?"

    &array(1) {
      [1]=>
      int(39)
    }

    &array(1) {
      [1]=>
      int(292)
    }

    &array(1) {
      ["type"]=>
      string(4) "main"
    }

PHP & MYSQL:

[root@TEST ~]# php --version
PHP 5.6.16 (cli) (built: Nov 29 2015 18:13:35)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies

[root@TEST ~]# php --ri connect_pool
connect_pool

connect_pool support => enabled
Version => 1.4.6
Author => 郭新华,张磊
email => [email protected]

软件: MySQL
软件版本: 5.5.30-tokudb-7.1.0-log - MySQL Community Server (GPL)

主从环境下写入数据发生变化问题

重现步骤如下:

  1. 测试环境:
    thinkphp5.0.7
    php7.0.14
    mysql :5.7.16

2.修改 \thinkphp\library\think\db\Connection.php 301行:
if($config["use_connect_pool"]){ $this->links[$linkNum] = new \pdoProxy( $config['dsn'], $config['username'], $config['password'],$params); }else{ $this->links[$linkNum] = new PDO($config['dsn'], $config['username'], $config['password'], $params); } // $this->links[$linkNum] = new PDO($config['dsn'], $config['username'], $config['password'], $params);
3.修改tp5数据库配置,database.php

return [ // 数据库类型 'type' => 'mysql', 'hostname' => '192.168.0.100,192.168.0.101', 'database' => 'test_db', 'username' => 'root', 'password' => 'root', 'hostport' => '3306', 'dsn' => '', 'params' => [ ], 'charset' => 'utf8', 'prefix' => 'pre_', 'debug' => false, 'deploy' => 1, 'rw_separate' => true, 'master_num' => 1, 'slave_no' => '', 'fields_strict' => true, 'resultset_type' => 'array', 'auto_timestamp' => false, 'sql_explain' => false, 'break_reconnect' => true, "use_connect_pool" =>true, //true:使用连接池,false:不使用 "pool_param" => [ \PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, \PDO::ATTR_TIMEOUT => 3, \PDO::ATTR_CASE => \PDO::CASE_NATURAL, ], ];

4.SQL
CREATE TABLE pre_log_5(idint(11) unsigned NOT NULL AUTO_INCREMENT,user_idint(11) DEFAULT '0',total_changedecimal(15,4) DEFAULT '0.0000',use_changedecimal(15,4) DEFAULT '0.0000',nouse_changedecimal(15,4) DEFAULT '0.0000',collection_changedecimal(15,4) DEFAULT '0.0000',waitreplay_change decimal(15,4) DEFAULT '0.0000', PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

5.测试代码:

tp5下,任意建一个controller,执行下列代码:

$json=<<<JSONSTRING
{"user_id":"665","total_change":0,"use_change":-1315,"nouse_change":"1315","collection_change":0,"waitrep lay_change":0}
JSONSTRING;
db("log_5")->insert(json_decode($json,1));

6.执行结果:

+----+---------+--------------+------------+--------------+-------------------+-------------------+ | id | user_id | total_change | use_change | nouse_change | collection_change | waitreplay_change | +----+---------+--------------+------------+--------------+-------------------+-------------------+ | 4 | 665 | 0.0000 | 221.0000 | 1315.0000 | 0.0000 | 0.0000 | +----+---------+--------------+------------+--------------+-------------------+-------------------+

可以看到 use_change值与预设值不一样

多个请求的连接可以重复使用吗?

我想问下,这个扩展的连接池,是可以重复使用的吗,比方有两个请求,第一个请求连了redis和mysql,将其放入连接池,然后请求结束,第二个请求是否直接可以使用第一个的连接,而不用重新开启连接

Using php enabled "debug", cause compiling error

PHP version 7.0.9, build with:
$ ./configure --enable-debug --enable-maintainer-zts
Then, rebuild php-cp, make clean, execute phpize, then make. Got error as picture shows.
php-cp-bug

I've read msgpack7/swoole_serialize.c where error occured. The problem caused by line 614:
_zend_hash_init(ht, zend_hash_num_elements(Z_ARRVAL(retval)), ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC); The macro transfered to variable that never declared when debug mode enabled.

你好,请问connect-pool不能安装在php5.5+的版本吗?

你好,请问connect-pool不能安装在php5.5+的版本吗?
我用的php版本是5.5的,在安装这个扩展时 ./configure 配置OK,就在make install就报错了,还麻烦你看一下
cal/src/connect-pool-master/connect_pool.c -fPIC -DPIC -o .libs/connect_pool.o
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘cp_serialize’中:
/usr/local/src/connect-pool-master/connect_pool.c:343:52: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c:343:52: 附注:每个未声明的标识符在其出现的函数内只报告一次
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘cp_unserialize’中:
/usr/local/src/connect-pool-master/connect_pool.c:356:52: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘CP_INTERNAL_SERIALIZE_SEND_MEM’中:
/usr/local/src/connect-pool-master/connect_pool.c:371:5: 错误:提供给函数‘php_msgpack_serialize’的实参太少
In file included from /usr/local/src/connect-pool-master/php_connect_pool.h:75:0,
from /usr/local/src/connect-pool-master/connect_pool.c:17:
/usr/local/src/connect-pool-master/msgpack/php_msgpack.h:46:46: 附注:在此声明
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘pdo_proxy_connect’中:
/usr/local/src/connect-pool-master/connect_pool.c:408:65: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘cp_call_user_function’中:
/usr/local/src/connect-pool-master/connect_pool.c:476:109: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘pdo_proxy_pdo’中:
/usr/local/src/connect-pool-master/connect_pool.c:503:63: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c:518:25: 警告:传递‘zend_get_object_classname’的第 2 个参数时在不兼容的指针类型间转换 [默认启用]
In file included from /usr/local/php5.5.16/include/php/main/php.h:38:0,
from /usr/local/src/connect-pool-master/php_connect_pool.h:22,
from /usr/local/src/connect-pool-master/connect_pool.c:17:
/usr/local/php5.5.16/include/php/Zend/zend_API.h:344:45: 附注:需要类型‘const char *’,但实参的类型为‘char *
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘pdo_proxy_stmt’中:
/usr/local/src/connect-pool-master/connect_pool.c:559:55: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘redis_proxy_connect’中:
/usr/local/src/connect-pool-master/connect_pool.c:601:66: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
/usr/local/src/connect-pool-master/connect_pool.c: 在函数‘redis_dispatch’中:
/usr/local/src/connect-pool-master/connect_pool.c:713:63: 错误:‘tsrm_ls’未声明(在此函数内第一次使用)
make: *** [connect_pool.lo] 错误 1

PID没有生成

ini_set('memory_limit', '300M'); //防止扩展有内存泄露,超过10000次请求重启代理进程
ini_set("display_errors", "On");
define("PID_PRE", "/usr/local/php/var/run/redis_pool_");
$conf = "/usr/local/php/etc/pool.ini"; //pool_server的配置文件
用root执行的 ./pool_server start
进程都存在,是不是还有什么需要注意的。

mac install error

  1. phpize 2../configure 3.make
    mac-share:php-cp-php7 wanmin$ sudo make
    Password:
    /bin/sh /Users/wanmin/Downloads/php-cp-php7/libtool --mode=compile cc -I. -I/Users/wanmin/Downloads/php-cp-php7 -DPHP_ATOM_INC -I/Users/wanmin/Downloads/php-cp-php7/include -I/Users/wanmin/Downloads/php-cp-php7/main -I/Users/wanmin/Downloads/php-cp-php7 -I/usr/local/Cellar/php70/7.0.5/include/php -I/usr/local/Cellar/php70/7.0.5/include/php/main -I/usr/local/Cellar/php70/7.0.5/include/php/TSRM -I/usr/local/Cellar/php70/7.0.5/include/php/Zend -I/usr/local/Cellar/php70/7.0.5/include/php/ext -I/usr/local/Cellar/php70/7.0.5/include/php/ext/date/lib -I/Users/wanmin/Downloads/php-cp-php7/include -DHAVE_CONFIG_H -Wall -pthread -g -O2 -c /Users/wanmin/Downloads/php-cp-php7/connect_pool.c -o connect_pool.lo
    cc -I. -I/Users/wanmin/Downloads/php-cp-php7 -DPHP_ATOM_INC -I/Users/wanmin/Downloads/php-cp-php7/include -I/Users/wanmin/Downloads/php-cp-php7/main -I/Users/wanmin/Downloads/php-cp-php7 -I/usr/local/Cellar/php70/7.0.5/include/php -I/usr/local/Cellar/php70/7.0.5/include/php/main -I/usr/local/Cellar/php70/7.0.5/include/php/TSRM -I/usr/local/Cellar/php70/7.0.5/include/php/Zend -I/usr/local/Cellar/php70/7.0.5/include/php/ext -I/usr/local/Cellar/php70/7.0.5/include/php/ext/date/lib -I/Users/wanmin/Downloads/php-cp-php7/include -DHAVE_CONFIG_H -Wall -pthread -g -O2 -c /Users/wanmin/Downloads/php-cp-php7/connect_pool.c -fno-common -DPIC -o .libs/connect_pool.o
    In file included from /Users/wanmin/Downloads/php-cp-php7/connect_pool.c:17:
    ./php_connect_pool.h:32:10: fatal error: 'sys/epoll.h' file not found
    #include <sys/epoll.h> //todo
    ^
    1 error generated.
    make: *** [connect_pool.lo] Error 1

多个MySQL和Redis链接时Auth丢失的问题

现在建立2个Redis池和3个MySQL池,当1个MySQL池和2个Redis池连接时,使用正常,当第2个MySQL池中链接建立时,所有的Redis链接的Auth都立即失效且无法重新建立。

创建进程失败

cpCreate_worker_mem: create sys v shm. Error: Inappropriate ioctl for device [25]
cpServer_start: Fork worker process fail

这是/tmp/log里的记录,还需要其他的信息吗?

一个 warning

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20131226/connect_pool.so' - /usr/lib/php5/20131226/connect_pool.so: undefined symbol: php_pdo_get_exception in Unknown on line 0

ubuntu: 14.04
PHP:

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20131226/connect_pool.so' - /usr/lib/php5/20131226/connect_pool.so: undefined symbol: php_pdo_get_exception in Unknown on line 0
PHP 5.6.7-1+deb.sury.org~trusty+1 (cli) (built: Mar 24 2015 11:21:10)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
with Xdebug v2.2.7, Copyright (c) 2002-2015, by Derick Rethans
with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2015, by Zend Technologies

可能的内存泄露

  1. connect_pool_client.c中的
    static int _workerid2writefd = NULL;
    static int *workerid2readfd = NULL;
    static void *_semid2attbuf = NULL;
    使用原生的calloc
    没有free
    为什么不用pecalloc
  2. 每个worker中创建的共享内存, 在回收worker并没有shmctl删除

长时间空闲之后出错

我用ab 测试并发访问页面,数据池在并发下没有出错。当并发停止之后一段时间,出现下面错误。代码用的源码中的测试代码。ab -c 1000 -n 10000
Fatal error: Call to a member function fetchAll() on a non-object in

不支持执行SET NAMES utf8 只能通过dsn传入连接编码?

$ cat /home/test/sql.php
<? php
$pdo = new pdoProxy("mysql:dbname=db_test;host=db.com;port=3306", "db_user", "db_password");
var_dump($pdo);
$pdo->exec("SET NAMES utf8");
$rs = $pdo->query("show tables");
var_dump($rs->fetchAll());
$pdo->release();

CLI 执行会报Fatal error:

object(pdoProxy) # 1 (4) {
["use_ms"]=>
bool(false)
["config"]=>
array(1) {
["master"]=>
array(3) {
["data_source"]=>
string(65) "mysql:dbname=db_test;host=db.com;port=3306"
["username"]=>
string(12) "db_user"
["pwd"]=>
string(16) "db_password"
}
}
["in_tran"]=>
bool(false)
["enable_slave"]=>
bool(true)
}
PHP Fatal error: Uncaught exception 'Exception' with message 'call pdo method error!' in /home/test/sql.php:4
Stack trace:
# 0 /home/test/sql.php(4): pdoProxy->__call('exec', Array)
# 1 /home/test/sql.php(4): pdoProxy->exec('SET NAMES utf8')
# 2 {main}
thrown in /home/test/sql.php on line 4

Fatal error: Uncaught exception 'Exception' with message 'call pdo method error!' in /root/sql.php:4
Stack trace:
# 0 /home/test/sql.php(4): pdoProxy->__call('exec', Array)
# 1 /home/test/sql.php(4): pdoProxy->exec('SET NAMES utf8')
# 2 {main} thrown in /home/test/sql.php on line 4

错误抛出位置位于:

cpLog("call pdo method error!");

修改默认最大最小连接数

配置中是否可以直接修改默认的最大最小连接数?因为项目中使用的连接比较多,每个单独配置会配置很多内容

redisProxy 不支持 multi

试了一下 mutli 报错
PHP Fatal error: redisProxy::__call(): you send the request to pool worker ,but the worker is died in XXX.php on line ##

错误指的那行,就是 $redis->multi() 所在行

怎么没有说明文档?程序的架构流程是怎样的?

Hi:
有几个使用中的问题请教一下。
按照我的理解是:php里面以连接池的方式访问本机porxy已经建立好的连接池,proxy负责维护和这个连接池与其它服务的连接,那么这个proxy的配置文件里应该出现至少两组ip:port配置,一组是proxy本身listen的地址和端口,另一组需要建立连接池的对端的地址和端口。现在是proxy的配置文件里没有配置ip地址的地方,我只发现一个配置proxy服务本身listen的port可以设置,我的redis及mysql服务在其它的机器上,配置文件里没有办法指定和哪个地址的服务器端口建立连接池,那么这个连接池是怎么建立的?

[bug] pool_server stop pop error

version:1.4.4
无法执行停止,报错如下
shutdown fail. kill -SIGTERM master_pid[4659] fail. Error: No such process[3]
ps -ef|grep pool, 进程依然还在

没有测试并发,一个请求访问效率减半?是否打开姿势不对?

这里的library中redispool和redis基本一样,redispool中构建对象是使用new redisProxy(),pool.ini没改,用了默认的配置,执行结果redis: 1123ms, redispool: 2303

getMillisecond(); $this->load->library('redis'); for ($i=0; $i<10000; $i++) { $this->redis->hset("POOL1", $i, time()); } $this->redis->hgetall("POOL1"); $end = $this->getMillisecond(); echo "done ".($end-$start); } public function pool() { $start = $this->getMillisecond(); $this->load->library('redispool'); for ($i=0; $i<10000; $i++) { $this->redispool->hset("POOL1", $i, time()); } $this->redispool->hgetall("POOL1"); $end = $this->getMillisecond(); echo "done ".($end-$start); } private function getMillisecond() { list($t1, $t2) = explode(' ', microtime()); return (float)sprintf('%.0f',(floatval($t1)+floatval($t2))*1000); } ``` }

值为负的字段,读取后变成正值?这个bug有点重

使用pdoProxy建立的连接
$result = $mysqlConn -> query('select fenceId from users where userId = 5628');
$a = $result -> fetch();
print_r($a);
当fenceId为负值=-51时,居然溢出了变成了205!
再次尝试当fenceId=-999时,返回了25
使用正常的pdo均可正常返回负值

gone away......

在使用过程中若出现gone away,则需要重启pool_server才能继续访问DB;

服务器设置timeout为60s,由于需要过渡阶段,mysql依然会接受若干短连接,所以不能通过修改wait_timeout和interactive_timeout来解决问题,可有解决方案?

php5.5.21 使用php-cp过程中出core

如下:
[New LWP 8084]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `pool_ping_mysql '.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000007fadc0 in gc_remove_from_buffer (root=0x7fffae540b20) at /home/fan/www/server/php/php-5.5.21/Zend/zend_gc.h:189

189 root->next->prev = root->prev;
(gdb) bt
(gdb) bt
#0 0x00000000007fadc0 in gc_remove_from_buffer (root=0x7fffae540b20) at /home/fan/www/server/php/php-5.5.21/Zend/zend_gc.h:189
#1 gc_remove_zval_from_buffer (zv=zv@entry=0x7fffae540a40) at /home/fan/www/server/php/php-5.5.21/Zend/zend_gc.c:265
#2 0x00000000007ce008 in i_zval_ptr_dtor (zval_ptr=0x7fffae540a40)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute.h:80

#3 zend_vm_stack_clear_multiple (nested=0) at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute.h:298
#4 zend_call_function (fci=fci@entry=0x7fffae5409b0, fci_cache=, fci_cache@entry=0x0)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute_API.c:991

#5 0x00000000007ce4de in call_user_function_ex (function_table=, object_pp=object_pp@entry=0x0,

function_name=<optimized out>, retval_ptr_ptr=retval_ptr_ptr@entry=0x7fffae540a30, param_count=param_count@entry=1, 
params=params@entry=0x7fffae540a20, no_separation=no_separation@entry=0, symbol_table=symbol_table@entry=0x0)
at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute_API.c:722

#6 0x00007f3e02ed0bb8 in cpSettitle (title_name=title_name@entry=0x7fffae540c20 "ping_mysql")

at /home/fan/www/server/php/php-cp/cpFunction.c:160

#7 0x00007f3e02ed3095 in cpFork_ping_worker () at /home/fan/www/server/php/php-cp/cpPingWorker.c:149
#8 0x00007f3e02ecbdec in cpWorker_manager_loop () at /home/fan/www/server/php/php-cp/cpWorker.c:235
#9 0x00007f3e02ecaf04 in cpServer_start () at /home/fan/www/server/php/php-cp/cpServer.c:230
#10 0x00007f3e02ec3e85 in zif_pool_server_create (ht=, return_value=,

return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>)
at /home/fan/www/server/php/php-cp/connect_pool.c:302

#11 0x000000000088c86a in zend_do_fcall_common_helper_SPEC (execute_data=)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_vm_execute.h:550

#12 0x00000000008061a8 in execute_ex (execute_data=0x7f3e09ef4680)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_vm_execute.h:363

#13 0x00000000007ddb90 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3)

at /home/fan/www/server/php/php-5.5.21/Zend/zend.c:1327

#14 0x000000000077e0b5 in php_execute_script (primary_file=primary_file@entry=0x7fffae544050)

at /home/fan/www/server/php/php-5.5.21/main/main.c:2506

#15 0x000000000088e63f in do_cli (argc=3, argv=0x2e74790) at /home/fan/www/server/php/php-5.5.21/sapi/cli/php_cli.c:994
#16 0x00000000004345f0 in main (argc=3, argv=0x2e74790) at /home/fan/www/server/php/php-5.5.21/sapi/cli/php_cli.c:1378

(gdb) bt

(gdb) bt full
#0 0x00000000007fadc0 in gc_remove_from_buffer (root=0x7fffae540b20) at /home/fan/www/server/php/php-5.5.21/Zend/zend_gc.h:189

No locals.
#1 gc_remove_zval_from_buffer (zv=zv@entry=0x7fffae540a40) at /home/fan/www/server/php/php-5.5.21/Zend/zend_gc.c:265

    root_buffer = 0x7fffae540b20

#2 0x00000000007ce008 in i_zval_ptr_dtor (zval_ptr=0x7fffae540a40)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute.h:80

No locals.
#3 zend_vm_stack_clear_multiple (nested=0) at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute.h:298

    q = 0x7fffae540a40
    p = 0x7f3e09ef4760
    end = 0x7f3e09ef4760

#4 zend_call_function (fci=fci@entry=0x7fffae5409b0, fci_cache=, fci_cache@entry=0x0)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute_API.c:991
    i = <optimized out>
    original_return_value = <optimized out>
    calling_symbol_table = <optimized out>
    original_op_array = <optimized out>
    original_opline_ptr = <optimized out>
    current_scope = 0x0
    current_called_scope = 0x0
    calling_scope = <optimized out>
    called_scope = <optimized out>
    current_this = 0x0
    execute_data = {opline = 0x0, function_state = {function = 0x30bd3d0, arguments = 0x7f3e09ef4768}, op_array = 0x0, 
      object = 0x0, symbol_table = 0x1011928 <executor_globals+360>, prev_execute_data = 0x7f3e09ef4680, 
      old_error_reporting = 0x0, nested = 0 '\000', original_return_value = 0x21, current_scope = 0x21, 
      current_called_scope = 0x7f3e09ef46a8, current_this = 0x0, fast_ret = 0x21, call_slots = 0x7f3e09ef4730, 
      call = 0x7f3e09ef4730}
    fci_cache_local = {initialized = 0 '\000', function_handler = 0x30bd3d0, calling_scope = 0x0, called_scope = 0x0, 
      object_ptr = 0x0}

#5 0x00000000007ce4de in call_user_function_ex (function_table=, object_pp=object_pp@entry=0x0,

---Type to continue, or q to quit---
function_name=, retval_ptr_ptr=retval_ptr_ptr@entry=0x7fffae540a30, param_count=param_count@entry=1,
params=params@entry=0x7fffae540a20, no_separation=no_separation@entry=0, symbol_table=symbol_table@entry=0x0)
at /home/fan/www/server/php/php-5.5.21/Zend/zend_execute_API.c:722
fci = {size = 72, function_table = 0x2e753d0, function_name = 0x7f3e09f2e728, symbol_table = 0x0,
retval_ptr_ptr = 0x7fffae540a30, param_count = 1, params = 0x7fffae540a20, object_ptr = 0x0, no_separation = 0 '\000'}
#6 0x00007f3e02ed0bb8 in cpSettitle (title_name=title_name@entry=0x7fffae540c20 "ping_mysql")

at /home/fan/www/server/php/php-cp/cpFunction.c:160
    title = "pool_ping_mysql", '\000' <repeats 116 times>
    name_ptr = 0x7fffae540a40
    name = {value = {lval = 140736118131296, dval = 6.9532881097728726e-310, str = {val = 0x7fffae540a60 "pool_ping_mysql", 
          len = 15}, ht = 0x7fffae540a60, obj = {handle = 2924743264, handlers = 0xf}}, refcount__gc = 0, type = 6 '\006', 
      is_ref__gc = 0 '\000'}
    retval = 0x7f3e09f2c9e0
    args = {0x7fffae540a28}
    function = 0x7f3e09f2e728

#7 0x00007f3e02ed3095 in cpFork_ping_worker () at /home/fan/www/server/php/php-cp/cpPingWorker.c:149

    name = "ping_mysql", '\000' <repeats 116 times>
    pid = <optimized out>
    __func__ = "cpFork_ping_worker"

#8 0x00007f3e02ecbdec in cpWorker_manager_loop () at /home/fan/www/server/php/php-cp/cpWorker.c:235

    ping_pid = <optimized out>
    pid = 8083
    new_pid = <optimized out>
    i = <optimized out>
    worker_exit_code = 139
    block_alarm = {__val = {8589943296, 0 <repeats 15 times>}}
    __func__ = "cpWorker_manager_loop"

#9 0x00007f3e02ecaf04 in cpServer_start () at /home/fan/www/server/php/php-cp/cpServer.c:230

    i = <optimized out>
    pid = <optimized out>
    ret = <optimized out>

---Type to continue, or q to quit---
ping_pid =
func = "cpServer_start"
#10 0x00007f3e02ec3e85 in zif_pool_server_create (ht=, return_value=,

return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>)
at /home/fan/www/server/php/php-cp/connect_pool.c:302
    ret = <optimized out>
    config = 0x7f3e09f2cb90
    name = 0x7f3e09f2cbc0 "mysql"
    keylen = 6
    pid = <optimized out>
    conf = 0x7f3e09f2ca10
    config_file = 0x7f3e09e2a8f0 "/etc/pool.ini"
    file_len = 13
    group_id = 0

#11 0x000000000088c86a in zend_do_fcall_common_helper_SPEC (execute_data=)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_vm_execute.h:550
    ret = 0x7f3e09ef44c0
    opline = <optimized out>
    should_change_scope = 0 '\000'
    fbc = 0x2f0bd70

#12 0x00000000008061a8 in execute_ex (execute_data=0x7f3e09ef4680)

at /home/fan/www/server/php/php-5.5.21/Zend/zend_vm_execute.h:363
    ret = <optimized out>
    original_in_execution = 0 '\000'

#13 0x00000000007ddb90 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3)

at /home/fan/www/server/php/php-5.5.21/Zend/zend.c:1327
    files = {{gp_offset = 40, fp_offset = 0, overflow_arg_area = 0x7fffae541d60, reg_save_area = 0x7fffae541cf0}}
    i = 1
    file_handle = 0x7fffae544050
    orig_op_array = 0x0
    orig_retval_ptr_ptr = 0x0

---Type to continue, or q to quit---
orig_interactive = 0
#14 0x000000000077e0b5 in php_execute_script (primary_file=primary_file@entry=0x7fffae544050)

at /home/fan/www/server/php/php-5.5.21/main/main.c:2506
    realfile = "/home/fan/www/server/php/php-cp/pool_server\000\326O9\253\000\304\352\a>\177\000\000⪵\a>\177\000\000\300\023\001\001\000\000\000\000\020Ԉ\000\000\000\000\000\300\023\001\001\000\000\000\000\257Vx\000\000\000\000\000\261ϫQ\000\200\377\377\005\000\000\000w\000\000\000\001\000\000\000\000\000\000\000[\000\000\000\000\000\000\000\221ϫQ\000\200\377\377\a\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\061\000\000\000\000\000\000\000p0T\256\377\177\000\000\000\000\000\000\000\000\000\000\022\000\000\000\022", '\000' <repeats 11 times>, "\003\000\000\000\003", '\000' <repeats 27 times>...
    __orig_bailout = 0x7fffae544180
    __bailout = {{__jmpbuf = {1, 4220484695226928415, 48711648, 51108624, 0, 48711648, 4220484696235658527, 
          -4220593856142422753}, __mask_was_saved = 0, __saved_mask = {__val = {139904397522784, 32, 140736118140784, 0, 0, 
            48711648, 3855532544492760320, 16847488, 140736118145616, 51108624, 43, 0, 0, 48711648, 7841705, 51108624}}}}
    prepend_file_p = <optimized out>
    append_file_p = 0x0
    prepend_file = {type = ZEND_HANDLE_FILENAME, filename = 0x0, opened_path = 0x0, handle = {fd = 0, fp = 0x0, stream = {
          handle = 0x0, isatty = 0, mmap = {len = 0, pos = 0, map = 0x0, buf = 0x0, old_handle = 0x0, old_closer = 0x0}, 
          reader = 0x0, fsizer = 0x0, closer = 0x0}}, free_filename = 0 '\000'}
    append_file = {type = ZEND_HANDLE_FILENAME, filename = 0x0, opened_path = 0x0, handle = {fd = 0, fp = 0x0, stream = {
          handle = 0x0, isatty = 0, mmap = {len = 0, pos = 0, map = 0x0, buf = 0x0, old_handle = 0x0, old_closer = 0x0}, 
          reader = 0x0, fsizer = 0x0, closer = 0x0}}, free_filename = 0 '\000'}
    old_cwd = 0x7fffae541d70 ""
    retval = 0

#15 0x000000000088e63f in do_cli (argc=3, argv=0x2e74790) at /home/fan/www/server/php/php-5.5.21/sapi/cli/php_cli.c:994

    __orig_bailout = 0x7fffae545320
    __bailout = {{__jmpbuf = {0, 4220484698061229343, 140736118149908, 0, 0, 16699648, 4220484695220636959, 
          -4220592198598439649}, __mask_was_saved = 0, __saved_mask = {__val = {10992065, 10992089, 10865865, 10865886, 
            10992102, 10992122, 10992139, 10992693, 10992160, 10992174, 10992196, 10992215, 10992242, 10992271, 0, 
            7165064483209180463}}}}
    c = <optimized out>
    file_handle = {type = ZEND_HANDLE_MAPPED, filename = 0x2e747e0 "./pool_server", opened_path = 0x0, handle = {
        fd = 166896280, fp = 0x7f3e09f2a298, stream = {handle = 0x7f3e09f2a298, isatty = 0, mmap = {len = 1353, pos = 0, 

---Type to continue, or q to quit---
map = 0x7f3e09f64000, buf = 0x7f3e09f64013 "", old_handle = 0x30bd620,
old_closer = 0x7f2320 <zend_stream_stdio_closer>}, reader = 0x7f2350 <zend_stream_stdio_reader>,
fsizer = 0x7f22c0 <zend_stream_stdio_fsizer>, closer = 0x7f2240 <zend_stream_mmap_closer>}},
free_filename = 0 '\000'}
behavior =
reflection_what = 0x0
request_started = 1
exit_status = 0
php_optarg = 0x0
php_optind = 2
exec_direct = 0x0
exec_run = 0x0
exec_begin = 0x0
exec_end = 0x0
arg_free =
arg_excp =
script_file =
translated_path =
interactive = 0
lineno = 2
param_error =
hide_argv = 0
#16 0x00000000004345f0 in main (argc=3, argv=0x2e74790) at /home/fan/www/server/php/php-5.5.21/sapi/cli/php_cli.c:1378

    __orig_bailout = 0x0
    __bailout = {{__jmpbuf = {48712224, 4220484698061229343, 140736118149908, 0, 0, 16699648, 4220484698005654815, 
          -4220593757272453857}, __mask_was_saved = 0, __saved_mask = {__val = {139904355942584, 0, 140736118150440, 0, 
            139904431867168, 140736118150080, 140736118150064, 4131212846, 4294129, 4294967295, 139904429684055, 
            139904393658792, 139904431703288, 140733193388033, 139904393639592, 1}}}}
    c = <optimized out>
    exit_status = 0
    module_started = 1

---Type to continue, or q to quit---
sapi_started = 1
php_optarg = 0x0
php_optind = 1
use_extended_info = 0
ini_path_override = 0x0
ini_entries = 0x2e74a20 "html_errors=0\nregister_argc_argv=1\nimplicit_flush=1\noutput_buffering=0\nmax_execution_time=0\nmax_input_time=-1\n"
ini_entries_len = 0
ini_ignore = 0
sapi_module =

配置如下:
[mysql]
;the min connection num(最小连接数)
pool_min = 2
;the max connection num(最大连接数)
pool_max = 30
;the log file path(日志文件)
log_file = /tmp/mysqllog
;the num of TCP connections release every idel_time cycles(连接空闲后的回收力度,值越大回收的越快,但是会造成更多的消耗)
recycle_num = 2
;In this period of time,if no process use this connection ,the TCP connection will release(空闲连接回收的发呆时间 单位秒)
idel_time = 2
;;max query package len,exceed will throw exception(最大转发的数据包,超过跑异常5M)
max_read_len = 5242880
;run as daemonize(是否开启守护进程化)
daemonize = 1
;If the num of connection to max, whether to use the queue buffer, set to 0 throw an exception(连接都被占用后,再获取连接是否使用队列缓冲,设置为0直接抛异常)
use_wait_queue = 1
;the get_disable_list() function returns the maximum number of IP(get_disable_list函数最多返回多少个失效结点,防止网络抖动踢掉所有的机器)
max_fail_num = 1
;just the pool_server process port(端口)
port = 6253

use in multi process

Error Info: redis_connect_pool::__call(): ERROR!the connection object create in parent process and use in multi process,please create in every process
PHP ERROR TYPE: Fatal error
At File: /app/ThinkPHP/Library/Think/Session/Driver/Redis.class.php
Line Number: 42

还有另外一个错误
Error Info: redis_connect_pool::__call(): open error Error: No such file or directory [2]
PHP ERROR TYPE: Fatal error
At File: /app/ThinkPHP/Library/Think/Session/Driver/Redis.class.php
Line Number: 42

收到这个错误,环境是这样的
Docker-Apache-PHP5.3-ThinkPHP

感觉尤其不可思议,CPM上10K之后会比较容易出这个问题,然而重启之后就不会出现了,很费解,附上配置文件(*起到类似打码的作用,请不要在意)

[common]
log_file = /tmp/phpcp.log
;the num of TCP connections release every idel_time cycles(连接空闲后的回收力度,值越大回收的越快,但是会造成更多的消耗)
recycle_num = 2
;In this period of time,if no process use this connection ,the TCP connection will release(空闲连接回收的发呆时间 单位秒)
idel_time = 2
;;max query package len,exceed will throw exception(最大转发的数据包,超过跑异常5M)
max_read_len = 5242880
;run as daemonize(是否开启守护进程化)
daemonize = 1
;If the num of connection to max, whether to use the queue buffer, set to 0 throw an exception(连接都被占用后,再获取连接是否使用队列缓冲,设置为0直接抛异常)
use_wait_queue = 1
;the get_disable_list() function returns the maximum number of IP(get_disable_list函数最多返回多少个失效结点,防止网络抖动踢掉所有的机器)
max_fail_num = 1
;just the pool_server process port(端口)
port = 6253

;注意数据源需要加 ''
['mysql:host=.mysql.rds.aliyuncs.com;dbname='];mysql配置
pool_min = 5
pool_max = 30
['mysql:host=.mysql.rds.aliyuncs.com;dbname='];mysql配置
pool_min = 5
pool_max = 30
['mysql:host=.mysql.rds.aliyuncs.com;dbname='];mysql配置
pool_min = 5
pool_max = 30

['*.m.cnhza.kvstore.aliyuncs.com:6379:0'];redis配置 ip:port:db号
pool_min = 5
pool_max = 30

['*.m.cnhza.kvstore.aliyuncs.com:6379:0'];redis配置 ip:port:db号
pool_min = 5
pool_max = 30

wrk测试问题

wrk测试参数 wrk -t12 -c100 -d30s “http://xxxx.com/xx.php?uid=1234”
在没有加的时候结果,平均是
12 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 67.29ms 3.04ms 126.24ms 85.55%
Req/Sec 119.19 26.18 161.00 55.12%
42763 requests in 30.02s, 31.81MB read
Requests/sec: 1424.35
Transfer/sec: 1.06MB

加了连接池以后,平均
12 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 74.02ms 3.06ms 143.04ms 91.87%
Req/Sec 108.41 25.59 161.00 56.56%
38882 requests in 30.02s, 28.92MB read
Requests/sec: 1295.11
Transfer/sec: 0.96MB
为什么性能反而变差了,我php是7.0.3 phpfpm开了1000个,连接池开了20-1000

./php_connect_pool.h:32:10: fatal error: 'sys/epoll.h' file not found #include <sys/epoll.h> //todo

/bin/sh /Users/nate/Downloads/php-cp-1.4.8/libtool --mode=compile cc -I. -I/Users/nate/Downloads/php-cp-1.4.8 -DPHP_ATOM_INC -I/Users/nate/Downloads/php-cp-1.4.8/include -I/Users/nate/Downloads/php-cp-1.4.8/main -I/Users/nate/Downloads/php-cp-1.4.8 -I/usr/local/Cellar/php54/5.4.45_4/include/php -I/usr/local/Cellar/php54/5.4.45_4/include/php/main -I/usr/local/Cellar/php54/5.4.45_4/include/php/TSRM -I/usr/local/Cellar/php54/5.4.45_4/include/php/Zend -I/usr/local/Cellar/php54/5.4.45_4/include/php/ext -I/usr/local/Cellar/php54/5.4.45_4/include/php/ext/date/lib -I/Users/nate/Downloads/php-cp-1.4.8/include -DHAVE_CONFIG_H -Wall -pthread -g -O0 -c /Users/nate/Downloads/php-cp-1.4.8/connect_pool.c -o connect_pool.lo
mkdir .libs
cc -I. -I/Users/nate/Downloads/php-cp-1.4.8 -DPHP_ATOM_INC -I/Users/nate/Downloads/php-cp-1.4.8/include -I/Users/nate/Downloads/php-cp-1.4.8/main -I/Users/nate/Downloads/php-cp-1.4.8 -I/usr/local/Cellar/php54/5.4.45_4/include/php -I/usr/local/Cellar/php54/5.4.45_4/include/php/main -I/usr/local/Cellar/php54/5.4.45_4/include/php/TSRM -I/usr/local/Cellar/php54/5.4.45_4/include/php/Zend -I/usr/local/Cellar/php54/5.4.45_4/include/php/ext -I/usr/local/Cellar/php54/5.4.45_4/include/php/ext/date/lib -I/Users/nate/Downloads/php-cp-1.4.8/include -DHAVE_CONFIG_H -Wall -pthread -g -O0 -c /Users/nate/Downloads/php-cp-1.4.8/connect_pool.c -fno-common -DPIC -o .libs/connect_pool.o
In file included from /Users/nate/Downloads/php-cp-1.4.8/connect_pool.c:17:
./php_connect_pool.h:32:10: fatal error: 'sys/epoll.h' file not found

include <sys/epoll.h> //todo

     ^

1 error generated.
make: *** [connect_pool.lo] Error 1

下载的v1.1版本,conf 通过,make的时候报错

/bin/bash /opt/phpdevelop/php-cp-1.1/libtool --mode=compile cc -I. -I/opt/phpdevelop/php-cp-1.1 -DPHP_ATOM_INC -I/opt/phpdevelop/php-cp-1.1/include -I/opt/phpdevelop/php-cp-1.1/main -I/opt/phpdevelop/php-cp-1.1 -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/TSRM -I/usr/include/php5/Zend -I/usr/include/php5/ext -I/usr/include/php5/ext/date/lib -I/opt/phpdevelop/php-cp-1.1/include -DHAVE_CONFIG_H -g -O2 -c /opt/phpdevelop/php-cp-1.1/cpServer.c -o cpServer.lo
libtool: compile: cc -I. -I/opt/phpdevelop/php-cp-1.1 -DPHP_ATOM_INC -I/opt/phpdevelop/php-cp-1.1/include -I/opt/phpdevelop/php-cp-1.1/main -I/opt/phpdevelop/php-cp-1.1 -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/TSRM -I/usr/include/php5/Zend -I/usr/include/php5/ext -I/usr/include/php5/ext/date/lib -I/opt/phpdevelop/php-cp-1.1/include -DHAVE_CONFIG_H -g -O2 -c /opt/phpdevelop/php-cp-1.1/cpServer.c -fPIC -DPIC -o .libs/cpServer.o
/opt/phpdevelop/php-cp-1.1/cpServer.c: In function 'cpServer_master_onAccept':
/opt/phpdevelop/php-cp-1.1/cpServer.c:315:69: error: 'EPOLLIN' undeclared (first use in this function)
if (cpEpoll_add(CPGS->reactor_threads[c_pti].epfd, conn_fd, EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLPRI) < 0) {
^
/opt/phpdevelop/php-cp-1.1/cpServer.c:315:69: note: each undeclared identifier is reported only once for each function it appears in
/opt/phpdevelop/php-cp-1.1/cpServer.c:315:79: error: 'EPOLLRDHUP' undeclared (first use in this function)
if (cpEpoll_add(CPGS->reactor_threads[c_pti].epfd, conn_fd, EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLPRI) < 0) {
^
/opt/phpdevelop/php-cp-1.1/cpServer.c:315:92: error: 'EPOLLHUP' undeclared (first use in this function)
if (cpEpoll_add(CPGS->reactor_threads[c_pti].epfd, conn_fd, EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLPRI) < 0) {
^
/opt/phpdevelop/php-cp-1.1/cpServer.c:315:103: error: 'EPOLLERR' undeclared (first use in this function)
if (cpEpoll_add(CPGS->reactor_threads[c_pti].epfd, conn_fd, EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLPRI) < 0) {
^
/opt/phpdevelop/php-cp-1.1/cpServer.c:315:114: error: 'EPOLLPRI' undeclared (first use in this function)
if (cpEpoll_add(CPGS->reactor_threads[c_pti].epfd, conn_fd, EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLPRI) < 0) {
^
/opt/phpdevelop/php-cp-1.1/cpServer.c: In function 'cpReactor_thread_loop':
/opt/phpdevelop/php-cp-1.1/cpServer.c:533:13: error: 'EPOLLIN' undeclared (first use in this function)
handles[EPOLLIN] = cpReactor_client_receive;
^
/opt/phpdevelop/php-cp-1.1/cpServer.c:534:13: error: 'EPOLLPRI' undeclared (first use in this function)
handles[EPOLLPRI] = cpReactor_client_release;
^
/opt/phpdevelop/php-cp-1.1/cpServer.c: In function 'cpReactor_start':
/opt/phpdevelop/php-cp-1.1/cpServer.c:548:40: error: 'EPOLLIN' undeclared (first use in this function)
if (cpEpoll_add(accept_epfd, sock, EPOLLIN) < 0) {
^
make: *** [cpServer.lo] Error 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.