laravel下安装laravels以及websocket的使用


laravel下安装laravels以及websocket的使用

🚀 LaravelS 是 Swoole 和 Laravel/Lumen 之间开箱即用的适配器。

环境要求

依赖 说明
PHP >= 5.5.9 推荐PHP7+
Swoole >= 1.7.19 从2.0.12开始不再支持PHP5 推荐4.2.3+
Laravel/Lumen >= 5.1 推荐5.6+

安装

1.通过Composer安装(packagist)。有可能找不到3.0版本,解决方案移步#81

composer require "hhxsv5/laravel-s:~3.7.0" -vvv
# 确保你的composer.lock文件是在版本控制中

2.注册Service Provider(以下两步二选一)。

  • Laravel: 修改文件config/app.phpLaravel 5.5+支持包自动发现,你应该跳过这步

      'providers' => [
          //...
          Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class,
      ],
    
  • Lumen: 修改文件bootstrap/app.php

      $app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
    

3.发布配置和二进制文件。

每次升级LaravelS后,需重新publish;点击Release去了解各个版本的变更记录。

php artisan laravels publish
# 配置文件:config/laravels.php
# 二进制文件:bin/laravels bin/fswatch bin/inotify

4.修改配置config/laravels.php:监听的IP、端口等,请参考配置项

运行

在运行之前,请先仔细阅读:注意事项(这非常重要)。

  • 操作命令:php bin/laravels {start|stop|restart|reload|info|help}
命令 说明
start 启动LaravelS,展示已启动的进程列表 “ps -ef|grep laravels
stop 停止LaravelS,并触发自定义进程的onStop方法
restart 重启LaravelS:先平滑Stop,然后再Start;在Start完成之前,服务是不可用的
reload 平滑重启所有Task/Worker/Timer进程(这些进程内包含了你的业务代码),并触发自定义进程的onReload方法,不会重启Master/Manger进程;修改config/laravels.php后,你只有调用restart来完成重启
info 显示组件的版本信息
help 显示帮助信息
  • 启动选项,针对startrestart命令。
选项 说明
-d|—daemonize 以守护进程的方式运行,此选项将覆盖laravels.phpswoole.daemonize设置
-e|—env 指定运行的环境,如--env=testing将会优先使用配置文件.env.testing,这个特性要求Laravel 5.2+
-i|—ignore 忽略检查Master进程的PID文件
-x|—x-version 记录当前工程的版本号(分支),保存在$_ENV/$_SERVER中,访问方式:$_ENV['X_VERSION'] $_SERVER['X_VERSION'] $request->server->get('X_VERSION')
  • 运行时文件:start时会自动执行php artisan laravels config并生成这些文件,开发者一般不需要关注它们,建议将它们加到.gitignore中。
文件 说明
storage/laravels.conf LaravelS的运行时配置文件
storage/laravels.pid Master进程的PID文件
storage/laravels-timer-process.pid 定时器Timer进程的PID文件
storage/laravels-custom-processes.pid 所有自定义进程的PID文件

与Nginx配合使用(推荐)

gzip on;
gzip_min_length 1024;
gzip_comp_level 2;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
gzip_vary on;
gzip_disable "msie6";
upstream swoole {
    # 通过 IP:Port 连接
    server 127.0.0.1:5200 weight=5 max_fails=3 fail_timeout=30s;
    # 通过 UnixSocket Stream 连接,小诀窍:将socket文件放在/dev/shm目录下,可获得更好的性能
    #server unix:/yourpath/laravel-s-test/storage/laravels.sock weight=5 max_fails=3 fail_timeout=30s;
    #server 192.168.1.1:5200 weight=3 max_fails=3 fail_timeout=30s;
    #server 192.168.1.2:5200 backup;
    keepalive 16;
}
server {
    listen 80;
    # 别忘了绑Host
    server_name laravels.com;
    root /yourpath/laravel-s-test/public;
    access_log /yourpath/log/nginx/$server_name.access.log  main;
    autoindex off;
    index index.html index.htm;
    # Nginx处理静态资源(建议开启gzip),LaravelS处理动态资源。
    location / {
        try_files $uri @laravels;
    }
    # 当请求PHP文件时直接响应404,防止暴露public/*.php
    #location ~* \.php$ {
    #    return 404;
    #}
    location @laravels {
        # proxy_connect_timeout 60s;
        # proxy_send_timeout 60s;
        # proxy_read_timeout 120s;
        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;
        # “swoole”是指upstream
        proxy_pass http://swoole;
    }
}

启用WebSocket服务器

WebSocket服务器监听的IP和端口与Http服务器相同。

1.创建WebSocket Handler类,并实现接口WebSocketHandlerInterface。start时会自动实例化,不需要手动创建实例。

fd, request()->all(), session()->getId(), session('xxx'), session(['yyy' => time()])]);
        Log::info('WebSocket 连接建立');
        $server->push($request->fd, 'Welcome to LaravelS');
        // throw new \Exception('an exception');// 此时抛出的异常上层会忽略,并记录到Swoole日志,需要开发者try/catch捕获处理
    }
    public function onMessage(Server $server, Frame $frame)
    {
        // \Log::info('Received message', [$fram        // \Log::info('Received message', [$frame->fd, $frame->data, $frame->opcode, $frame->finish]);
        //
        //        $server->push($frame->fd, $frame->data);e->fd, $frame->data, $frame->opcode, $frame->finish]);

        $server->push($frame->fd, $frame->data);
//        $arr = [
//            'time' => date('Y-m-d H:i:s')
//        ];
//        $server->push($frame->fd, json_encode($arr));
        // throw new \Exception('an exception');// 此时抛出的异常上层会忽略,并记录到Swoole日志,需要开发者try/catch捕获处理
    }
    public function onClose(Server $server, $fd, $reactorId)
    {
        Log::info('WebSocket 连接关闭');
        // throw new \Exception('an exception');// 此时抛出的异常上层会忽略,并记录到Swoole日志,需要开发者try/catch捕获处理
    }

}

