本文将详细介绍如何利用开源的 Workerman 框架开发一个高性能的在线客服系统源码,重点解决即时通讯聊天部分的实现。Workerman 是一款开源高性能的 PHP 异步 Socket 框架,特别适合构建实时通讯应用,如客服系统源码、即时聊天源码等。市面上大部分PHP开发的客服系统都是基于workerman开发的,例如99客服等。本教程将带你从环境搭建到实现一个简单的 WebSocket 聊天功能,帮助开发者快速上手。
在开始开发之前,需要准备以下环境和工具:
使用 Composer 安装 Workerman 和 GatewayWorker(Workerman 的增强版,适合开发客服系统):
# 它会自动安装workerman
composer require workerman/gatewayworker
以下是实现客服系统即时通讯功能的核心步骤。我们将使用 GatewayWorker 框架,结合 WebSocket 协议实现实时聊天。
在 start.php
中配置 GatewayWorker 服务,负责处理 WebSocket 连接和消息分发。
use Workerman\Worker;
use GatewayWorker\Gateway;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Register;
require_once __DIR__ . '/../vendor/autoload.php';
// Register 服务,用于服务注册
$register = new Register('text://0.0.0.0:1238');
// Gateway 服务,监听 WebSocket 连接
$gateway = new Gateway("websocket://0.0.0.0:8282");
$gateway->name = 'ChatGateway';
$gateway->count = 4; // 启动 4 个进程
$gateway->registerAddress = '127.0.0.1:1238';
// BusinessWorker 服务,处理业务逻辑
$business_worker = new BusinessWorker();
$business_worker->name = 'ChatBusiness';
$business_worker->count = 4;
$business_worker->registerAddress = '127.0.0.1:1238';
$business_worker->eventHandler = '\Events';
// 启动服务
if (!defined('GLOBAL_START')) {
Worker::runAll();
}
?>
在 Events.php
中实现 WebSocket 的事件处理逻辑,包括连接建立、消息接收和断开连接等。
use GatewayWorker\Lib\Gateway;
class Events
{
// 客户端连接时触发
public static function onConnect($client_id)
{
// 向新连接的客户端发送欢迎消息
Gateway::sendToClient($client_id, json_encode([
'type' => 'welcome',
'message' => '欢迎使用客服系统!您的客户端 ID: ' . $client_id
]));
}
// 接收到客户端消息时触发
public static function onMessage($client_id, $message)
{
$data = json_decode($message, true);
if (!$data) return;
switch ($data['type']) {
case 'chat':
// 广播消息给所有客户端
Gateway::sendToAll(json_encode([
'type' => 'chat',
'message' => $data['message'],
'client_id' => $client_id,
'time' => date('Y-m-d H:i:s')
]));
break;
case 'bind':
// 绑定用户 ID(例如客服或用户)
Gateway::bindUid($client_id, $data['uid']);
break;
}
}
// 客户端断开连接时触发
public static function onClose($client_id)
{
// 通知所有客户端某用户下线
Gateway::sendToAll(json_encode([
'type' => 'system',
'message' => '用户 ' . $client_id . ' 已下线',
'time' => date('Y-m-d H:i:s')
]));
}
}
?>
在 public/index.html
中创建前端页面,使用 WebSocket 连接到服务端。
DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Workerman 客服系统title>
<style>
#chat-box { height: 400px; overflow-y: scroll; border: 1px solid #ccc; padding: 10px; }
#message { width: 80%; padding: 5px; }
#send-btn { padding: 5px 10px; }
style>
head>
<body>
<h2>在线客服系统h2>
<div id="chat-box">div>
<input type="text" id="message" placeholder="请输入消息">
<button id="send-btn">发送button>
<script>
const ws = new WebSocket('ws://127.0.0.1:8282');
const chatBox = document.getElementById('chat-box');
const messageInput = document.getElementById('message');
const sendBtn = document.getElementById('send-btn');
ws.onopen = () => {
// 连接成功后绑定用户 ID
ws.send(JSON.stringify({ type: 'bind', uid: 'user_' + Math.random().toString(36).substr(2) }));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
const p = document.createElement('p');
if (data.type === 'chat') {
p.textContent = `[${data.time}] ${data.client_id}: ${data.message}`;
} else if (data.type === 'welcome' || data.type === 'system') {
p.textContent = `[系统] ${data.message}`;
}
chatBox.appendChild(p);
chatBox.scrollTop = chatBox.scrollHeight;
};
sendBtn.onclick = () => {
const message = messageInput.value.trim();
if (message) {
ws.send(JSON.stringify({ type: 'chat', message }));
messageInput.value = '';
}
};
messageInput.onkeypress = (e) => {
if (e.key === 'Enter') sendBtn.click();
};
script>
body>
html>
在项目根目录下运行以下命令启动 Workerman 服务:
php start.php start
然后通过 Web 服务器(如 Nginx)访问 public/index.html
,即可进入聊天界面。
通过 Gateway::bindUid
方法,可以为每个客户端绑定一个唯一用户 ID,区分客服和普通用户。例如,可以在 Events.php
中添加逻辑,将消息只发送给特定用户组。
将聊天记录存储到数据库(如 MySQL 或 Redis),在用户连接时加载历史消息。可以在 onMessage
中添加数据库操作逻辑。
Workerman 支持多进程和事件驱动模型,可通过调整 start.php
中的 count
参数增加进程数,以支持更多并发连接。
start.php
中启用日志以便调试。