Giter Club home page Giter Club logo

chat's Introduction

用 Laravel Reverb 和 Vue SPA 开发的聊天室

介绍

这是一个使用 Laravel Reverb 和 Vue SPA 开发的聊天室,支持多房间、多用户、实时聊天等功能。

技术栈

Note

前后端公用一个仓库,通过 Laravel Sanctum 来处理 SPA 登陆认证。

后端是 Laravel,采用 Laravel Reverb 作为 WebSocket 服务器,负责从 Event 事件中推送消息到前端。

前端是 Vue SPA,使用了 Vue Router 作为路由管理,Pinia 共享全局状态,Tailwind CSS 添加样式。

本地开发

常规的 Laravel 项目开发流程,不再赘述。

.env 设置

配置 .env 文件时,确保广播连接设置为 reverb,如下:

BROADCAST_CONNECTION=reverb

Warning

BROADCAST_CONNECTION 默认是 log 哦,这里要改成 reverb,别像我部署的时候忘了改,浪费了一个小时

添加 Reverb 的配置,新项目安装 Reverb 时会自动生成并写入 .env,但是部署或者 git clone 时,需要手动添加,如下:

REVERB_APP_ID=321494
REVERB_APP_KEY=v7pw8vesuuhaguqg3zop
REVERB_APP_SECRET=0ikht21jxdfge9dyg6h5
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"

Tip

  • REVERB_APP_ID REVERB_APP_KEY REVERB_APP_SECRET 具体是什么不重要,随便填写即可;
  • REVERB_HOST REVERB_PORT REVERB_SCHEME 只对 Vite 有效,如果你不喜欢默认的配置,从命令行才能修改。

如果需要 @kimi 支持,还需要添加 Moonshot 的 API:

Tip

Moonshot 免费额度内可能限制较大,比如 3 RPM(每分钟最多 3 次)等

MOONSHOT_API_KEY=sk-xxx

本地运行

Reverb 是通过异步事件才能触发,因此得把队列跑起来:

php artisan queue:listen

然后再启动 Reverb 服务:

php artisan reverb:work --debug

chat's People

Contributors

xuchunyang avatar

Watchers

 avatar

chat's Issues

用 GitHub Action 自动化部署

当前的部署环境是崭新的一台 Ubuntu 22.04 腾讯云轻量,我已经手动装了 Caddy、PHP-FPM 等,已经把应用跑起来了,要是能自动化部署就更好了,我之前已经弄过多次了,包括 BT 宝塔 和 1Panel,这次是崭新的服务器。

基本上执行 SSH 进服务器,git pull 代码,安装依赖,迁移数据库等等部署命令。

MessageCreated 广播出错:production.ERROR: Pusher error: Internal server error.

偶然发现了 2 次事件出错的情况,恐怕这意味着这 2 条消息广播失败了,原因待调整:

CleanShot 2024-03-26 at 21 14 10@2x

下面是日志:

