有了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,當然了現在這種模式運行下,這裏的數據庫能扛的併發更高一些了,不過這不是代碼上面的問題,是運行模式機制帶來的效果。