0
点赞
收藏
分享

微信扫一扫

laravel-s实现高性能webSocket服务


laravel-s实现高性能webSocket服务

  • 1 安装
  • 基于 LaravelS 构建 HTTP 服务器
  • 2 在 Laravel 中集成 Swoole 实现 WebSocket 服务器
  • 1 修改配置文件
  • 2 创建 WebSocketService 类
  • 3 测试
  • 新建一个控制器和视图和路由
  • view视图
  • 预览效果

1 安装

首先PHP需要安装swoole扩展,仅支持 Linux、FreeBSD、MacOS 三种操作系统。
安装 laravel,安装 LaravelS 扩展包。

[root@bogon laravels]# php -m
[PHP Modules]
swoole

laravel-s实现高性能webSocket服务_laravel


参考文献

laravel-s实现高性能webSocket服务_Server_02

基于 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服务_服务器_03


laravel-s实现高性能webSocket服务_laravel_04


laravel-s实现高性能webSocket服务_Server_05


laravel-s实现高性能webSocket服务_服务器_06


举报

相关推荐

0 条评论