怎样在PHP项目中实现Workerman?

wen java案例 2

本文目录导读:

怎样在PHP项目中实现Workerman?

  1. 安装Workerman
  2. 基础示例代码
  3. 与框架集成
  4. 进阶用法
  5. 部署配置
  6. 安全考虑
  7. 性能优化
  8. 常见问题解决

我来详细讲解如何在PHP项目中集成和使用Workerman。

安装Workerman

使用Composer安装(推荐)

# 在项目根目录执行
composer require workerman/workerman

手动安装

# 下载源码
git clone https://github.com/walkor/Workerman.git

基础示例代码

简单HTTP服务器

<?php
// server.php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
// 创建一个Worker监听端口,使用http协议
$http_worker = new Worker('http://0.0.0.0:8080');
// 设置进程数
$http_worker->count = 4;
// 接收到浏览器发送的数据时会触发此事件
$http_worker->onMessage = function(TcpConnection $connection, Request $request) {
    // 设置响应头
    $connection->send("Hello World");
};
// 运行worker
Worker::runAll();

启动服务器:

php server.php start

WebSocket服务器示例

<?php
// websocket.php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
// 创建WebSocket服务器
$ws_worker = new Worker('websocket://0.0.0.0:8080');
// 设置进程数
$ws_worker->count = 1;
// 建立连接时触发
$ws_worker->onConnect = function(TcpConnection $connection) {
    echo "新连接: {$connection->getRemoteIp()}\n";
    $connection->send('欢迎连接WebSocket服务器!');
};
// 接收到消息时触发
$ws_worker->onMessage = function(TcpConnection $connection, $data) {
    echo "收到消息: {$data}\n";
    // 发送消息给客户端
    $connection->send("服务端回复: {$data}");
};
// 连接关闭时触发
$ws_worker->onClose = function(TcpConnection $connection) {
    echo "连接关闭\n";
};
Worker::runAll();

与框架集成

在Laravel中使用

<?php
// app/Console/Commands/WorkermanCommand.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Workerman\Worker;
class WorkermanCommand extends Command
{
    protected $signature = 'workerman:start {action?}';
    protected $description = 'Workerman服务器管理';
    public function handle()
    {
        $action = $this->argument('action') ?: 'start';
        $worker = new Worker('http://0.0.0.0:8080');
        $worker->count = 4;
        $worker->onMessage = function($connection, $request) {
            $connection->send('Laravel + Workerman');
        };
        Worker::runAll();
    }
}

在ThinkPHP中使用

<?php
// application/command/Workerman.php
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use Workerman\Worker;
class Workerman extends Command
{
    protected function configure()
    {
        $this->setName('workerman:start')
             ->setDescription('Start Workerman');
    }
    protected function execute(Input $input, Output $output)
    {
        $worker = new Worker('http://0.0.0.0:8080');
        $worker->count = 4;
        $worker->onMessage = function($connection, $request) {
            $connection->send('ThinkPHP + Workerman');
        };
        Worker::runAll();
    }
}

进阶用法

定时任务

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Workerman\Lib\Timer;
$task_worker = new Worker();
$task_worker->count = 1;
$task_worker->onWorkerStart = function($worker) {
    // 每5秒执行一次
    $time_interval = 5;
    $timer_id = Timer::add($time_interval, function() {
        echo "定时任务执行\n";
    });
};
Worker::runAll();

心跳检测

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Workerman\Lib\Timer;
$ws_worker = new Worker('websocket://0.0.0.0:8080');
$ws_worker->count = 1;
$ws_worker->onConnect = function($connection) {
    $connection->lastPingTime = time();
    // 设置定时器检查心跳
    $connection->timer_id = Timer::add(10, function() use ($connection) {
        if (time() - $connection->lastPingTime > 30) {
            echo "心跳超时,关闭连接\n";
            $connection->close();
        }
    });
};
$ws_worker->onMessage = function($connection, $data) {
    if ($data === 'ping') {
        $connection->lastPingTime = time();
        $connection->send('pong');
    } else {
        $connection->send("收到: {$data}");
    }
};
Worker::runAll();

部署配置

生产环境启动脚本

#!/bin/bash
# start.sh
case "$1" in
    start)
        echo "Starting Workerman..."
        php server.php start -d
        ;;
    stop)
        echo "Stopping Workerman..."
        php server.php stop
        ;;
    restart)
        echo "Restarting Workerman..."
        php server.php restart
        ;;
    status)
        echo "Checking Workerman status..."
        php server.php status
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

Nginx代理配置

# nginx.conf
upstream workerman {
    server 127.0.0.1:8080;
    # 如果有多个Worker实例
    # server 127.0.0.1:8081;
}
server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://workerman;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 86400;
    }
}

安全考虑

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
// 限制访问IP
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function($connection, $request) {
    $allowed_ips = ['127.0.0.1', '192.168.1.*'];
    $client_ip = $connection->getRemoteIp();
    if (!in_array($client_ip, $allowed_ips)) {
        $connection->close();
        return;
    }
    $connection->send('安全连接');
};
// 设置运行用户
$worker->user = 'www-data';
$worker->group = 'www-data';
Worker::runAll();

性能优化

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker('http://0.0.0.0:8080');
// 设置进程数(根据CPU核心数设置)
$worker->count = 4;
// 开启reusePort(Linux 3.9+)
$worker->reusePort = true;
// 设置连接超时
$worker->connections = 1024;
// 使用更少的IO操作
$worker->onMessage = function($connection, $request) {
    // 使用Redis/Memcached缓存
    static $cache = [];
    $cache_key = $request->path();
    if (isset($cache[$cache_key])) {
        $connection->send($cache[$cache_key]);
        return;
    }
    // 业务逻辑
    $result = "Response for: {$cache_key}";
    $cache[$cache_key] = $result;
    $connection->send($result);
};
// 设置事件循环
$worker->eventLoop = \Workerman\Events\Ev::class;
Worker::runAll();

常见问题解决

端口被占用

# 检查端口
netstat -anp | grep 8080
# 使用不同端口
$worker = new Worker('http://0.0.0.0:9090');

内存不足

// 限制内存使用
ini_set('memory_limit', '256M');
// 设置单进程处理连接数限制
$worker->maxRequestCount = 1000;

日志管理

// 设置日志文件
Worker::$logFile = '/var/log/workerman.log';
Worker::$stdoutFile = '/var/log/workerman_stdout.log';

Workerman真正强大的地方在于它的事件驱动架构,特别适合高并发、长连接或实时通信场景,如果你想深入某个功能(比如WebSocket聊天室、长连接优化等),可以具体问我。

抱歉,评论功能暂时关闭!