当前位置: 首页 > news >正文

ThinkPHP8使用workerman

应用场景说明:通过建立通信,不同用户进行消息推送或数据更新,因为本身需要作为服务端进行主动消息推送,因此使用Gateway方式,如果不需要的可以不采用这种形式,以下内容仅为参考,具体业务场景,自行修改!!!!

Linux或MacOS不需要进行自定义命令,直接使用php think worker:server  php think worker:gateway 使用即可。

废话少说,直接开干!!!

你可能会碰到以下问题,仅供参考!

一、可能会出现问题

1.GatewayWorker Not Support On Windows.

此问题出现在启用命令php think worker:gateway之后,需要使用自定义命令进行修改,具体下面细说

2.Implicit conversion from float 999996.9005584717 to int loses precision

此问题,在自定义命令后,需进行如下修改:\vendor\workerman\workerman\Events\Selelct.php第215行,

usleep($this->_selectTimeout); //    修改为下面usleep((int)$this->_selectTimeout);
二、不使用gateway

1.安装think-worker

composer require topthink/think-worker

2.运行命令

php think worker 运行httpphp think worker:server 运行webscoket //    默认是2345端口 

3.测试链接

// 新建一个html,直接复制以下代码,浏览器访问,打开控制台
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
</body>
<script>/*** 与GatewayWorker建立websocket连接,域名和端口改为你实际的域名端口,* 其中端口为Gateway端口,即start_gateway.php指定的端口。* start_gateway.php 中需要指定websocket协议,像这样* $gateway = new Gateway(websocket://0.0.0.0:7272);*/ws = new WebSocket("ws://127.0.0.1:2348");// 服务端主动推送消息时会触发这里的onmessagews.onopen = function () {// 触发系统自定义的test_event事件,发送json数据var data = {"type": "bind", "data": {"uid": "10001"}};ws.send(JSON.stringify(data));}ws.onmessage = function (e) {console.log(e.data);var data = {"type": "send", "data": {"uid": "10001", 'message': '呦吼'}};ws.send(JSON.stringify(data))}// ws.onmessage = onmessagews.onclose = function () {//  连接关闭,推送消息至服务端var data = {type: 'close', data: "{'uid':10001}"};ws.send(JSON.stringify(data));}</script>
</html>

4、效果截图

监听的方法,默认在config/worker_server.php里面,也可以通过继承Server进行修改,具体方法参考手册。tp-workerman

三、使用Gateway

如果直接使用 php think worker:gateway 就会提示GatewayWorker Not Support On Windows.具体原因简单说明(php think worker:gateway就是在同一个php文件里启动了多个worker,因为不能成功运行所以tp的命令行提前做了判定,显示不支持在windows下运行),大家自行搜一下具体原因即可。

具体解决思路,自定义命令进行运行,根据以下步骤进行参考

1.创建命令

php think make:command common@WorkerMain

2.复制以下代码到以上文件中

