Swoole 扩展安装与使用入门
Swoole 概述
Swoole 是面向生产环境的 PHP 异步网络通信引擎。使用纯 C 语言编写(Swoole 4 开始逐渐改为通过 C++ 编写),提供了 PHP 语言的异步多线程服务器、异步 TCP/UDP 网络客户端、异步 MySQL、异步 Redis、数据库连接池、AsyncTask、消息队列、毫秒定时器、异步文件读写、异步 DNS 查询。除了异步 IO 的支持之外,Swoole 为 PHP 多进程的模式设计了多个并发数据结构和 IPC 通信机制,可以大大简化多进程并发编程的工作。其中包括了并发原子计数器,并发 HashTable、Channel、Lock、进程间通信 IPC 等丰富的功能特性。
之前 PHP 一直被诟病的一个原因就是它是同步阻塞式语言,这在 Web 应用这种 IO 密集型的领域对于编写高并发高性能的应用而言,是一个重大阻碍。有了 Swoole 之后,PHP 开发人员可以轻松编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP 以及 WebSocket 服务,从而使得 PHP 语言在异步 IO 和网络通信领域开疆拓土,并且有望在工业级技术方面与 Node.js 和 Go 语言展开角逐。从某种角度上说,Swoole 让 PHP 插上了异步的翅膀,让它飞得更高。
值得一提的是,Swoole 由中国的韩天峰创建并维护,目前已经以独立的开源项目形式进行运作和维护,关于 Swoole 的最新进展可以看下作者韩天峰的这篇文章:Swoole 2019 :化繁为简、破茧成蝶。
关于 Swoole 的官方中文文档可以看这里:https://wiki.swoole.com,本系列教程主要侧重于在 Laravel 框架中集成使用 Swoole 来构建高性能 Laravel 应用。
此外,如果想要更好的掌握 Swoole 的底层原理,需要具备以下知识储备:
多进程/多线程
- 了解 Linux 操作系统进程和线程的概念
- 了解 Linux 进程/线程切换调度的基本知识
- 了解进程间通信的基本知识,如管道、UnixSocket、消息队列、共享内存
SOCKET
- 了解 SOCKET 的基本操作如 accept/connect、send/recv、close、listen、bind
- 了解 SOCKET 的接收缓存区、发送缓存区、阻塞/非阻塞、超时等概念
IO复用
- 了解 select/poll/epoll
- 了解基于 select/epoll 实现的事件循环,Reactor 模型
- 了解可读事件、可写事件
TCP/IP网络协议
- 了解 TCP/IP 协议
- 了解 TCP、UDP 传输协议
调试工具
- 使用 gdb 调试 Linux 程序
- 使用 strace 跟踪进程的系统调用
- 使用 tcpdump 跟踪网络通信过程
- 其他 Linux 系统工具,如 ps、lsof、top、vmstat、netstat、sar、ss 等
注:关于这部分内容你可以网上搜索相应资源进行了解,也可以通过程序员内功修炼系列进行系统学习。
安装启用
Swoole 是 PHP 的一个扩展,可以通过 PHP 扩展的方式进行安装和启用。
本地安装
Laradock
在本地安装的话,以 Laradock 为例,需要在 laradock
目录下的 .env
中将下面两行配置值设置为 true
:
WORKSPACE_INSTALL_SWOOLE=true
PHP_FPM_INSTALL_SWOOLE=true
然后运行 docker-compose build php-fpm workspace
重新构建 Docker 容器,构建完成后重启这两个容器,进入 workspace
容器,运行 php -m
查看 Swoole 是否安装成功,如果扩展列表包含 swoole
则表示安装成功。
Windows/Mac
如果是本地 Windows/Mac 系统上安装的话,直接执行以下命令安装接口:
pecl install swoole
前提是 pecl
命令在系统路径中可用。然后运行 php -m
看到扩展列表包含 swoole
则表明安装成功。
线上安装
如果是在服务器安装的话,以 Ubuntu 系统为例,通过执行下列命令安装即可:
pecl install swoole
然后通过 php -i | grep php.ini
定位 php.ini
文件所在位置,并打开该配置文件,在文件末尾追加如下内容:
[swoole]
extension=swoole.so
保存并退出,在终端运行 php -m
,如果看到扩展里包含 swoole
,说明安装启用成功。
注:以上服务器安装方式也适用于 Homestead 和其他环境 Ubuntu 系统。
测试 Swoole
下面我们基于 Swoole 编写两个简单的功能来测试 Swoole 是否可以正常工作。
HTTP 服务器
首先我们通过 Swoole 编写一个简单的 HTTP 服务器,在测试目录下创建一个 http_server.php
文件,编写文件代码如下:
<?php
// 表明服务器启动后监听本地 9051 端口
$server = new swoole_http_server('127.0.0.1', 9501);
// 服务器启动时返回响应
$server->on("start", function ($server) {
echo "Swoole http server is started at http://127.0.0.1:9501\n";
});
// 向服务器发送请求时返回响应
// 可以获取请求参数,也可以设置响应头和响应内容
$server->on("request", function ($request, $response) {
$response->header("Content-Type", "text/plain");
$response->end("Hello World\n");
});
// 启动 HTTP 服务器
$server->start();
这样,一个最基本的 HTTP 服务器就完成了,其工作原理和工业级的 Apache 和 Nginx 服务器类似,只不过提供的是最简单的服务器监听和响应功能罢了,我们在终端启用这个服务器:
这样,表示服务器已经启动并且在监听请求了,到浏览器中访问 http://127.0.0.1:9501
,即可获取服务器输出响应内容:
TCP 服务器和客户端
接下来,我们通过 Swoole 及其协程特性实现一个简单的 TCP 服务器和客户端,TCP 协议需要双方通过三次握手建立连接后才能进行通信,所以是一种可靠的协议,常见的聊天室应用就是基于 TCP 协议传输内容。我们还是在前面的测试目录下创建一个 tcp_server.php
文件用于编写 TCP 服务端代码:
<?php
namespace Swoole;
// 监听本地 9503 端口,等待客户端请求
$server = new Server("127.0.0.1", 9503);
// 建立连接时输出
$server->on('connect', function ($serv, $fd){
echo "Client:Connect.\n";
});
// 接收消息时返回内容
$server->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, 'Swoole: '.$data);
$serv->close($fd);
});
// 连接关闭时输出
$server->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
// 启动 TCP 服务器
$server->start();
然后在该目录下创建一个 tcp_client.php
文件用于编写 TCP 客户端代码:
<?php
namespace Swoole;
// Swoole4以后通过协程来实现异步通信
go(function () {
$client = new Coroutine\Client(SWOOLE_SOCK_TCP);
// 尝试与指定 TCP 服务端建立连接(IP和端口号需要与服务端保持一致,超时时间为0.5秒)
if ($client->connect("127.0.0.1", 9503, 0.5)) {
// 建立连接后发送内容
$client->send("hello world\n");
// 打印接收到的消息
echo $client->recv();
// 关闭连接
$client->close();
} else {
echo "connect failed.";
}
});
这样,一个最基本的 TCP 服务端和客户端程序就编写完成了,在终端先启动 TCP 服务端:
php tcp_server.php
然后新开启一个终端窗口,启动 TCP 客户端:
输出从 TCP 服务端接收到消息后 TCP 客户端退出,此时服务端也会打印连接建立和断开的日志消息:
客户端退出后,服务端依然处理监听状态,等待下一个请求。
好了,以上就是今天要给大家介绍的 Swoole 安装及入门教程,后面我们将结合 Laravel 应用实例逐步给大家介绍更多的 Swoole 特性及使用方法,以及如何基于 Swoole 构建高性能的 Laravel 应用。
39 Comments
执行docker-compose build php-fpm workspace 报curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused /bin/sh: 1: .: Can't open /home/laradock/.nvm/nvm.sh ERROR: Service 'workspace' failed to build: The command '/bin/sh -c if [ ${INSTALL_NODE} = true ]; then mkdir -p $NVM_DIR && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash && . $NVM_DIR/nvm.sh && nvm install ${NODE_VERSION} && nvm use ${NODE_VERSION} && nvm alias ${NODE_VERSION} && if [ ${NPM_REGISTRY} ]; then npm config set registry ${NPM_REGISTRY} ;fi && if [ ${INSTALL_NPM_GULP} = true ]; then npm install -g gulp ;fi && if [ ${INSTALL_NPM_BOWER} = true ]; then npm install -g bower ;fi && if [ ${INSTALL_NPM_VUE_CLI} = true ]; then npm install -g @vue/cli ;fi && if [ ${INSTALL_NPM_ANGULAR_CLI} = true ]; then npm install -g @angular/cli ;fi && ln -s
npm bin --global
/home/laradock/.node-bin ;fi' returned a non-zero code: 2downloading swoole-4.4.16.tgz ... Starting to download swoole-4.4.16.tgz (1,457,270 bytes) ................................................................................................................done: 557,056 bytes ERROR: unable to unpack /tmp/pear/download/swoole-4.4.16.tgz Service 'php-fpm' failed to build: The command '/bin/sh -c if [ ${INSTALL_SWOOLE} = true ]; then if [ $(php -r "echo PHP_MAJOR_VERSION;") = "5" ]; then pecl install swoole-2.0.10; else if [ $(php -r "echo PHP_MINOR_VERSION;") = "0" ]; then pecl install swoole-2.2.0; else pecl install swoole; fi fi && docker-php-ext-enable swoole && php -m | grep -q 'swoole' ;fi' returned a non-zero code: 1 请问谁知道这种情况是什么问题导致的?php版本是7.3
最后一个案例,是用的异步吧,on的好像不是协程版的httpserver
我使用 laradock v11.0,按照上述的設定。
無論我怎麼重啟,或是 --no-cache,進到 workspace 之後,下 php -m 依然沒有看到 swoole。
什么时候出个Elasticsearch教程
看来用 Elasticsearch 的公司挺多啊
重新build成功了吗 然后restart重启容器
在laradock/docker-compose.yml 文件的workspace的 -ports 添加 "宿主端口号:容器端口号" ports: - "${WORKSPACE_SSH_PORT}:22" - "${WORKSPACE_BROWSERSYNC_HOST_PORT}:3000" - "${WORKSPACE_BROWSERSYNC_UI_HOST_PORT}:3001" - "${WORKSPACE_VUE_CLI_SERVE_HOST_PORT}:8080" - "${WORKSPACE_VUE_CLI_UI_HOST_PORT}:8000" - "${WORKSPACE_ANGULAR_CLI_SERVE_HOST_PORT}:4200" - 9588:9588 - 9501:9501
然后重新 build workspace 容器:
docker-compose build workspace 然后 重启 workspace 我简单粗暴点处理了 docker-compose down docker-compose up -d nginx (默认启动workspace) 浏览器访问就可以了
最后Tcp客户端的那个案例代码,需要更新一下。因为在swoole 4.6的版里运行这个案例,会报错提示:PHP Deprecated: Swoole\Event::rshutdown(): Event::wait() in shutdown function is deprecated in Unknown on line 0
Deprecated: Swoole\Event::rshutdown(): Event::wait() in shutdown function is deprecated in Unknown on line 0
我查了一下,说是go这个写法废弃了。 建议在这个网页里,在增加一个新版本的案例写法。
但是看了一个这篇教程是2019年发布的。估计都没有人维护更新了。