Swoole

Redis应用-限流

血红的双手。 提交于 2020-08-18 05:20:15
在高并发场景下有三把利器保护系统:缓存、降级、和限流。缓存的目的是提升系统的访问你速度和增大系统能处理的容量;降级是当服务出问题或影响到核心流程的性能则需要暂时屏蔽掉。而有些场景则需要限制并发请求量,如秒杀、抢购、发帖、评论、恶意爬虫等。 限流算法 常见的限流算法有:计数器,漏桶、令牌桶。 计数器 顾名思义就是来一个记一个,然后判断在有限时间窗口内的数量是否超过限制即可 function isActionAllowed($userId, $action, $period, $maxCount) { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $key = sprintf('hist:%s:%s', $userId, $action); $now = msectime(); # 毫秒时间戳 $pipe=$redis->multi(Redis::PIPELINE); //使用管道提升性能 $pipe->zadd($key, $now, $now); //value 和 score 都使用毫秒时间戳 $pipe->zremrangebyscore($key, 0, $now - $period); //移除时间窗口之前的行为记录,剩下的都是时间窗口内的 $pipe->zcard($key); //获取窗口内的行为数量

Swoole 中使用异步任务

吃可爱长大的小学妹 提交于 2020-08-18 05:20:00
执行异步任务 (Task) # server.php $serv = new Swoole\Server("127.0.0.1", 9501); // 设置异步任务的工作进程数量 $serv->set(array('task_worker_num' => 4)); $serv->on('Connect', function ($serv, $fd) { echo "Client: Connect.\n"; }); // 此回调函数在worker进程中执行 $serv->on('Receive', function ($serv, $fd, $from_id, $data) { $serv->send($fd, "Server: ".$data); // 向 task_worker 进程投递异步任务,程序继续向下执行代码 $task_id = $serv->task($data); echo "Dispatch AsyncTask: id=$task_id\n"; }); $serv->on('Close', function ($serv, $fd) { echo "Client: Close.\n"; }); // 处理异步任务(此回调函数在task进程中执行) // 会将当前进程状态切换为忙碌,不再接收任务;执行完成后切换为空闲,继续接收任务 $serv->on('Task',

PHP操作Redis,记不住多操作几次

感情迁移 提交于 2020-08-18 03:07:43
redis 的基本操作方法 1.redis 的连接 : //实例化redis $redis = new Redis(); //连接 $redis->connect('127.0.0.1', 6379); //检测是否连接成功 echo "Server is running: " . $redis->ping(); // 输出结果 Server is running: +PONG 2.redis 操作 Strng (字符串): // 设置一个字符串的值 $redis->set('cat', 111); //获取一个字符串的值 echo $redis->get('cat'); // 111 // 重复set $redis->set('cat', 222); echo $redis->get('cat'); // 222 3.redis 操作 List (列表): //存储数据到列表中 $redis->lpush('list', 'html'); $redis->lpush('list', 'css'); $redis->lpush('list', 'php'); //获取列表中所有的值 $list = $redis->lrange('list', 0, -1); print_r($list);echo '<br>'; // Array ( [0] => php [1] => css

PHP 多任务秒级定时器的实现方法

戏子无情 提交于 2020-08-17 20:11:20
描述 最近在公司部署crontab的时候,突发奇想是否可以用PHP去实现一个定时器,颗粒度到秒级就好,因为crontab最多到分钟级别,同时也调研了一下用PHP去实现的定时器还真不太多,Swoole 扩展里面到实现了一个毫秒级的定时器很高效,后面写一篇,先用PHP去实现一个定时器类,以供学习参考。 实现 在实现定时器代码的时候,用到了PHP系统自带的两个扩展 Pcntl - 多进程扩展 : 主要就是让PHP可以同时开启很多子进程,并行的去处理一些任务。 Spl - SplMinHeap - 小顶堆 一个小顶堆数据结构,在实现定时器的时候,采用这种结构效率还是不错的,插入、删除的时间复杂度都是 O(logN) ,像 libevent 的定时器也在 1.4 版本以后采用了这种数据结构之前用的是 rbtree,如果要是使用链表或者固定的数组,每次插入、删除可能都需要重新遍历或者排序,还是有一定的性能问题的。 流程 说明 1、定义定时器结构,有什么参数之类的. 2、然后全部注册进我们的定时器类 Timer. 3、调用定时器类的monitor方法,开始进行监听. 4、监听过程就是一个while死循环,不断的去看时间堆的堆顶是否到期了,本来考虑每秒循环看一次,后来一想每秒循环看一次还是有点问题,如果正好在我们sleep(1)的时候定时器有到期的了,那我们就不能马上去精准执行,可能会有延时的风险

PHP 闭包那点事儿

余生颓废 提交于 2020-08-17 17:07:31
匿名函数 匿名函数,也叫闭包函数,说白了就是“没有名字的函数”,和一般函数结构一样,只是少了函数名以及最后需要加上分号 ; 。 注:理论上讲闭包和匿名函数是不同的概念,不过PHP将其视作相同的概念。 $func = function() { echo 'Hello World' . PHP_EOL; }; $func(); 匿名函数和普通函数的区分有: 匿名函数也可以作为变量的值来使用。 匿名函数可以从父作用域继承变量,而这个父作用域是定义该闭包的函数(不一定是调用它的函数)。 $message = 'hello'; $example = function () use ($message) { return $message; }; $message = 'world'; echo $example(); 输出:hello 注意:必须使用 use 关键字将变量传递进去才行,具体见 官方文档 。 闭包类 定义一个闭包函数,其实就是实例化一个闭包类( Closure )对象: $func = function() { echo 'hello world' . PHP_EOL; }; var_dump($func); 输出: object(Closure)#1 (0) { } 类摘要: Closure { __construct ( void ) public static

理解PHP垃圾回收机制

让人想犯罪 __ 提交于 2020-08-17 15:51:30
php的垃圾回收机制可以简单总结为 引用计数 写时复制 COW机制。 引用计数基本知识 官网的解答如下 每个php变量存在一个叫”zval”的变量容器中一个zval变量容器,除了包含变量的类型和值 ,还包括两个字节的额外信息 is_ref 和 refcount is_ref 是个bool值,用来标识这个变量是否是属于引用集合(reference set)。 通过这个字节,php引擎才能把普通变量和引用变量区分开来 refcount 用以表示指向这个zval变量容器的变量个数 PHP5 中的引用计数在PHP5中,zval 的内存是单独从堆(heap)中分配的(有少数例外情况),PHP 需要知道哪些 zval 是正在使用的,哪些是需要释放的。所以这就需要用到引用计数:zval 中 refcount__gc 的值用于保存 zval 本身被引用的次数,比如 b = 12语句中,12 被两个变量引用,所以它的引用计数就是 2。如果引用计数变成 0,就意味着这个变量已经没有用了,内存也就可以释放了。 如下: <?php //php zval变量容器 $a = 1 ; $b = 1 ; $c = & $a ; $d = $b ; $e = range ( 0 , 3 ); xdebug_debug_zval ( 'a' ); xdebug_debug_zval ( 'b' ); xdebug

江娱互动「世界争霸」产品迁移至腾讯云云函数的实践

风流意气都作罢 提交于 2020-08-17 02:56:49
社交,是游戏玩家的一项基本需求,那么,在游戏中,成熟稳定的聊天系统担负着玩家交流的重要使命。 做为一家从不 996 的游戏创业公司,我们的两款产品《世界争霸》和《农场小镇》都在使用自研的聊天系统。随着在线人数逐渐增多,系统的稳定性和成本面临着更多的考验。于是,升级技术栈势在必行。 至此,核心目标已经出现,以保障性能为前提,同时做到省事和省钱。最终,腾讯云的云函数产品进入了我们的视线。 云函数,无需服务器,省去运维烦恼,只需要关注于业务逻辑代码,可谓省事。按量付费,用多少花多少,避免业务低谷期的资源浪费,可谓省钱。非常适合游戏聊天系统 API 这种复杂度低的中小型需求。 那么接下来我们关注的是,现有系统能不能无缝迁移过去,也就是云函数能不能满足目前所有的特定需求,我们一个一个来说。 第一个需求:少改代码 原来的 API 部分是采用 swoole 做为底层扩展,部署在腾讯云的 CVM 上,并使用腾讯云的负载均衡来接收外部请求。代码层面则是使用了 composer 进行包管理,一款开源的 easyswoole 框架做为 http 业务的架子。 换用云函数的方案的话,非代码层面就变成了腾讯云 API 网关加云函数来提供服务,而为了方便,依然需要继续使用 composer 进行包管理。原来基于 swoole 的 http 框架无法继续使用,改代码的重点就在这里。 首先就是逻辑入口

PHP-Swoole操作多进程步骤

爱⌒轻易说出口 提交于 2020-08-16 10:17:48
在以往的开发项目中,要操作进程就会使用PHP自带的 pcntl拓展。但是pcntl存在着许多的不足: pcntl没有提供进程间通信的功能 pcntl不支持重定向标准输入和输出 pcntl只提供了fork这样原始的接口,容易使用错误 这边我们使用swoole进程管理模块,用来替代 PHP 的 pcntl ; 场景:日常任务中,有时需要通过php脚本执行一些日志分析,队列处理等任务,当数据量比较大时,可以使用多进程来处理。 准备: 安装PHP_swoole拓展; write($data)   向管道内写入数据。 $data 的长度在 Linux 系统下最大不超过 8K , MacOS/FreeBSD 下最大不超过 2K start():    执行fork调用,启动子进程。 /** 创建子进程,将数据写入管道,然后启动子进程 */ $process = new \swoole_process([$this, 'sonProcessWork']); $process->write(json_encode($data_pop)); $pid = $process->start(); swoole_event_add():  将一个socket加入到底层的 reactor 事件监听中;在子进程中处理一些耗时的计算或者操作; /** 获取管道的业务数据,进行相关的操作 */ public

PHP的架构及原理概述

邮差的信 提交于 2020-08-15 10:59:16
PHP 的特点 多进程模型 PHP是以多进程模型设计的,这样的好处是请求之间互不干涉,一个请求失败也不会对其他进程造成影响,作为最开始仅仅用于个人网站的一个工具集这样的设计并没有什么不妥,随着PHP的应用变大,访问量增加这种方式显然是不合适的,因为启动一个进程的开销对于海量请求是不划算的,所以现在PHP基本都是运行在PHP-FPM的管理下的,这是一个PHP进程管理器,它常驻内存启动一些PHP进程待命,当请求进入时分配一个进程进行处理,PHP进程处理完毕后回收进程,但并不销毁进程,这让PHP也能应对高流量的访问请求。 当然现在也有PHP多线程的解决方案和基于协程的解决方案,比如swoole让PHP更高效的处理WEB请求。 弱类型 与 JAVA、C/C++ 不同,PHP是一门若类型的语言,变量在声明的那一刻是不需要确定它的类型的,而在运行时类型也会发生显式或隐式的类型改变,这也是PHP开发应用迅速、方便的原因之一。 其他 Zend 引擎 + Ext 扩展 的模式降低了内部耦合,可以方便的为PHP本身增加功能和去除功能。 语法简单,没有太多强制规范,编程风格上既可以用过程式、也可以用面向对象的方式进行开发,当然函数式也可以。 PHP 的架构 以目前的 PHP 主流版本 PHP7 和 PHP5 来说架构是如上图所示,主要有四层体系构成,从下到上依次是 Zend 引擎、Extensions