实现一个 HTTP 服务器时, 每个请求开一个协程处理, 处理完请求后销毁, 让我们优化这段逻辑, 我们很容易联想到 FASTCGI 对比 CGI 的改进. 无非就是预先生成几个 worker 进程, 处理完成后不销毁复用嘛.
那协程也是同理, 为了方便演示, 只开一个协程, 便于理解.
一个请求一个协程:
- <?PHP
- Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
- use function Co\run;
- run(function () {
- $socket = stream_socket_server(
- 'tcp://0.0.0.0:9998',
- $errno,
- $errstr
- );
- if (!$socket) {
- echo "$errstr ($errno)" . PHP_EOL;
- exit(1);
- }
- while (true) {
- $conn = stream_socket_accept($socket);
- if ($conn) {
- go(function() use ($conn) {
- fwrite($conn, "HTTP/1.1 200 OK\r\nContent-Length:11\r\n\r\nHello!world");
- });
- }
- }
- });
协程复用:
- <?PHP
- Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
- use Co\Channel;
- use function Co\run;
- run(function () {
- $channel = new Channel(1);
- go(function() use ($channel) {
- while (($conn = $channel->pop()) !== false) {
- fwrite($conn, "HTTP/1.1 200 OK\r\nContent-Length:11\r\n\r\nHello!world");
- }
- });
- $socket = stream_socket_server(
- 'tcp://0.0.0.0:9999',
- $errno,
- $errstr
- );
- if (!$socket) {
- echo "$errstr ($errno)" . PHP_EOL;
- exit(1);
- }
- while (true) {
- $conn = stream_socket_accept($socket);
- if ($conn) {
- $channel->push($conn);
- }
- }
- });
现实中, 我们不会只开一个协程, 下次有时间再来撸一个协程池, 实现 getWorker 和 putWorker, 支持协程池动态扩容.
感谢 https://github.com/panjf2000/ants 项目的启发.
来源: https://segmentfault.com/a/1190000040550563