[2024-03-26 13:09:06] production.ERROR: Pusher error: Internal server error.. {"exception":"[object] (Illuminate\\Broadcasting\\BroadcastException(code: 0): Pusher error: Internal server error.. at /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php:164)
[stacktrace]
#0 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Broadcasting/BroadcastEvent.php(92): Illuminate\\Broadcasting\\Broadcasters\\PusherBroadcaster->broadcast()
#1 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Broadcasting\\BroadcastEvent->handle()
#2 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#3 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
#4 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\\Container\\BoundMethod::callBoundMethod()
#5 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
#6 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(128): Illuminate\\Container\\Container->call()
#7 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Bus\\Dispatcher->Illuminate\\Bus\\{closure}()
#8 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#9 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(132): Illuminate\\Pipeline\\Pipeline->then()
#10 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(123): Illuminate\\Bus\\Dispatcher->dispatchNow()
#11 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Queue\\CallQueuedHandler->Illuminate\\Queue\\{closure}()
#12 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#13 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(122): Illuminate\\Pipeline\\Pipeline->then()
#14 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(70): Illuminate\\Queue\\CallQueuedHandler->dispatchThroughMiddleware()
#15 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(102): Illuminate\\Queue\\CallQueuedHandler->call()
#16 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(439): Illuminate\\Queue\\Jobs\\Job->fire()
#17 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(389): Illuminate\\Queue\\Worker->process()
#18 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(176): Illuminate\\Queue\\Worker->runJob()
#19 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(139): Illuminate\\Queue\\Worker->daemon()
#20 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(122): Illuminate\\Queue\\Console\\WorkCommand->runWorker()
#21 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Queue\\Console\\WorkCommand->handle()
#22 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#23 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
#24 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\\Container\\BoundMethod::callBoundMethod()
#25 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
#26 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Console/Command.php(212): Illuminate\\Container\\Container->call()
#27 /home/ubuntu/chat/vendor/symfony/console/Command/Command.php(279): Illuminate\\Console\\Command->execute()
#28 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Console/Command.php(181): Symfony\\Component\\Console\\Command\\Command->run()
#29 /home/ubuntu/chat/vendor/symfony/console/Application.php(1049): Illuminate\\Console\\Command->run()
#30 /home/ubuntu/chat/vendor/symfony/console/Application.php(318): Symfony\\Component\\Console\\Application->doRunCommand()
#31 /home/ubuntu/chat/vendor/symfony/console/Application.php(169): Symfony\\Component\\Console\\Application->doRun()
#32 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(196): Symfony\\Component\\Console\\Application->run()
#33 /home/ubuntu/chat/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1183): Illuminate\\Foundation\\Console\\Kernel->handle()
#34 /home/ubuntu/chat/artisan(13): Illuminate\\Foundation\\Application->handleCommand()
#35 {main}
"}

了解下 Laravel 错误监控

Laravel App 上可能不时会出现各种问题,比如 AI API 欠费了,但发生异常时,要是能自动通知就好了。

能监控日志也不错了,但是 https://flareapp.io/https://sentry.io/for/laravel/ 看起来不错,但是都用不起,可以调查下其他方案。

ubuntu@VM-4-16-ubuntu:~/chat$ grep ERROR storage/logs/laravel.log | cut -c 1-120
[2024-03-25 15:38:07] production.ERROR: could not find driver (Connection: sqlite, SQL: select name from sqlite_master w
[2024-03-25 15:47:16] production.ERROR: file_put_contents(/var/www/chat/storage/framework/views/a8f168890e63c2214164d587
[2024-03-25 15:47:16] production.ERROR: SQLSTATE[HY000]: General error: 8 attempt to write a readonly database (Connecti
[2024-03-25 15:47:41] production.ERROR: file_put_contents(/var/www/chat/storage/framework/views/a8f168890e63c2214164d587
[2024-03-25 16:03:45] production.ERROR: Pusher error: cURL error 6: Could not resolve host: reverb.chat.xuchunyang.cn (s
[2024-03-25 16:03:48] production.ERROR: Pusher error: cURL error 6: Could not resolve host: reverb.chat.xuchunyang.cn (s
[2024-03-26 06:48:25] production.ERROR: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: us
[2024-03-26 06:48:45] production.ERROR: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: us
[2024-03-26 13:08:54] production.ERROR: Pusher error: Internal server error.. {"exception":"[object] (Illuminate\\Broadc
[2024-03-26 13:09:06] production.ERROR: Pusher error: Internal server error.. {"exception":"[object] (Illuminate\\Broadc
[2024-03-26 13:19:19] production.ERROR: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: us
[2024-03-26 13:21:48] production.ERROR: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: us
[2024-03-26 13:22:20] production.ERROR: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: us

处理 localStorage 中登陆状态过期的情况

更新 App 之后,之前的登陆状态会过期,但是目前我只依据 localStorage 来判断用户是否已经登陆,就会出现下面的问题:

CleanShot 2024-03-26 at 22 29 35@2x

虽然用户可以手动退出登陆,再重新登陆,但是这并不友好,一般用户会认为这是一个 bug,当然确实是一个 bug。

提示新消息

当有新消息时,左边的数字可以用红点标记下。

Vue SPA 路由改用 HTML5 Mode

需要服务器端配合下,目前的 Caddy 配置:

chat.xuchunyang.cn {
        root * /home/ubuntu/chat/public
        php_fastcgi unix//run/php/php-fpm.sock
        file_server
}

reverb.chat.xuchunyang.cn {
        reverse_proxy :8080
}

CleanShot 2024-03-26 at 22 08 35@2x

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.