115人参与 • 2024-11-25 • Php
swoole 是一个使用 c++ 语言编写的基于异步事件驱动和协程的并行网络通信引擎,为 php 提供协程、高性能网络编程支持。提供了多种通信协议的网络服务器和客户端模块,可以方便快速的实现 tcp/udp服务、高性能web、websocket服务、物联网、实时通讯、游戏、微服务等,使 php 不再局限于传统的 web 领域。
php的异步、并行、高性能网络通信引擎,使用纯c语言编写,提供了多种通信协议的异步io服务器和客户端。swoole4 支持了完整的 coroutine + channel csp 编程模式 ,可以使用同步风格实现异步程序。
// 预定义常量 swoole_version 当前swoole的版本号,字符串类型,如1.6.0 // swoole_server构造函数参数 swoole_base 使用base模式,业务代码在reactor进程中直接执行 swoole_process 使用进程模式,业务代码在worker进程中执行 // swoole_client构造函数参数 swoole_sock_tcp 创建tcp socket swoole_sock_tcp6 创建tcp ipv6 socket swoole_sock_udp 创建udp socket swoole_sock_udp6 创建udp ipv6 socket swoole_sock_sync 同步客户端 swoole_sock_async 异步客户端 // swoole_lock构造函数参数 swoole_filelock 创建文件锁 swoole_mutex 创建互斥锁 swoole_rwlock 创建读写锁 swoole_spinlock 创建自旋锁 swoole_sem 创建信号量 // ssl加密方法 swoole_sslv3_server_method; swoole_sslv3_method; swoole_sslv3_client_method; swoole_sslv23_method 默认加密方法; swoole_sslv23_server_method; swoole_sslv23_client_method; swoole_tlsv1_method; swoole_tlsv1_server_method; swoole_tlsv1_client_method; swoole_tlsv1_1_method; swoole_tlsv1_1_server_method; swoole_tlsv1_1_client_method; swoole_tlsv1_2_method; swoole_tlsv1_2_server_method; swoole_tlsv1_2_client_method; swoole_dtlsv1_method; swoole_dtlsv1_server_method; swoole_dtlsv1_client_method;
$serv->set(array( // 通过此参数来调节主进程内事件处理线程的数量,以充分利用多核。默认会启用cpu核数相同的数量。一般设置为cpu核数的1-4倍 'reactor_num' => 2, // 设置启动的worker进程数。业务代码是全异步非阻塞的,这里设置为cpu的1-4倍最合理 // 业务代码为同步阻塞,需要根据请求响应时间和系统负载来调整 'worker_num' => 2, // 设置worker进程的最大任务数,默认为0,一个worker进程在处理完超过此数值的任务后将自动退出,进程退出后会释放所有内存和资源。 'max_request' => 1000, // 服务器程序,最大允许的连接数, 此参数用来设置server最大允许维持多少个tcp连接。超过此数量后,新进入的连接将被拒绝 'max_connection' => 10000, // 配置task进程的数量,配置此参数后将会启用task功能。所以server务必要注册ontask 'task_worker_num' => 2, // 设置task进程与worker进程之间通信的方式。1使用unix socket通信,默认模式, 2使用消息队列通信, 3使用消息队列通信,并设置为争抢模式 'task_ipc_mode' => 1 // 设置task进程的最大任务数。一个task进程在处理完超过此数值的任务后将自动退出。 'task_max_request' => 0, // 设置task的数据临时目录,在swoole_server中,如果投递的数据超过8192字节,将启用临时文件来保存数据 'task_tmpdir' => '/tmp', // 数据包分发策略默认为2。1轮循模式,2固定模式,3抢占模式,4ip分配,5uid分配 'dispatch_mode' => 2, // 设置dispatch函数,swoole底层了内置了5种dispatch_mode,如果仍然无法满足需求。 // 可以使用编写c++函数或php函数,实现dispatch逻辑。使用方法: 'dispatch_func' => 'my_dispatch_function', // 设置消息队列的key,仅在task_ipc_mode = 2/3时使用。 // 设置的key仅作为task任务队列的key,此参数的默认值为ftok($php_script_file, 1) 'message_queue_key' => ftok(sys_root . 'queue.msg', 1), // 设置守护进程模式 'daemonize' => 1, // listen队列长度,如backlog => 128,此参数将决定最多同时有多少个等待accept的连接 'backlog' => 128, // 指定swoole错误日志文件。在swoole运行期发生的异常信息会记录到这个文件中。默认会打印到屏幕 'log_file' => '/data/logs/swoole.log', // 设置swoole_server错误日志打印的等级,范围是0-5。低于log_level设置的日志信息不会抛出 'log_level' => 1, // 启用心跳检测,此选项表示每隔多久轮循一次,单位为秒 'heartbeat_check_interval' => 10, // 与heartbeat_check_interval配合使用。表示连接最大允许空闲的时间 'heartbeat_idle_time' => 20, // 打开eof检测,此选项将检测客户端连接发来的数据,当数据包结尾是指定的字符串时才会投递给worker进程 // 否则会一直拼接数据包,直到超过缓存区或者超时才会中止。当出错时底层会认为是恶意连接,丢弃数据并强制关闭连接 'open_eof_check' => true, // 启用eof自动分包。当设置open_eof_check后,底层检测数据是否以特定的字符串结尾来进行数据缓冲 'open_eof_split' => true, // 与 open_eof_check 或者 open_eof_split 配合使用,设置eof字符串。 'package_eof' => "\r\r\n", // 打开包长检测特性。包长检测提供了固定包头+包体这种格式协议的解析。 // 启用后,可以保证worker进程onreceive每次都会收到一个完整的数据包。 'open_length_check' => true, // 长度值的类型,接受一个字符参数,与php的 pack 函数一致。 'package_length_type' => 'n', // 设置长度解析函数,支持c++或php的2种类型的函数。长度函数必须返回一个整数 'package_length_func' => 'package_length_func_name' // 设置最大数据包尺寸,单位为字节 'package_max_length' => 2000000, // 启用cpu亲和性设置 'open_cpu_affinity' => 1, // cpu_affinity_ignore 设置将此cpu空出,专门用于处理网络中断 'cpu_affinity_ignore' => [0,1], // 启用open_tcp_nodelay,开启后tcp连接发送数据时会关闭nagle合并算法,立即发往客户端连接 'open_tcp_nodelay' => 1, // 启用tcp_defer_accept特性,可以设置为一个数值,表示当一个tcp连接有数据发送时才触发accept 'tcp_defer_accept' => 5 // 设置ssl隧道加密,设置值为一个文件名字符串,制定cert证书和key私钥的路径 'ssl_cert_file' => __dir__.'/config/ssl.crt', 'ssl_key_file' => __dir__.'/config/ssl.key', // 设置openssl隧道加密的算法。server与client使用的算法必须一致,否则ssl/tls握手会失败,连接会被切断 'ssl_method' => swoole_sslv3_client_method, // 启用ssl后,设置ssl_ciphers来改变openssl默认的加密算法 'ssl_ciphers' => 'all:!adh:!export56:rc4+rsa:+high:+medium:+low:+sslv2:+exp', // 设置worker/task子进程的所属用户 'user' => 'swoole', // 设置worker/task子进程的进程用户组 'group' => 'www-data', // 重定向worker进程的文件系统根目录 'chroot' => '/data/server/', // 在server启动时自动将master进程的pid写入到文件,在server关闭时自动删除pid文件 'pid_file' => __dir__.'/server.pid', // 调整管道通信的内存缓存区长度。swoole使用unix socket实现进程间通信。 'pipe_buffer_size' => 32 * 1024 *1024, // 配置发送输出缓存区内存尺寸 'buffer_output_size' => 32 * 1024 *1024 // 配置客户端连接的缓存区长度 'socket_buffer_size' => 128 * 1024 *1024 // swoole在配置dispatch_mode=1或3后,因为系统无法保证onconnect/onreceive/onclose的顺序,默认关闭了onconnect/onclose事件。 // 如果应用程序需要onconnect/onclose事件,并且能接受顺序问题可能带来的安全风险, // 可以通过设置enable_unsafe_event为true,启用onconnect/onclose事件 'enable_unsafe_event' => true, // swoole在配置dispatch_mode=1或3后,系统无法保证onconnect/onreceive/onclose的顺序,因此可能会有一些请求数据在连接关闭后, // 才能到达worker进程。discard_timeout_request配置默认为true,表示如果worker进程收到了已关闭连接的数据请求,将自动丢弃。 // discard_timeout_request如果设置为false,表示无论连接是否关闭worker进程都会处理数据请求。 'discard_timeout_request' => true, // 设置端口重用 'enable_reuse_port' => true, // 设置此选项为true后,accept客户端连接后将不会自动加入eventloop,仅触发onconnect回调。 // worker进程可以调用$serv->confirm($fd)对连接进行确认,此时才会将fd加入eventloop开始进行数据收发, // 也可以调用$serv->close($fd)关闭此连接。 'enable_delay_receive' => true, // 启用http协议处理 'open_http_protocol' => true, // 启用http2协议解析,需要依赖--enable-http2编译选项。默认为false 'open_http2_protocol' => true, // 启用websocket协议处理,swoole\websocket\server会自动启用此选项 'open_websocket_protocol' => true, // 启用mqtt协议处理,启用后会解析mqtt包头,worker进程onreceive每次会返回一个完整的mqtt数据包 'open_mqtt_protocol' => true, // 设置异步重启开关 'reload_async' => true, // 开启tcp快速握手特性。此项特性,可以提升tcp短连接的响应速度,在客户端完成握手的第三步,发送syn包时携带数据 'tcp_fastopen' => true // 开启请求慢日志。启用后manager进程会设置一个时钟信号,定时侦测所有task和worker进程, // 一旦进程阻塞导致请求超过规定的时间,将自动打印进程的php函数调用栈 'request_slowlog_file' => '/tmp/trace.log', // enable_coroutine参数,默认为true,通过设置为false可关闭内置协程 'enable_coroutine' => false // 设置当前工作进程最大协程数量,超过max_coroutine底层将无法创建新的协程,底层会抛出错误,并直接关闭连接 'max_coroutine' => 3000, ));
// 创建一个异步server对象。 $serv = new swoole_server('0.0.0.0', '9501', $mode = swoole_process, $sock_type = swoole_sock_tcp); // swoole_server->set函数用于设置swoole_server运行时的各项参数。 // 服务器启动后通过$serv->setting来访问set函数设置的参数数组。 $serv->set(array( 'reactor_num' => 2, 'worker_num' => 4, 'backlog' => 128, 'max_request' => 50, 'dispatch_mode' => 1, )); // 注册server的事件回调函数。 $serv->on('connect', function ($serv, $fd){ echo "client:connect.\n"; }); // 增加监听的端口。业务代码中可以通过调用swoole_server::connection_info来获取某个连接来自于哪个端口。 $serv->addlistener("127.0.0.1", 9502, swoole_sock_tcp); // 监听一个新的server端口,此方法是addlistener的别名 $serv->listen("127.0.0.1", 9503, swoole_sock_tcp); // 添加一个用户自定义的工作进程。此函数通常用于创建一个特殊的工作进程,用于监控、上报或者其他特殊的任务。 $process = new swoole_process(function($process) use ($server) { while (true) { $msg = $process->read(); foreach($server->connections as $conn) { $server->send($conn, $msg); } } }); $server->addprocess($process); // 启动server,监听所有tcp/udp端口 $serv->start(); // 重启所有worker进程。$only_reload_taskworkrer 是否仅重启task进程 $serv->reload($only_reload_taskworkrer = false); // 使当前worker进程停止运行,并立即触发onworkerstop回调函数。 swoole_server->stop(int $worker_id = -1, bool $waitevent = false); // 此函数可以用在worker进程内。向主进程发送sigterm也可以实现关闭服务器。 $serv->shutdown(); // tick定时器,可以自定义回调函数。此函数是swoole_timer_tick的别名。 $serv->tick(1000, function ($id) { var_dump($id); }); // 在指定的时间后执行函数,swoole_server::after函数是一个一次性定时器,执行完成后就会销毁 $serv->after(2000, function(){ echo "timeout: ".microtime(true)."\n"; }); // 延后执行一个php函数。swoole底层会在eventloop循环完成后执行此函数。 // 此函数的目的是为了让一些php代码延后执行,程序优先处理io事件。 $server->defer(function() use ($db) { $db->close(); }); // 清除tick/after定时器,此函数是 swoole_timer_clear 的别名。 $timer_id = $server->tick(1000, function ($id) use ($server) { $server->cleartimer($id); }); // 关闭客户端连接,操作成功返回true,失败返回false. $serv->close($fd); // 向客户端发送数据 $data,发送的数据,tcp协议最大不得超过2m,可修改 buffer_output_size 改变允许发送的最大包长度 // udp协议不得超过65507,udp包头占8字节, ip包头占20字节,65535-28 = 65507 $serv->send($fd, 'swoole: '.$data); // 发送文件到tcp客户端连接 $serv->sendfile($fd, __dir__.'/test.jpg'); // 向任意的客户端ip:port发送udp数据包 $serv->sendto("127.0.0.1", 9999, "hello world"); // 阻塞地向客户端发送数据 server->sendwait($fd, "hello world"); // 此函数可以向任意worker进程或者task进程发送消息。在非主进程和管理进程中可调用。收到消息的进程会触发onpipemessage事件 $serv->sendmessage("hello task process", $worker_id); // 检测fd对应的连接是否存在,$fd对应的tcp连接存在返回true,不存在返回false $serv->exist($fd) // 停止接收数据。调用此函数后会将连接从eventloop中移除,不再接收客户端数据 $serv->pause($fd) // 恢复数据接收。与pause方法成对使用,调用此函数后会将连接重新加入到eventloop中,继续接收客户端数据 $serv->resume(int $fd); // swoole_server->getclientinfo函数用来获取连接的信息,别名是swoole_server->connection_info $fdinfo = $serv->connection_info($fd); // 用来遍历当前server所有的客户端连接,方法是基于共享内存的,不存在iowait // 推荐使用 swoole_server::$connections 迭代器来遍历连接,getclientlist的别名是connection_list $conn_list = $serv->getclientlist($start_fd, 10); // 将连接绑定一个用户定义的uid,可以设置dispatch_mode=5设置以此值进行hash固定分配。 // 可以保证某一个uid的连接全部会分配到同一个worker进程。 $serv->bind($fd, $uid) // 得到当前server的活动tcp连接数,启动时间,accpet/close的总次数等信息。 $serv_stats = $serv->stats(); // 投递一个异步任务到task_worker池中。此函数是非阻塞的,执行完毕会立即返回。worker进程可以继续处理新的请求。 // 使用task功能,必须先设置 task_worker_num,并且必须设置server的ontask和onfinish事件回调函数 $task_id = $serv->task("some data"); // taskwait与task方法作用相同,用于投递一个异步的任务到task进程池去执行。 // 与task不同的是taskwait是同步等待的,直到任务完成或者超时返回。 $serv->taskwait(['type' => 'array', 'value' => $data]); // 并发执行多个task,$tasks 必须为数字索引数组,不支持关联索引数组 $tasks[] = mt_rand(1000, 9999); // 任务1 $tasks[] = mt_rand(1000, 9999); // 任务2 var_dump($tasks); // 等待所有task结果返回,超时为10s $results = $serv->taskwaitmulti($tasks, 10.0); // 并发执行task并进行协程调度 $result = $serv->taskco($tasks, 0.5); // 此函数用于在task进程中通知worker进程,投递的任务已完成。此函数可以传递结果数据给worker进程。 $serv->finish("response"); // 检测服务器所有连接,并找出已经超过约定时间的连接。 // 如果指定if_close_connection,则自动关闭超时的连接。未指定仅返回连接的fd数组。 $closefdarr = $serv->heartbeat(); // 获取最近一次操作错误的错误码。业务代码中可以根据错误码类型执行不同的逻辑。 $errcode = $serv->getlasterror(); // 调用此方法可以得到底层的socket句柄,返回的对象为sockets资源句柄。 // 依赖php的sockets扩展,并且编译swoole时需要开启--enable-sockets选项 $socket = $serv->getsocket(); // 设置客户端连接为保护状态,不被心跳线程切断。 $serv->protect(int $fd, bool $value = 1); // 确认连接,与enable_delay_receive或wait_for_bind配合使用。当客户端建立连接后,并不监听可读事件。 // 仅触发onconnect事件回调在onconnect回调中执行confirm确认连接,这时服务器才会监听可读事件,接收来自客户端连接的数据。 $serv->confirm(int $fd);
// swoole_server::set()函数所设置的参数会保存到swoole_server::$setting属性上。在回调函数中可以访问运行参数的值。 echo $serv->setting['worker_num']; // 返回当前服务器主进程的pid。 int $serv->master_pid; // 返回当前服务器管理进程的pid。 int $serv->manager_pid; // 得到当前worker进程的编号,包括task进程。worker进程编号范围是[0, worker_num] // task进程编号范围是[worker_num, worker_num + task_worker_num] int $serv->worker_id; // 得到当前worker进程的操作系统进程id。与posix_getpid()的返回值相同。 int $serv->worker_pid; // 布尔类型,true表示当前的进程是task工作进程,false表示当前的进程是worker进程 bool $serv->taskworker; // tcp连接迭代器,可以使用foreach遍历服务器当前所有的连接, // 此属性的功能与swoole_server->connnection_list是一致的,但是更加友好。遍历的元素为单个连接的fd。 // 监听端口数组,如果服务器监听了多个端口可以遍历swoole_server::$ports得到所有swoole\server\port对象。 // 其中swoole_server::$ports[0]为构造方法所设置的主服务器端口。 $ports = swoole_server::$ports; $ports[0]->set($settings); $ports[1]->on("receive", function(){});
// server启动在主进程的主线程回调此函数 $serv->on('start', function(swoole\server $server){}); // 此事件在server正常结束时发生 $serv->on('shutdown', function(swoole\server $server){}); // 此事件在worker进程/task进程启动时发生 $serv->on('workerstart', function(swoole\server $server, int $worker_id){}); // 此事件在worker进程终止时发生 $serv->on('workerstop', function(swoole\server $server, int $worker_id){}); // 仅在开启reload_async特性后有效会先创建新的worker进程处理新请求,旧的worker进程自行退出。 $serv->on('workerexit', function(swoole\server $server, int $worker_id){}); // 有新的连接进入时,在worker进程中回调 $serv->on('connect', function(swoole\server $server, int $fd, int $reactorid){}); // 接收到数据时回调此函数,发生在worker进程中 $serv->on('receive', function(swoole\server $server, int $fd, int $reactor_id, string $data){}); // 接收到udp数据包时回调此函数,发生在worker进程中 $serv->on('packet', function(swoole\server $server, string $data, array $client_info){}); // tcp客户端连接关闭后,在worker进程中回调此函数 $serv->on('close', function(swoole\server $server, int $fd, int $reactorid){}); // 当缓存区达到最高水位时触发此事件。 $serv->on('bufferfull', function(swoole\server $serv, int $fd){}); // 当缓存区低于最低水位线时触发此事件 $serv->on('bufferempty', function(swoole\server $serv, int $fd){}); // 在task_worker进程内被调用。worker进程可以使用swoole_server_task函数向task_worker进程投递新的任务。 // 当前的task进程在调用ontask回调函数时会将进程状态切换为忙碌,这时将不再接收新的task, // 当ontask函数返回时会将进程状态切换为空闲然后继续接收新的task。 $serv->on('task', function(swoole\server $serv, int $task_id, int $src_worker_id, mixed $data){}); // 当worker进程投递的任务在task_worker中完成时, // task进程会通过swoole_server->finish()方法将任务处理的结果发送给worker进程 $serv->on('finish', function(swoole\server $serv, int $task_id, string $data){}); // 当工作进程收到由 sendmessage 发送的管道消息时会触发onpipemessage事件。worker/task进程都可能会触发onpipemessage事件 $serv->on('pipemessage', function(swoole\server $server, int $src_worker_id, mixed $message){}); // 当worker/task_worker进程发生异常后会在manager进程内回调此函数 $serv->on('workererror', function(swoole\server $serv, int $worker_id, int $worker_pid, int $exit_code, int $signal){}); // 当管理进程启动时调用它 $serv->on('managerstart', function(swoole\server $serv){}); // 当管理进程结束时调用它 $serv->on('managerstop', function(swoole\server $serv){});
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论