Swoole

Swoole 协程性能测试

前提是你 提交于 2020-08-12 05:14:35
// 开启协程化,文件操作,sleep,Mysqli,PDO,streams等都变成异步IO Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]); $s = microtime(true); // 创建协程容器 Co\run(function() { // 开启100个协程执行usleep for ($c = 100; $c--;) { go(function () { for ($n = 100; $n--;) { usleep(1000); } }); } // 开启100个协程执行100次文件读写 for ($c = 100; $c--;) { go(function () use ($c) { $tmp_filename = "/tmp/test-{$c}.php"; for ($n = 100; $n--;) { $self = file_get_contents(__FILE__); file_put_contents($tmp_filename, $self); assert(file_get_contents($tmp_filename) === $self); } unlink($tmp_filename); }); } // 开启50个协程执行100次数据库查询 for ($c = 50; $c--;) { go(function

PHPer需要掌握的php-fpm优化

泄露秘密 提交于 2020-08-11 08:21:52
1.通常情况我们修改/etc/php.ini文件,仅会修改错误日志与文件上传 #;;;;;;;;;;;;;;;;; # Error logging ; #;;;;;;;;;;;;;;;;; expose_php = Off # 关闭php版本信息 display_error = Off # 屏幕不显示错误日志 error_reporting = E_WARNING & E_ERROR # 记录php错误日志至后台 log_errors = On # 开启日志 error_log = /var/log/php_error.log # 错误日志记录的位置 date.timezone = PRC # 时区调整,默认PRC, 建议调整为Asia/Shanghai #;;;;;;;;;;;;;;; # File Uploads ; #;;;;;;;;;;;;;;; file_uploads = On # 开启文件上传功能,默认启动 upload_max_filesize = 300M # 允许上传文件的最大大小 post_max_size = 300M # 允许客户端单个POST请求发送的最大数据 max_file_uploads = 20 # 允许同时上传的文件的最大数量 memory_limit = 128M # 每个脚本执行最大内存 #/etc/php.ini优化配置如下 sql

MySQL多表查询优化

戏子无情 提交于 2020-08-10 16:41:50
一、多表查询连接的选择: 相信这内连接,左连接什么的大家都比较熟悉了,当然还有左外连接什么的,基本用不上我就不贴出来了。这图只是让大家回忆一下,各种连接查询。 然后要告诉大家的是,需要根据查询的情况,想好使用哪种连接方式效率更高。 二、MySQL的JOIN实现原理 在MySQL 中,只有一种Join 算法,就是大名鼎鼎的Nested Loop Join,他没有其他很多数据库所提供的Hash Join,也没有Sort Merge Join。顾名思义,Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join 结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复。 ——摘自《MySQL 性能调优与架构设计》 三、补充:mysql对sql语句的容错问题 即在sql语句不完全符合书写建议的情况,mysql会允许这种情况,尽可能解释它: 1)一般cross join后面加上where条件,但是用cross join+on也是被解释为cross join+where; 2)一般内连接都需要加上on限定条件,如上面场景一;如果不加会被解释为交叉连接; 3)如果连接表格使用的是逗号,会被解释为交叉连接; 注

Swoole 中使用 UDP 异步服务器、UDP 同步客户端、UDP 协程客户端

做~自己de王妃 提交于 2020-08-10 13:22:19
UDP 异步风格服务器 # udp_server.php // 创建 UDP 服务器对象,监听0.0.0.0:9502端口,类型为SWOOLE_SOCK_UDP $serv = new Swoole\Server("0.0.0.0", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); // 设置服务器运行参数 $serv->set(array( 'daemonize' => 1, // 作为守护进程运行,需同时设置log_file 'log_file' => '/www/logs/swoole.log', // 指定标准输出和错误日志文件 )); // 监听数据接收事件 // $clientInfo数组是客户端的相关信息,有客户端的 IP 和端口等内容 $serv->on('Packet', function ($serv, $data, $clientInfo) { // 向客户端发送数据 $serv->sendto($clientInfo['address'], $clientInfo['port'], "Server: " . $data); var_dump($clientInfo); }); // 启动服务器 $serv->start(); 运行并测试 UDP 异步风格服务器 # 如果程序已经运行,先结束进程 kill -9 11591 #

Swoole 中使用 Context 类管理上下文,防止发生数据错乱

