在 ServBay 中搭建和运行 Workerman 应用
概述
本篇文档旨在指导 ServBay 用户如何在本地 macOS 开发环境中,利用 ServBay 集成的 PHP 环境和 Composer,快速搭建并运行基于 Workerman 的高性能异步网络应用。Workerman 是一个强大的 PHP 库,适用于构建各种需要高并发处理的网络服务,如 Web 服务器、实时通信服务器、游戏服务器等。ServBay 提供了一个开箱即用的开发平台,极大地简化了 Workerman 的环境配置过程。
什么是 Workerman?
Workerman 是一个完全由 PHP 编写的开源高性能异步网络通信框架。它基于 EventLoop 事件循环机制,实现了异步非阻塞 I/O,能够有效处理大量并发连接。与传统的 PHP Web 开发模式(如 Apache/Nginx + PHP-FPM)不同,Workerman 应用通常以常驻内存的方式运行,监听特定端口,直接处理网络连接和数据,从而避免了传统模式下请求处理完成后进程销毁带来的开销,显著提升了性能和吞吐量。
利用 Workerman,开发者可以轻松构建:
- 高性能的 HTTP 服务器,甚至可以替代 Apache/Nginx 处理简单的静态或动态请求。
- 实时 WebSocket 服务器,用于构建聊天室、实时数据推送等应用。
- 各种自定义协议的 TCP/UDP 服务器。
- 命令行工具、计划任务、微服务等。
Workerman 的核心特性与优势
- 高性能: 核心基于事件驱动和异步非阻塞 I/O,能够处理海量并发连接,提供卓越的性能表现。
- 多协议支持: 内置支持 HTTP、WebSocket、TCP、UDP 等多种主流网络协议,并提供了灵活的接口允许开发者实现自定义协议。
- 易于使用: 提供简洁直观的 API,降低了异步网络编程的复杂性,PHP 开发者可以快速上手。
- 灵活扩展: 支持多进程模型,便于利用多核 CPU 进行水平扩展和负载均衡。可以方便地集成 Composer 包和现有的 PHP 库。
- PHP 生态融合: 作为 PHP 库,与 PHP 现有生态系统紧密结合,可以无缝使用 Composer 管理依赖。
- 守护进程模式: 支持以守护进程(Daemon)方式在后台稳定运行,适合生产环境部署,保证服务的持续可用性。
Workerman 为 PHP 开发者打开了构建高性能、实时、高并发网络应用的大门。
使用 ServBay 搭建 Workerman 开发环境
ServBay 是一款专为 Web 开发者量身打造的本地开发环境工具,集成了 PHP、Node.js、Python、Go、Java 等多种主流编程语言运行时,以及 Caddy、Nginx、Apache、MySQL、PostgreSQL、MongoDB、Redis、Memcached 等常用数据库和服务器软件。ServBay 的核心优势在于其“开箱即用”的特性,特别是它内置并配置好了 Composer 环境,这为在 ServBay 中搭建和运行 Workerman 项目提供了极大的便利。
本指南将通过创建几个基础示例,演示如何在 ServBay 环境中快速搭建并运行 Workerman 应用,包括一个简单的 HTTP 服务器、一个 WebSocket 服务器和一个 TCP 服务器。
TIP
为了方便管理和统一规范,ServBay 建议将所有本地网站项目文件存放在 /Applications/ServBay/www
目录下。本文档中的所有项目路径示例均将基于此目录。
前提条件
在开始之前,请确保满足以下条件:
- ServBay 已安装并正常运行: 访问 ServBay 官方网站 下载并安装最新版本的 ServBay。
- ServBay 中的 PHP 已启用: 在 ServBay 控制面板中,确保你计划使用的 PHP 版本已启用。Workerman 需要 PHP 5.4 或更高版本,推荐使用 PHP 7.x 或 8.x 版本以获得最佳性能。
- 具备基础的 PHP 编程和命令行操作知识: 你需要了解基本的 PHP 语法和如何在终端中使用命令行工具。
安装 Workerman
1. 确保 Composer 可用
ServBay 已经内置了 Composer,无需单独安装。请确保你的 ServBay 环境已启动,并且你计划使用的 PHP 版本已启用。ServBay 会自动配置好对应 PHP 版本的 Composer 环境。你可以通过 ServBay 的终端或者外部终端(如果 ServBay 已将 PHP 和 Composer 添加到系统 PATH)进入 ServBay 的 PHP 环境来使用 Composer。
打开终端,输入以下命令验证 Composer 是否可用:
composer -v
如果 Composer 正确安装并配置在 ServBay 的 PHP 环境中,你将看到 Composer 的版本信息。如果命令未找到,请检查 ServBay 是否正在运行以及 PHP 版本是否已启用。
2. 创建项目目录
导航到 ServBay 推荐的网站根目录,并创建一个新的项目目录,然后进入该目录:
cd /Applications/ServBay/www
mkdir servbay-workerman-demo
cd servbay-workerman-demo
2
3
这里我们创建了一个名为 servbay-workerman-demo
的目录来存放 Workerman 项目文件。
3. 使用 Composer 安装 Workerman
在项目目录 (/Applications/ServBay/www/servbay-workerman-demo
) 中,使用 Composer 安装 Workerman 库。这是推荐的安装方式,Composer 会自动处理依赖:
composer require workerman/workerman
Composer 将会自动下载 Workerman 及其依赖到当前目录下的 vendor
目录中。
编写 Workerman HTTP 服务器代码
HTTP 服务器是 Workerman 最常见的应用场景之一,可以用于构建高性能的 Web 应用或 API 服务。
在项目目录下创建一个名为 http_server.php
(或者你喜欢的其他名称,例如 server.php
)的文件,并添加以下 PHP 代码:
<?php
// 引入 Composer 的自动加载文件,以便使用 Workerman 类
require __DIR__ . '/vendor/autoload.php';
// 导入 Workerman 的 Worker 类
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
// 创建一个 Worker 实例,指定监听的协议和地址
// 'http://0.0.0.0:8080' 表示创建一个 HTTP 服务器,监听所有网络接口(0.0.0.0)的 8080 端口
// 0.0.0.0 允许从本机或局域网内的其他设备访问;8080 是监听的端口号。
$http_worker = new Worker('http://0.0.0.0:8080');
// 设置 Worker 进程的数量
// 这里设置为 4,表示启动 4 个独立的 PHP 进程来处理请求,可以根据 CPU 核心数进行调整
$http_worker->count = 4;
// 定义当接收到客户端消息(HTTP 请求)时的处理逻辑
// $connection 是当前的连接对象,通过它可以向客户端发送响应
// $request 是当前的请求对象,包含了请求的详细信息(URL, Headers, Body 等)
$http_worker->onMessage = function(TcpConnection $connection, Request $request) {
// 向客户端发送一个简单的字符串作为 HTTP 响应
// Workerman 的 HTTP 协议会自动处理 HTTP 响应头等细节
$connection->send(new Response(200, [], 'Hello ServBay Workerman HTTP Server!'));
};
// 运行所有的 Worker 实例
// 这是 Workerman 的主循环,启动后 Worker 进程开始监听端口并处理事件
Worker::runAll();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
代码解释:
require __DIR__ . '/vendor/autoload.php';
: 载入 Composer 生成的自动加载文件,使得 Workerman 的类(包括Worker
,Request
,Response
等)可以被使用。use Workerman\...;
: 引入需要的类。new Worker('http://0.0.0.0:8080')
: 创建一个 Workerman 实例。参数指定了监听的协议(http
)和地址(0.0.0.0:8080
)。$http_worker->count = 4;
: 设置 Workerman 启动的进程数量。增加进程数可以利用多核 CPU,提高并发处理能力。$http_worker->onMessage = function(TcpConnection $connection, Request $request) { ... };
: 定义了当 Workerman 接收到完整的 HTTP 请求时执行的回调函数。$connection
对象用于发送数据回客户端,$request
对象包含客户端发送的请求信息。Response
类用于构建标准的 HTTP 响应。Worker::runAll();
: 启动 Workerman 的事件循环,使所有定义的 Worker 实例开始监听并处理连接。
运行 Workerman HTTP 服务器
在项目目录 (/Applications/ServBay/www/servbay-workerman-demo
) 中,打开终端,运行以下命令启动 HTTP 服务器:
php http_server.php start
运行模式说明:
- 前台模式 (Foreground): 执行
php http_server.php start
命令后,Workerman 会在前台运行,终端会输出运行信息和日志。你可以通过Ctrl+C
停止服务器。这种模式适合开发和调试。 - 守护进程模式 (Daemon): 在生产环境中,通常需要让 Workerman 在后台作为守护进程稳定运行。可以使用
-d
参数:bashWorkerman 将在后台运行,并将输出重定向到日志文件(默认在 Workerman 目录下或指定路径)。php http_server.php start -d
1
进程管理:
Workerman 提供了一系列方便的进程管理命令:
- 启动:
php http_server.php start
(前台) 或php http_server.php start -d
(后台) - 停止:
php http_server.php stop
(会等待当前请求处理完毕后优雅退出) - 重启:
php http_server.php restart
(先停止再启动) - 平滑重启 (Reload):
php http_server.php reload
(通常用于代码更新,会逐个重启子进程,不中断服务,但需要注意onWorkerStart
等生命周期函数的使用) - 查看状态:
php http_server.php status
(查看 Workerman 进程的运行状态、内存占用、连接数等信息)
启动服务器后,打开浏览器,访问 http://localhost:8080
或 http://127.0.0.1:8080
。您应该会看到页面输出 Hello ServBay Workerman HTTP Server!
。
使用 Workerman 创建 WebSocket 服务器
WebSocket 协议允许客户端和服务器之间建立持久的双向通信连接,非常适合构建实时应用,如在线聊天、股票行情、游戏等。Workerman 对 WebSocket 有良好的支持。
创建 WebSocket 服务器代码
在项目目录下创建一个
websocket_server.php
文件,并添加以下代码:php<?php require __DIR__ . '/vendor/autoload.php'; use Workerman\Worker; use Workerman\Connection\TcpConnection; // 创建一个 WebSocket 服务器实例,监听 8081 端口 // 'websocket://0.0.0.0:8081' 表示创建一个 WebSocket 服务器 // Workerman 会自动处理 WebSocket 的握手过程 $ws_worker = new Worker('websocket://0.0.0.0:8081'); // 启动 4 个进程来处理连接 $ws_worker->count = 4; // 定义连接建立时的处理逻辑 // 当有新的客户端连接到服务器时触发 $ws_worker->onConnect = function(TcpConnection $connection) { echo "New WebSocket connection from " . $connection->getRemoteIp() . "\n"; }; // 定义消息接收时的处理逻辑 // 当服务器收到客户端发送的 WebSocket 消息时触发 // $data 是从客户端接收到的消息内容(已解码) $ws_worker->onMessage = function(TcpConnection $connection, $data) { echo "Received message: " . $data . "\n"; // 向客户端回显收到的消息 // $connection->send() 会自动编码为 WebSocket 帧发送 $connection->send('ServBay Workerman received: ' . $data); }; // 定义连接关闭时的处理逻辑 // 当客户端断开连接时触发 $ws_worker->onClose = function(TcpConnection $connection) { echo "WebSocket Connection closed\n"; }; // 定义发生错误时的处理逻辑 (可选) $ws_worker->onError = function(TcpConnection $connection, $code, $msg) { echo "Error: $code - $msg\n"; }; // 运行所有的 Worker 实例 Worker::runAll();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44运行 WebSocket 服务器
在项目目录下运行以下命令启动 WebSocket 服务器:
bashphp websocket_server.php start
1您同样可以使用
-d
参数在后台运行。启动后,您可以使用 WebSocket 客户端工具连接到ws://localhost:8081
。例如,您可以在浏览器开发者工具的 Console 中使用 JavaScript 进行测试:
javascriptvar ws = new WebSocket("ws://localhost:8081"); ws.onopen = function(event) { console.log("WebSocket connection opened"); ws.send("Hello from Browser!"); // 发送消息 }; ws.onmessage = function(event) { console.log("Message from server:", event.data); // 接收消息 }; ws.onclose = function(event) { if (event.wasClean) { console.log("WebSocket connection closed cleanly, code=" + event.code + " reason=" + event.reason); } else { console.error("WebSocket connection died"); } }; ws.onerror = function(error) { console.error("WebSocket error:", error); }; // 关闭连接 (可选) // ws.close();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25连接成功后,您将看到终端输出连接信息,发送消息后,终端会显示收到的消息,并且浏览器会收到服务器回显的消息。
使用 Workerman 创建 TCP 服务器
Workerman 也可以用于创建通用的 TCP 服务器,处理各种基于 TCP 协议的应用层数据。这对于构建游戏后端、物联网平台、自定义通信服务等非常有用。
创建 TCP 服务器代码
在项目目录下创建一个
tcp_server.php
文件,并添加以下代码:php<?php require __DIR__ . '/vendor/autoload.php'; use Workerman\Worker; use Workerman\Connection\TcpConnection; // 创建一个 TCP 服务器实例,监听 8082 端口 // 'tcp://0.0.0.0:8082' 表示创建一个 TCP 服务器 // Workerman 默认使用 Text 协议(行结束符 '\n'),也可以指定其他协议或自定义协议 $tcp_worker = new Worker('tcp://0.0.0.0:8082'); // 启动 4 个进程来处理连接 $tcp_worker->count = 4; // 定义连接建立时的处理逻辑 $tcp_worker->onConnect = function(TcpConnection $connection) { echo "New TCP connection from " . $connection->getRemoteIp() . "\n"; // 连接建立时发送欢迎消息 $connection->send("Welcome to ServBay Workerman TCP Server!\n"); }; // 定义消息接收时的处理逻辑 // $data 是从客户端接收到的原始 TCP 数据(根据协议解析后的数据) $tcp_worker->onMessage = function(TcpConnection $connection, $data) { echo "Received data: " . $data; // 向客户端回显收到的数据 $connection->send('ServBay Workerman received: ' . $data); }; // 定义连接关闭时的处理逻辑 $tcp_worker->onClose = function(TcpConnection $connection) { echo "TCP Connection closed\n"; }; // 运行所有的 Worker 实例 Worker::runAll();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36运行 TCP 服务器
在项目目录下运行以下命令启动 TCP 服务器:
bashphp tcp_server.php start
1您同样可以使用
-d
参数在后台运行。启动后,您可以使用 TCP 客户端工具连接到localhost:8082
。例如,在 macOS/Linux 系统中,打开另一个终端窗口,输入
telnet
或nc
命令:bash# 使用 telnet telnet localhost 8082 # 或者使用 nc (netcat) nc localhost 8082
1
2
3
4
5连接成功后,您将看到服务器发送的欢迎消息。输入任意文本(以回车结束,因为默认使用了 Text 协议),服务器将会回显您发送的消息。
注意事项
- 端口占用: 确保 Workerman 监听的端口(示例中的 8080, 8081, 8082)没有被 macOS 系统或 ServBay 中运行的其他程序占用。如果端口冲突,Workerman 将无法启动并报错。你可以通过
lsof -i :端口号
命令来检查端口占用情况。 - 防火墙: macOS 的内置防火墙可能会阻止外部设备访问这些端口。在本地开发环境中,通常不是问题,但如果需要从局域网内的其他设备访问 Workerman 服务,请检查并配置 macOS 的防火墙设置。
- 与 ServBay Web 服务器的关系: Workerman 运行在自己监听的端口上,与 ServBay 中运行的 Caddy 或 Nginx 是独立的进程和服务。Workerman 应用通常直接处理连接,而不是通过 Caddy/Nginx 代理(除非你专门配置反向代理)。Workerman 更适合处理需要长时间连接或高并发异步处理的场景(如 WebSocket),而 ServBay 集成的 Caddy/Nginx 主要用于处理传统的、短连接的 HTTP 请求。
- PHP 版本: 确保 ServBay 中用于运行 Workerman 的 PHP 版本符合 Workerman 的最低要求。ServBay 支持并预装了多个 PHP 版本,你可以根据项目需求在 ServBay 控制面板中选择并启用合适的版本。
- 扩展依赖: Workerman 依赖于一些 PHP 扩展以获得最佳性能和功能,例如
event
扩展(如果安装且启用,Workerman 会优先使用,提供更高的性能)、posix
、pcntl
(用于多进程模式)。ServBay 默认启用了大部分常用扩展,但如果遇到特定问题,请检查 ServBay 控制面板中对应 PHP 版本的扩展是否已启用。 - 日志: 在守护进程模式下,Workerman 的输出会重定向到日志文件。请定期检查日志文件以了解应用运行状态和潜在错误。
常见问题解答 (FAQ)
- Q: 如何停止 Workerman 服务器?
- A: 如果服务器在前台运行(使用
start
命令),直接在终端中按Ctrl+C
即可停止。如果服务器在后台作为守护进程运行(使用start -d
命令),则需要在项目目录下使用命令php your_server_file.php stop
来停止。
- A: 如果服务器在前台运行(使用
- Q: 为什么 Workerman 服务器无法启动?
- A: 最常见的原因是监听的端口已被占用。请检查终端输出的错误信息,通常会提示端口被占用。你可以尝试更换一个未被占用的端口,或者停止占用该端口的其他程序。使用
lsof -i :端口号
命令可以查看哪个进程占用了特定端口。
- A: 最常见的原因是监听的端口已被占用。请检查终端输出的错误信息,通常会提示端口被占用。你可以尝试更换一个未被占用的端口,或者停止占用该端口的其他程序。使用
- Q: ServBay 的 Caddy/Nginx 和 Workerman 有什么区别?我应该用哪个?
- A: ServBay 的 Caddy/Nginx 是传统的 Web 服务器,主要用于处理标准的 HTTP/HTTPS 请求,通常与 PHP-FPM 配合工作,每个请求处理完毕后 PHP 进程可能会退出。Workerman 是一个 PHP 异步网络框架,可以自己作为 HTTP 服务器,也可以处理 WebSocket、TCP 等其他协议,它以常驻内存的方式运行,更适合处理高并发、长连接或实时通信的应用。选择哪个取决于你的应用需求:传统网站或 RESTful API 通常使用 Caddy/Nginx;实时聊天、游戏后端、物联网服务等更适合使用 Workerman。当然,你也可以结合使用,例如用 Caddy/Nginx 作为反向代理转发特定请求到 Workerman。
- Q: 我可以在 ServBay 中同时运行多个 Workerman 应用吗?
- A: 可以。每个 Workerman 应用都需要在一个独立的 PHP 进程中运行,并且监听不同的端口。只需为每个应用编写单独的启动脚本,并在不同的终端窗口中运行
php your_app_server.php start
命令(或在后台运行)即可。确保它们监听的端口不冲突。
- A: 可以。每个 Workerman 应用都需要在一个独立的 PHP 进程中运行,并且监听不同的端口。只需为每个应用编写单独的启动脚本,并在不同的终端窗口中运行
总结
通过本指南,你已经了解了如何在 ServBay 这一高效的本地开发环境中,快速搭建和运行 Workerman 项目。Workerman 凭借其高性能和异步特性,为 PHP 开发者提供了构建下一代网络应用的强大能力。结合 ServBay 提供的开箱即用的 Composer 和 PHP 环境,你可以极大地提高开发效率,专注于 Workerman 应用的业务逻辑实现,而无需花费大量时间在环境配置上。无论是构建高性能的 Web 服务,还是开发实时交互的 WebSocket 应用,ServBay 都是你使用 Workerman 的理想本地开发伙伴。希望本文能帮助你顺利开启 Workerman 的探索之旅!