laravel-s实现高性能webSocket服务
Posted willem_chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了laravel-s实现高性能webSocket服务相关的知识,希望对你有一定的参考价值。
laravel-s实现高性能webSocket服务
1 安装
首先php需要安装swoole扩展,仅支持 Linux、FreeBSD、MacOS 三种操作系统。
安装 laravel,安装 LaravelS 扩展包。
[root@bogon laravels]# php -m
[PHP Modules]
swoole
基于 LaravelS 构建 HTTP 服务器
nginx 为例,进行示例演示。
配置 Nginx
我们知道在使用 Nginx 作为 Web 服务器的时候,前端资源文件,比如 CSS、JS、图片等静态资源都是通过 Nginx 进行处理的,比较高效,而 PHP 脚本请求这种动态资源都是转发到后端 PHP-FPM 进程进行处理,如果要基于 Swoole 实现高性能 HTTP 服务器,则这个 HTTP 服务器替代的也是 PHP-FPM 的职能,也就是说,我们将原本转发到 PHP-FPM 进程的请求转发给 Swoole 进行处理。在本例中,就是转发给 LaravelS 服务。
配置文件
upstream laravels {
# Connect IP:Port
server 172.20.31.97:5200 weight=5 max_fails=3 fail_timeout=30s;
keepalive 16;
}
server {
listen 80;
server_name www.thhir.com;
root /www/wwwroot/laravels/public;
index index.php index.html index.htm;
# Nginx 处理静态资源,LaravelS 处理动态资源
location / {
try_files $uri @laravels;
}
location @laravels {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header Server-Protocol $server_protocol;
proxy_set_header Server-Name $server_name;
proxy_set_header Server-Addr $server_addr;
proxy_set_header Server-Port $server_port;
proxy_pass http://laravels;
}
}
配置 Laravel 应用
接下来,在 blog 项目根目录下打开 .env,新增下面两条配置:
LARAVELS_LISTEN_IP=172.20.31.97
LARAVELS_DAEMONIZE=true
LARAVELS_LISTEN_IP 用于设置 LaravelS 监听的 IP 地址,这里的地址和 Nginx 配置转发的 IP 地址保持一致,就是 workspace 容器名,LARAVELS_DAEMONIZE 用于设置后台启动 LaravelS 服务。
2 在 Laravel 中集成 Swoole 实现 WebSocket 服务器
LaravelS 扩展包把 Swoole 集成到 Laravel 项目来实现 WebSocket 服务器,以便与客户端进行 WebSocket 通信从而实现广播功能。
1 修改配置文件
接下来,打开配置文件 config/laravels.php,启用 WebSocket 通信并将刚刚创建的服务器类配置到对应的配置项:
'websocket' => [
'enable' => true, // 看清楚,这里是true
'handler' => \\App\\Services\\WebSocketService::class,
],
'swoole' => [
//...
// dispatch_mode只能设置为2、4、5,https://wiki.swoole.com/wiki/page/277.html
'dispatch_mode' => 2,
//...
],
2 创建 WebSocketService 类
在app文件夹下新建Services文件夹,新建WebSocketService.php文件
<?php
namespace App\\Services;
use Hhxsv5\\LaravelS\\Swoole\\WebSocketHandlerInterface;
use Illuminate\\Support\\Facades\\Log;
use Swoole\\Http\\Request;
use Swoole\\WebSocket\\Frame;
use Swoole\\WebSocket\\Server;
class WebSocketService implements WebSocketHandlerInterface
{
public function __construct()
{
}
// 连接建立时触发
public function onOpen(Server $server, Request $request)
{
// 在触发 WebSocket 连接建立事件之前,Laravel 应用初始化的生命周期已经结束,你可以在这里获取 Laravel 请求和会话数据
// 调用 push 方法向客户端推送数据,fd 是客户端连接标识字段
Log::info('WebSocket 连接建立');
$server->push($request->fd, '欢迎使用基于LaravelS的WebSocket服务器');
}
// 收到消息时触发
public function onMessage(Server $server, Frame $frame)
{
// 调用 push 方法向客户端推送数据
// $server->push($frame->fd, '这是从WebSocket服务器发送的消息 ' . date('Y-m-d H:i:s'));
$server->push($frame->fd, "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\\n");
}
// 关闭连接时触发
public function onClose(Server $server, $fd, $reactorId)
{
Log::info('WebSocket 连接关闭');
}
}
3 测试
新建一个控制器和视图和路由
Route::get('text', 'TextController@text');
<?php
namespace App\\Http\\Controllers;
use App\\Exceptions\\ApiException;
use App\\GoodsCategory;
use Common;
use Illuminate\\Http\\Request;
class TextController extends Controller
{
public function text()
{
return view('index');
}
}
view视图
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chat Client</title>
</head>
<body>
<script>
window.onload = function () {
var nick = prompt("Enter your nickname");
var input = document.getElementById("input");
input.focus();
// 初始化客户端套接字并建立连接
var socket = new WebSocket("ws://www.thhir.com:5200");
// 连接建立时触发
socket.onopen = function (event) {
console.log("webSocket 链接成功");
}
// 接收到服务端推送时执行
socket.onmessage = function (event) {
var msg = event.data;
var node = document.createTextNode(msg);
var div = document.createElement("div");
div.appendChild(node);
document.body.insertBefore(div, input);
input.scrollIntoView();
};
// 连接关闭时触发
socket.onclose = function (event) {
console.log("WebSocket 关闭连接");
}
input.onchange = function () {
var msg = nick + ": " + input.value;
// 将输入框变更信息通过 send 方法发送到服务器
socket.send(msg);
input.value = "";
};
}
</script>
<input id="input" style="width: 100%;">
</body>
</html>
预览效果
以上是关于laravel-s实现高性能webSocket服务的主要内容,如果未能解决你的问题,请参考以下文章
怎么使用 Socket.io 连接 WebSocket 服务
node.js搭建简单服务器,用于前端测试websocket链接方法和性能测试