拯救php性能的神器webman-数据库
有了webman的这个框架,我们得看看它是怎么使用数据库的,毕竟我们不能一直用内存变量啊。
好,很简单一句话跑起来。
composer require -W illuminate/database illuminate/pagination illuminate/events symfony/var-dumper
官方对于这里数据库的解释是: webman数据库默认采用的是 illuminate/database,也就是laravel的数据库,用法与laravel相同。
当然你可以参考使用其它数据库组件章节使用ThinkPHP或者其它数据库。
执行结果
这上面的命令执行了一大堆东西,如果不需要分页、数据库事件、打印SQL,则只需要执行
composer require -W illuminate/database
好,这里我们就按最完整的来,安装一大堆东西,看看该怎么用。
1. 配置数据库链接信息
先配置一下数据库信息,在 config/database.php 里面看看代码
它默认是这样的
我们先到数据库里面去建立一个库 create database webman charset utf8mb4;
然后创建一个users表
CREATE TABLE `users` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `username` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名', `password` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码', `mobile` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '手机', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0禁用/1启动', `last_login_time` int unsigned NOT NULL DEFAULT '0' COMMENT '上次登录时间', `last_login_ip` char(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '上次登录IP', `login_count` int NOT NULL DEFAULT '0' COMMENT '登录次数', `create_time` int unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', `update_time` int unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', PRIMARY KEY (`id`), KEY `usermame_idx` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='会员表';
最后搞个100万数据进去
然后就是这样的
好了,数据库有了,表也有了,然后配置这边就需要改一下。
我这数据库密码也是root,你自己的要改一下
然后就尝试着写点代码,连接一下数据库。
2. 连接数据库并发送查询
在IndexController.php 文件同级目录下新建一个UsersController.php
代码如下:
<?php namespace app\controller; use support\Request; use support\Db; class UsersController { public function index(Request $request) { $default_id = 29; $uid = $request->get('id', $default_id); $name = Db::table('users')->where('id', $uid)->value('username'); return response("hello $name"); } }
然后把服务开起来。
好,现在访问 http://127.0.0.1:8787/users/index 得到结果
好了,现在对比一下跟我们数据库中的是不是一样的。
可以看到确实一样。
3. 根据参数动态查询
随便改改参数,访问发现 http://127.0.0.1:8787/users/index?id=527
数据变了,说明用到了我们传递的参数527,看看数据库里面的是不是一样。
果然一样。好的,那么我们就完成了最简单的一个数据查询。
4. 新增
新增就比较简单,实际上这些ORM的语法基本上都类似
Db::table('users')->insert( ['username' => '姓名', 'password' => '密码'] );
新增多条
Db::table('users')->insert([ ['username' => '姓名2', 'password' => '密码1'], ['username' => '姓名1', 'password' => '密码2'] ]);
这里我们就不再举例了,实在是太简单了,就像小学暑假作业后面的答案略一样。唯一注意一点返回自增id 可以用 insertGetId
Db::table('users')->insertGetId( ['username' => '姓名', 'password' => '密码'] );
5. 修改
修改的语法也差不多
$affected = Db::table('users')->where('id', 1)->update(['status' => 1]);
根据某些条件,更新某些字段,ORM基本通用都这样写。
有个亮点就是它实现了一个新增或者修改
Db::table('users')->updateOrInsert( ['username' => '用户名'], ['status' => '0'] );
updateOrInsert 方法将首先尝试使用第一个参数的键和值对来查找匹配的数据库记录。 如果记录存在,则使用第二个参数中的值去更新记录。 如果找不到记录,将插入一个新记录,新记录的数据是两个数组的集合。
6. 删除
删除的ORM就很简单
Db::table('users')->where('id', '=', 100)->delete();
你要是想清空表的话,就用 truncate。这么写
Db::table('users')->truncate();
5.请求压力测试
好,我们现在根据这种简单的查询来尝试给它上点强度,
首先把代码改为这样,让它每次都动态的随机获取一条数据,避免数据库层面的缓存。
然后还是用我们的 ddosify 来发起请求。
老规矩,先来5000个。
不错,再来点强度!来2万个请求!
好了出现了一点点问题,1个请求是400,再上更大的强度!来5万个请求!
可以看到这个问题感觉明显了,可以看到这里的提示是 socket: too many open files
感觉这个需要查一下是怎么回事,于是我就去搜索了一下,发现这里说的files实际上不是指文件而是指句柄,我们链接的数据库也算句柄。查到的说法也是让我们改一下这里的限制,感觉大家写的都不太深入,没有讲清楚到底为什么会出现这个问题。
那么我们就按最终的解决方法配置一下看看。
先用 ulimit -a 看一下结果
我注意到了这一行 Maximum number of open file descriptors (-n) 1024
说明只让我打开1024个,那我就改一下
操作如下:
我先用 ulimit -n 设置最大能打开 65535 个句柄,再用 ulimit -a 看一下配置。当然我这里是临时在命令行里面修改,只会临时生效,如果你想永久生效,要改这里的文件 /etc/security/limits.conf
加两行
* soft nofile 65535 * hard nofile 65535
之后我们再发起5万个请求看看效果:
好,你看看,5万个请求扛住了,再往上看看呢?它的极限在哪儿呢?
直接怼到10万请求!好家伙,站起来蹬是吧?
一看,嗯,遇到了点问题,出现了1个400的请求。
感觉这样测好像不是很合理,我想了想,还是换成持续5秒请求,共发起50万个,再试试看
总体来讲还是不错的,虽然出现了这样几十个错误。
好,现在我们想办法将这个数据用缓存来加载。
代码如下:
再次请求,5秒内持续50万个请求看看:
ok,效果不错,看来还是静态缓存能扛事儿啊!
好了,关于数据库的我们就讲到这里,这实在是没什么很深入的东西可说的,毕竟这是大家都通用的ORM,当然了现在这种模式运行下,这里的数据库能扛的并发更高一些了,不过这不是代码上面的问题,是运行模式机制带来的效果。