<?phpnamespace app\common\command;use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Config;
use Workerman\Worker;/*** Worker 命令行*/
class WorkerMain extends Command
{public function configure(){$this->setName('WorkerMain')->addArgument('service', Argument::OPTIONAL, 'workerman service: gateway|register|business_worker', null)->addOption('host', 'H', Option::VALUE_OPTIONAL, 'the host of workerman server.', null)->addOption('port', 'p', Option::VALUE_OPTIONAL, 'the port of workerman server.', null)->setDescription('GatewayWorker Server for ThinkPHP runs on Windows system');}/*** 由于windows下不支持下无法使用status、stop、reload、restart等命令。* 所以去掉status、stop、reload、restart、守护进程等命令。* 文档说明: https://www.workerman.net/doc/workerman/must-read.html** 命令使用:* php think worker:gateway_win register* php think worker:gateway_win business_worker* php think worker:gateway_win gateway** @param Input $input* @param Output $output* @return int|void|null*/public function execute(Input $input, Output $output){$service = $input->getArgument('service');$option = Config::get('gateway_worker');if ($input->hasOption('host')) {$host = $input->getOption('host');} else {$host = !empty($option['host']) ? $option['host'] : '0.0.0.0';}if ($input->hasOption('port')) {$port = $input->getOption('port');} else {$port = !empty($option['port']) ? $option['port'] : '2347';}$registerAddress = !empty($option['registerAddress']) ? $option['registerAddress'] : '127.0.0.1:1236';switch ($service) {case 'register':$this->register($registerAddress);break;case 'business_worker':$this->businessWorker($registerAddress, $option['businessWorker'] ?? []);break;case 'gateway':$this->gateway($registerAddress, $host, $port, $option);break;default:$output->writeln("<error>Invalid argument action:{$service}, Expected gateway|register|business_worker.</error>");exit(1);break;}Worker::runAll();}/*** 启动register* @access public* @param string $registerAddress* @return void*/public function register(string $registerAddress): void{// 初始化registernew Register('text://' . $registerAddress);}/*** 启动businessWorker* @access public* @param string $registerAddress registerAddress* @param array $option 参数* @return void*/public function businessWorker(string $registerAddress, array $option = []): void{// 初始化 bussinessWorker 进程$worker = new BusinessWorker();$this->option($worker, $option);$worker->registerAddress = $registerAddress;}/*** @note 返回Gateway对象* @param string $registerAddress 注册地址* @param string $host 服务地址* @param int $port 监听端口* @param array $option 参数* @return void*/public function gateway(string $registerAddress, string $host, int $port, array $option = []): void{// 初始化 gateway 进程if (!empty($option['socket'])) {$socket = $option['socket'];unset($option['socket']);} else {$protocol = !empty($option['protocol']) ? $option['protocol'] : 'websocket';$socket = $protocol . '://' . $host . ':' . $port;unset($option['host'], $option['port'], $option['protocol']);}$gateway = new Gateway($socket, $option['context'] ?? []);// 以下设置参数都可以在配置文件中重新定义覆盖$gateway->name = 'Gateway';$gateway->count = 4;$gateway->lanIp = '127.0.0.1';$gateway->startPort = 2000;$gateway->pingInterval = 5;$gateway->pingNotResponseLimit = 0;$gateway->pingData = '{"type":"ping"}';$gateway->registerAddress = $registerAddress;// 全局静态属性设置foreach ($option as $name => $val) {if (in_array($name, ['stdoutFile', 'daemonize', 'pidFile', 'logFile'])) {Worker::${$name} = $val;unset($option[$name]);}}$this->option($gateway, $option);}/*** 设置参数* @access protected* @param Worker $worker Worker对象* @param array $option 参数* @return void*/protected function option(Worker $worker, array $option = []){// 设置参数if (!empty($option)) {foreach ($option as $key => $val) {$worker->$key = $val;}}}
}

3.运行命令

//    需依次运行以下命令php think WorkerMain gatewayphp think WorkerMain business_workerphp think WorkerMain register

4.浏览器访问:端口需改成gateway端口,默认2348

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body></body>
<script>/*** 与GatewayWorker建立websocket连接,域名和端口改为你实际的域名端口,* 其中端口为Gateway端口,即start_gateway.php指定的端口。* start_gateway.php 中需要指定websocket协议,像这样* $gateway = new Gateway(websocket://0.0.0.0:7272);*/ws = new WebSocket("ws://127.0.0.1:2348");// 服务端主动推送消息时会触发这里的onmessagews.onopen = function () {// 触发系统自定义的test_event事件,发送json数据var data = {"type": "bind", "data": {"uid": "18317093686"}};ws.send(JSON.stringify(data));}ws.onmessage = onmessagews.onclose = function () {//  连接关闭,推送消息至服务端var data = {type: 'close', data: "{'uid':10001}"};ws.send(JSON.stringify(data));}// 服务端发来消息时function onmessage(e){console.log(e.data,123);var data = JSON.parse(e.data);switch(data['type']){// 服务端ping客户端case 'ping':ws.send('{"type":"pong"}');break;;// 登录 更新用户列表case 'login':var client_name = data['client_name'];if(data['client_list']){client_id = data['client_id'];client_name = '你';client_list = data['client_list'];}else{client_list[data['client_id']] = data['client_name'];}say(data['client_id'], data['client_name'],  client_name+' 加入了聊天室', data['time']);flush_client_list();console.log(data['client_name']+"登录成功");break;// 发言case 'say'://{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}console.log(data['msg']);break;// 用户退出 更新用户列表case 'logout'://{"type":"logout","client_id":xxx,"time":"xxx"}say(data['from_client_id'], data['from_client_name'], data['from_client_name']+' 退出了', data['time']);delete client_list[data['from_client_id']];flush_client_list();}}
</script>
</html>

完成以上工作就可以顺利进行啦。

相关文章:

ThinkPHP8使用workerman

应用场景说明&#xff1a;通过建立通信&#xff0c;不同用户进行消息推送或数据更新&#xff0c;因为本身需要作为服务端进行主动消息推送&#xff0c;因此使用Gateway方式&#xff0c;如果不需要的可以不采用这种形式&#xff0c;以下内容仅为参考&#xff0c;具体业务场景&am…...

C语言超详细教程

系列文章目录 文章目录 系列文章目录1 运算符1.1 算术运算符:2 控制语句2.1 条件语句:2.2 循环语句:3 函数3.1 函数的定义与声明:3.2 递归函数:4 指针4.1 指针的定义与使用函数指针:5. 数组与字符串5.1 数组一维数组:相同类型元素的集合(如:多维数组:数组的数组(如:…...

[开源]3K+ star!微软Office的平替工具,跨平台,超赞!

大家好&#xff0c;我是JavaCodexPro&#xff01; 数字化的当下&#xff0c;高效的办公工具是提升工作效率的关键&#xff0c;然而大家想到的一定是 Microsoft Office 办公软件&#xff0c;然而价格也是相当具有贵的性价比。 今天JavaCodexPro给大家分享一款超棒的开源办公套…...

如何借助计算机视觉算法通过识别水尺精准识别水位

如何借助计算机视觉算法通过识别水尺精准识别水位 随着技术的发展&#xff0c;计算机视觉在多个领域得到了广泛的应用&#xff0c;尤其是在环境监测方面。本文将介绍一种利用计算机视觉算法通过识别水尺来精准识别水位的方法。这种方法可以用于河流、水库等场景的水位监测&…...

C++(进阶) 第1章 继承

C&#xff08;进阶) 第1章 继承 文章目录 前言一、继承1.什么是继承2.继承的使用 二、继承方式1.private成员变量的&#xff08;3种继承方式&#xff09;继承2. private继承方式3.继承基类成员访问⽅式的变化 三、基类和派生类间的转换1.切片 四、 继承中的作⽤域1.隐藏规则&am…...

获国家权威机构认可 亚信安全荣获CNVD技术组支撑单位认证

近日&#xff0c;国家信息安全漏洞共享平台&#xff08;CNVD&#xff09;依据《CNVD管理办法》及《CNVD支撑单位能力要求》&#xff0c;对申请加入考察期的单位进行了全面而严格的能力评估。经过层层筛选与审核&#xff0c;亚信安全凭借卓越的技术实力与专业的服务能力&#xf…...

2. Autogen官网教程 (Terminating Conversations Between Agents)

在这一章中&#xff0c;我们将探讨如何结束自动生成代理之间的对话。 导入必要的库 import osfrom autogen import ConversableAgent配置智能体 我们需要配置智能体使用的语言模型&#xff08;LLM&#xff09;。以下是一个配置示例&#xff1a; llm_config {"config_…...

java 排序 详解

Java 提供了多种方式对数据进行排序&#xff0c;包括数组和集合的排序。排序在日常开发中非常常见&#xff0c;以下将从排序算法的基本原理、Java 中的内置排序方法以及自定义排序三方面进行详解。 1. 排序的基本概念 排序是将一组数据按特定顺序排列的过程&#xff0c;常见顺…...

【数据集】城市通量塔站点观测数据

【数据集】城市通量塔站点观测数据 数据概述数据下载参考数据概述 数据集简介:Harmonized gap-filled dataset from 20 urban flux tower sites 数据集名称:Harmonized gap-filled dataset from 20 urban flux tower sites (用于 Urban-PLUMBER 项目的 20 个城市通量塔站点…...

scau编译原理综合性实验

一、题目要求 题目&#xff1a; 选择部分C语言的语法成分&#xff0c;设计其词法分析程序、语法语义分析程序。 要求&#xff1a; 设计并实现一个一遍扫描的词法语法语义分析程序&#xff0c;将部分C语言的语法成分&#xff08;包含赋值语句、if语句、while循环语句&#xf…...

ETAS工具导入DBC生成Com协议栈

文章目录 前言DBC配置关键属性Cobra参数配置Cobra使用isolar工程配置总结前言 ETAS工具导入DBC主要也是生成arxml用的,ETAS推荐使用Cobra导入,本文介绍导入过程及注意事项 DBC配置关键属性 对于普通Com报文,配置为周期发送,及其周期,NmMessage配置为No,示例如下: 对…...

表单校验规则

这里简单记录下vue使用表单时候&#xff0c;给表单添加校验规则&#xff0c;直接上代码 <script setup>import { ref } from vue// 定义表单对象const form ref({account: ,password: ,agree: true})// 定义表单验证规则const rules {account: [{required: true, mess…...

接口的扩展

1. 接口中新增的方法 JDK7之前接口中只能定义抽象方法。 JDK8的新特性&#xff1a;接口中可以定义有方法体的方法。&#xff08;默认、静态&#xff09; JDK9的新特性&#xff1a;接口中可以定义有私有方法体的方法。 有方法体的方法&#xff1a;接口升级时&#xff0c;为了兼容…...

新能源电机轴承电腐蚀,如何破?

近年来&#xff0c;随着全球范围内对可再生能源的重视与推动&#xff0c;新能源电机作为新能源汽车、风力发电和太阳能发电等系统的重要组成部分&#xff0c;得到了迅猛的发展。然而&#xff0c;在实际应用中&#xff0c;新能源电机的维护与管理越来越受到关注&#xff0c;其中…...

Java中的File和IO流

File对象 File对象本质是一个文件或文件夹&#xff0c;用于写入和读取文件内容 注意&#xff1a;对于相对路径而言&#xff0c;在单元测试方法中的File是相对于Module&#xff0c;在main中的File是相对于Project 构造器 File(String pathname)File file1 new File("D:…...

ls命令实操笔记

ls命令&#xff1a;全称list&#xff0c;显示文件的文件名与相关属性。&#xff08;目前工作目录所含之文件及子目录&#xff09; 4567 45678 7891 a1b2 a2b3c abcd Abcd acde aD7E bcde 通过ls浏览上述文件所在的目录&#xff0c;实现以下需求&#xff1a; 浏览含…...

线段数--算法

线段树是常用来维护 区间信息 的数据结构 线段树可以在 O(logN) 的时间复杂度内实现 单点修改区间修改区间查询 区间求和求区间最大值求区间最小值 简单介绍一下线段树 线段树是一个将区间内的数不断细分的一种数据结构&#xff0c;也就是一个完全二叉树&#xff0c;用每一…...

JS的DOM操作和事件监听综合练习 (具备三种功能的轮播图案例)

下面是是对dom操作的一个综合练习 下面代码是html的基本骨架&#xff08;没有任何的功能&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" c…...

低温存储开关机问题

问题&#xff1a; 某消费电子产品在进行可靠性实验室&#xff0c;在低温-30C存储两个小时后&#xff0c;上电不开机。在常温25C时&#xff0c;开关机正常。 分析&#xff1a; 1、接串口抓log信息&#xff0c;从打印信息可以看出uboot可以起来&#xff0c;在跑kernel时&#x…...

mysql系列1—mysql架构和协议介绍

背景&#xff1a; 本文开始整理mysql相关的文章&#xff0c;用于收集数据库相关内容&#xff1b;包括mysql架构和存储方式、索引结构和查询优化、数据库锁等内容。思考如何根据具体的业务给出最优的分表规划和表设计、字段选择和索引设计、优化的SQL语句&#xff0c;以及数据库…...

设计模式——模板模式

定义与基本概念 模板模式&#xff08;Template Pattern&#xff09;是一种行为设计模式。它在一个抽象类中定义了一个操作的算法骨架&#xff0c;将一些步骤的实现延迟到具体子类中。这个抽象类就像是一个模板&#xff0c;定义了执行某个流程的基本框架&#xff0c;而具体的细…...

CV22_语义分割基础

1. 常见的分割类型 在计算机视觉领域&#xff0c;根据不同的应用场景和需求&#xff0c;分割任务可以分为几种主要类型。以下是几种常见的分割类型&#xff1a; 语义分割&#xff08;Semantic Segmentation&#xff09;&#xff1a; 语义分割的目标是将图像中的每个像素分配到…...

Dubbo源码解析-Dubbo的线程模型(九)

一、Dubbo线程模型 首先明确一个基本概念&#xff1a;IO 线程和业务线程的区别 IO 线程&#xff1a;配置在netty 连接点的用于处理网络数据的线程&#xff0c;主要处理编解码等直接与网络数据 打交道的事件。 业务线程&#xff1a;用于处理具体业务逻辑的线程&#xff0c;可以…...

【Canvas与标志】圆角三角形生化危险警示标志

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>圆角三角形生化危险警示标志 Draft1</title><style type&qu…...

解决Dcat Admin laravel框架登录报错问题,(blocked:mixed-content)

前言 在使用 Dcat Admin 后台登录时&#xff0c;发生 error 报错&#xff1a;(blocked:mixed-content) xhr VM484:1&#xff0c;浏览器拦截 其实这是浏览器在 HTTPS 页面中尝试加载 HTTP 资源&#xff0c;导致浏览器阻止了这些不安全的请求。 解决 在 .env 文件中添加或修改 AD…...

(三)Sping Boot学习——升级jdk1.8-jdk18

1.修改系统环境变量。 2.idea中修改配置。 3.项目setting中设置修改 4.更新后还要重新下载依赖mvn clean install &#xff0c;并且记住reload 项目。同时查看java -version查看一下jdk版本。...

语言模型中的多模态链式推理

神经网络的公式推导 简介摘要引言多模态思维链推理的挑战多模态CoT框架多模态CoT模型架构细节编码模块融合模块解码模块 实验结果运行代码补充细节安装包下载Flan-T5数据集准备rougenltkall-MiniLM-L6-v2运行 简介 本文主要对2023一篇论文《Multimodal Chain-of-Thought Reason…...

SCons:下一代构建工具,如何用 Python 驱动高效构建?

在现代软件开发中&#xff0c;构建工具是开发流程中不可或缺的一环。无论是小型项目还是跨平台的复杂工程&#xff0c;选择一个高效、灵活的工具都能显著提高开发效率和代码质量。SCons&#xff0c;一个以 Python 为基础的构建工具&#xff0c;通过自动化依赖管理、灵活的扩展性…...

springboot 整合 rabbitMQ (延迟队列)

前言&#xff1a; 延迟队列是一个内部有序的数据结构&#xff0c;其主要功能体现在其延时特性上。这种队列存储的元素都设定了特定的处理时间&#xff0c;意味着它们需要在规定的时间点或者延迟之后才能被取出并进行相应的处理。简而言之&#xff0c;延时队列被设计用于存放那…...

ES 基本使用与二次封装

概述 基本了解 Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;基于 Apache Lucene 构建。它提供了对海量数据的快速全文搜索、结构化搜索和分析功能&#xff0c;是目前流行的大数据处理工具之一。主要特点即高效搜索、分布式存储、拓展性强 核心功能 全文搜索:…...