2.更改配置config/laravels.php

// ...
'websocket'      => [
    'enable'  => true, // 看清楚,这里是true
    'handler' => \App\Services\WebSocketService::class,
],
'swoole'         => [
    //...
    // dispatch_mode只能设置为2、4、5,https://wiki.swoole.com/#/server/setting?id=dispatch_mode
    'dispatch_mode' => 2,
    //...
],
// ...

3.使用SwooleTable绑定FD与UserId,可选的,Swoole Table示例。也可以用其他全局存储服务,例如Redis/Memcached/MySQL,但需要注意多个Swoole Server实例时FD可能冲突。

4.与Nginx配合使用(推荐)

参考 WebSocket代理

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
upstream swoole {
    # 通过 IP:Port 连接
    server 127.0.0.1:5200 weight=5 max_fails=3 fail_timeout=30s;
    # 通过 UnixSocket Stream 连接,小诀窍:将socket文件放在/dev/shm目录下,可获得更好的性能
    #server unix:/yourpath/laravel-s-test/storage/laravels.sock weight=5 max_fails=3 fail_timeout=30s;
    #server 192.168.1.1:5200 weight=3 max_fails=3 fail_timeout=30s;
    #server 192.168.1.2:5200 backup;
    keepalive 16;
}
server {
    listen 80;
    # 别忘了绑Host
    server_name laravels.com;
    root /yourpath/laravel-s-test/public;
    access_log /yourpath/log/nginx/$server_name.access.log  main;
    autoindex off;
    index index.html index.htm;
    # Nginx处理静态资源(建议开启gzip),LaravelS处理动态资源。
    location / {
        try_files $uri @laravels;
    }
    # 当请求PHP文件时直接响应404,防止暴露public/*.php
    #location ~* \.php$ {
    #    return 404;
    #}
    # Http和WebSocket共存,Nginx通过location区分
    # !!! WebSocket连接时路径为/ws
    # Javascript: var ws = new WebSocket("ws://laravels.com/ws");
    location =/ws {
        # proxy_connect_timeout 60s;
        # proxy_send_timeout 60s;
        # proxy_read_timeout:如果60秒内被代理的服务器没有响应数据给Nginx,那么Nginx会关闭当前连接;同时,Swoole的心跳设置也会影响连接的关闭
        # proxy_read_timeout 60s;
        proxy_http_version 1.1;
        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_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_pass http://swoole;
    }
    location @laravels {
        # proxy_connect_timeout 60s;
        # proxy_send_timeout 60s;
        # proxy_read_timeout 60s;
        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://swoole;
    }
}

5.心跳配置

  • Swoole的心跳配置

      // config/laravels.php
      'swoole' => [
          //...
          // 表示每60秒遍历一次,一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭
          'heartbeat_idle_time'      => 600,
          'heartbeat_check_interval' => 60,
          //...
      ],
    
  • Nginx读取代理服务器超时的配置

      # 如果60秒内被代理的服务器没有响应数据给Nginx,那么Nginx会关闭当前连接
      proxy_read_timeout 60s;
    

    HTML实战代码

    GitHub完整源代码

<script type="text/javascript">
    if(window.WebSocket){
        // 端口和ip地址对应不要写错
        var webSocket = new WebSocket("ws://127.0.0.1:5200");
        webSocket.onopen = function (event) {
            console.log('webSocket 连接成功');
        };
        // 连接关闭时触发
        webSocket.onclose = function (event) {
            console.log("WebSocket 关闭连接");
        }

        //收到服务端消息回调
        webSocket.onmessage = function (event) {
            var content = document.getElementById('content');
            content.innerHTML = content.innerHTML.concat('<p style="margin-left:20px;height:20px;line-height:20px;">'+event.data+'</p>');
            console.log(event.data)
        }

        var sendMessage = function(){
            var data = document.getElementById('message').value;
            webSocket.send(data);
        }
    }else{
        console.log("您的浏览器不支持WebSocket");
    }
</script>

实战截图

启动laravels服务
页面实战

结束语

希望本文可以帮助大家学习如何使用websocket。👍


文章作者: WXiangQian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WXiangQian !
 上一篇
laravel/telescope望远镜在laravel6下安装以及使用 laravel/telescope望远镜在laravel6下安装以及使用
介绍 Telescope 是一个非常优雅的调试助手,提供了非常丰富的 Debug 功能,给开发及调试带来了极大的方便,如果你一直使用 Clockwork 或者 Laravel Debugbar 进行项目的调试,那么现在又多了一个新的选择。不
2020-12-17
下一篇 
揭秘《双11星秀猫巅峰时刻》功能设计 揭秘《双11星秀猫巅峰时刻》功能设计
前言为大家提供更好的设计思路,一起看透助力拉人头,坑多多砍一刀等等功能~~ 2020-11-10晚9点再看浙江卫视直播,某宝APP手机摇一摇抽红包。进去活动以后发现,这功能我去年在某公司设计过类似的功能。所以今天拿来分享给大家~~~ 某
2020-11-13
  目录