╄→гoц情女王★ 提交于 2020-08-09 20:56:51
前面的文章中,我们说过:不能使用类静态变量 Class::$array / 全局变量 global $_array / 全局对象属性 $object->array / 其他超全局变量 $GLOBALS 等保存协程上下文内容,以免发生数据错乱。 那是因为Swoole是常驻内存的,这些全局变量是共享的,在遇到并发请求时,协程A写入的内容可能会因为协程挂起或协程调度被协程B并发修改了,会导致上下文内容不一致。 解决办法是加入一个基于协程 ID 来保存上下文的 Context 类,来隔离不同协程之间的上下文/全局变量,然后在协程退出时清理上下文内容。 use Swoole\Coroutine; class Context { protected static $pool = []; // 基于协程 `ID` 获取数据 static function get($key) { $cid = Coroutine::getCid(); if ($cid < 0) { return null; } if(isset(self::$pool[$cid][$key])){ return self::$pool[$cid][$key]; } return null; } // 基于协程 `ID` 写入数据 static function put($key, $item) { $cid =

PHP5和PHP7取数组元素作动态函数名的差异

廉价感情. 提交于 2020-08-09 15:53:18
在 PHP5 和 PHP7 中通过变量获取函数/方法名执行函数/方法时,可能会由于版本之间不通的解释策略导致相同的代码无法运行。 示例 $a = ['add', 'sub']; class Test {   public function add()   {     echo 1 + 2;   } } $t = new Test(); $t->$a[0](); 上例在 PHP5.6 下可以正常运行,但在 PHP7 下会抛出 Fatal error: Function name must be a string。这是因为 PHP5 下执行$t->$a<a href="">0</a>时,会先执行$a[0],获取元素值,然后执行对象的具体方法。 在 PHP7 下,则会先执行$t->$a,导致抛出错误,中断执行。如需要在 PHP7 下正常执行,需要修改为$t->{$a[0]}()。 具体差异可参考: 以上内容希望帮助到大家, 很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务

MYSQL慢查询和日志

我是研究僧i 提交于 2020-08-09 05:21:50
一、简介 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。 二、参数说明 slow_query_log 慢查询开启状态 slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录) long_query_time 查询超过多少秒才记录 三、设置步骤 1.查看慢查询相关参数 mysql> show variables like 'slow_query%'; +---------------------------+----------------------------------+ | Variable_name | Value | +---------------------------+----------------------------------+ | slow_query_log | OFF | | slow_query_log_file | /mysql/data/localhost-slow.log | +---------------------------+----------------------------------+ mysql> show variables like 'long_query

Swoole 协程的并发调用及使用示例

家住魔仙堡 提交于 2020-08-08 15:06:08
示例一: 利用通道pop会自动挂起当前协程,等待生产者推送数据的特性,实现并发调用,并在协程完成后组合结果集。 $serv = new Swoole\Http\Server("127.0.0.1", 9503, SWOOLE_BASE); $serv->on('request', function ($req, $resp) { $chan = new Swoole\Coroutine\Channel(2); go(function () use ($chan) { $cli = new Swoole\Coroutine\Http\Client('www.qq.com', 80); $cli->set(['timeout' => 10]); $cli->setHeaders([ 'Host' => "www.qq.com", 'User-Agent' => 'Chrome/49.0.2587.3', 'Accept' => 'text/html,application/xhtml+xml,application/xml', 'Accept-Encoding' => 'gzip', ]); $ret = $cli->get('/'); $chan->push(['www.qq.com' => $cli->body]); }); go(function () use ($chan) {

Redis实现分布式锁与任务队列的思路

落花浮王杯 提交于 2020-08-06 09:22:43
一、正文 大家都知道在天猫、京东、苏宁等等电商网站上有很多秒杀活动,例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时,会迎来一个用户请求的高峰期,会有几十万几百万的并发量,来抢这个手机,在高并发的情形下会对数据库服务器或者是文件服务器应用服务器造成巨大的压力,严重时说不定就宕机了。 另一个问题是,秒杀的东西都是有量的,例如一款手机只有10台的量秒杀,那么,在高并发的情况下,成千上万条数据更新数据库(例如10台的量被人抢一台就会在数据集某些记录下 减1),那次这个时候的先后顺序是很乱的,很容易出现10台的量,抢到的人就不止10个这种严重的问题。那么,以后所说的问题我们该如何去解决呢? 接下来我所分享的技术就可以拿来处理以上的问题: 分布式锁 和 任务队列。 二、实现思路 1.Redis实现分布式锁思路 思路很简单,主要用到的redis函数是setnx(),这个应该是实现分布式锁最主要的函数。首先是将某一任务标识名(这里用Lock:order作为标识名的例子)作为键存到redis里,并为其设个过期时间,如果是还有Lock:order请求过来,先是通过setnx()看看是否能将Lock:order插入到redis里,可以的话就返回true,不可以就返回false。当然,在我的代码里会比这个思路复杂一些,我会在分析代码时进一步说明。 2.Redis实现任务队列

PHP多进程处理tcp连接

二次信任 提交于 2020-08-06 06:29:32
<?php if(($sock = socket_create(AF_INET, SOCK_STREAM, 0)) < 0) { echo "failed to create socket: ".socket_strerror($sock)."n"; exit(); } if(($ret = socket_bind($sock,'127.0.0.1', 8888)) < 0) { echo "failed to bind socket: ".socket_strerror($ret)."n"; exit(); } if( ( $ret = socket_listen( $sock, 0 ) ) < 0 ) { echo "failed to listen to socket: ".socket_strerror($ret)."n"; exit(); } while (true) { $conn = @socket_accept($sock); //子进程 if(pcntl_fork() == 0) { $recv = socket_read($conn, 8192); //处理数据 $send_data = "server: ".$recv; socket_write($conn, $send_data); socket_close($conn); exit(0); } else