我這里類似于sass結(jié)構(gòu)的 框架使用的webman 數(shù)據(jù)庫(kù)使用的mysql8.0+thinkorm連接
業(yè)務(wù)需要:數(shù)據(jù)庫(kù)是根據(jù)每家商戶進(jìn)行分庫(kù)存儲(chǔ)的,通過(guò)中間件進(jìn)行數(shù)據(jù)庫(kù)動(dòng)態(tài)切換連接。
現(xiàn)在動(dòng)態(tài)連接各方面訪問(wèn)都沒(méi)有問(wèn)題,但是數(shù)據(jù)庫(kù)連接量一直遞增,目前已經(jīng)跑到了1000多。一直擔(dān)心奔潰的問(wèn)題
我在中間件中使用動(dòng)態(tài)連接,自動(dòng)切換數(shù)據(jù)庫(kù)連接代碼如下
public function process(Request $request, callable $handler): Response
{
//請(qǐng)求控制器白名單,不能進(jìn)行數(shù)據(jù)庫(kù)模型操作,只用于回調(diào)接收數(shù)據(jù)
$whiteController = Config::get('white_api_secret.white_controller');
$controller = $request->controller;
if (in_array($controller, $whiteController)) {
$merchant_id = 0;
} else {
// 獲取商戶ID
$merchant_id = $request->header('X-Merchant-ID');
}
// 檢查商戶ID是否有效
if (!isset($merchant_id) || !is_numeric($merchant_id)) {
return json(['code' => 400, 'msg' => 'Invalid merchant ID!']);
}
// 非法
if ($merchant_id < 0) {
return json(['code' => 400, 'msg' => 'Invalid merchant ID!']);
}
// 將當(dāng)前商戶的數(shù)據(jù)庫(kù)配置存儲(chǔ)在全局變量中
global $merchant_dbs;
// 等于0 屬于碩昆平臺(tái)端連接
if ($merchant_id == 0) {
$merchant_dbs[$merchant_id] = Config::get('thinkorm');
// 初始化數(shù)據(jù)庫(kù)連接
Db::setConfig(Config::get('thinkorm'));
Db::connect('mysql');
}
// 商戶連接
if ($merchant_id > 0) {
$merchantInfoDb = $this->selectDbShopConfig($merchant_id);
if (!is_array($merchantInfoDb)) {
return $merchantInfoDb;
}
$merchant_dbs[$merchant_id] = $merchantInfoDb;
}
# 獲取當(dāng)前商戶的數(shù)據(jù)庫(kù)配置
$db_config = Config::get('thinkorm');
# 檢查當(dāng)前商戶是否有對(duì)應(yīng)的數(shù)據(jù)庫(kù)配置
if (!$db_config) {
return json(['code' => 400, 'msg' => 'Database configuration not found for the merchant!']);
}
# 如果不存在直接退出
if (!isset($merchant_dbs[$merchant_id])) {
return json(['code' => 400, 'msg' => 'Database $merchant_id not save global!']);
}
if ($merchant_id > 0) {
# 動(dòng)態(tài)設(shè)置數(shù)據(jù)庫(kù)
Db::setConfig($merchant_dbs[$merchant_id]);
# 動(dòng)態(tài)連接數(shù)據(jù)庫(kù)
Db::connect('merchant' . $merchant_id);
}
return $handler($request);
}
這是中間件中所執(zhí)行的動(dòng)態(tài)切換 也就是根據(jù)商戶的id進(jìn)行切換到指定的庫(kù)。我發(fā)現(xiàn)這樣使用連接量大量的sleep
你這是搞復(fù)雜化了吧!建議看看
【SaaS多租戶架構(gòu)數(shù)據(jù)源動(dòng)態(tài)切換解決方案】
https://mp.weixin.qq.com/s/RszdlEXlyDIzv6Bn0xNl7g
大佬 其實(shí)和這個(gè)思路是一樣的 我當(dāng)時(shí)不想再模型中寫入相關(guān)的數(shù)據(jù)庫(kù)切換操作 在中間件直接去做的調(diào)用 但是每次進(jìn)入接口都會(huì)重新連接 導(dǎo)致這種問(wèn)題了 目前看看怎么改動(dòng)量最小 感謝大佬
@Tinywan 文章看了,切換是沒(méi)有問(wèn)題的,問(wèn)題是預(yù)定義數(shù)據(jù)庫(kù)配置是寫死的,而不是動(dòng)態(tài)添加的,還有一點(diǎn)是配置了多個(gè),會(huì)導(dǎo)致項(xiàng)目啟動(dòng)時(shí)候就會(huì)有很多的鏈接存在,比如200個(gè)租戶,即使是4個(gè)進(jìn)程,就會(huì)有800個(gè)鏈接存在
@doit 大佬有什么不同的看法 他這么做其實(shí)最后是我一樣的。我現(xiàn)在是一樣的問(wèn)題,切換還是會(huì)存在大量sleep,哪怕是調(diào)用完成close也還是無(wú)效
mysql的連接數(shù)量是有限制的啊,多個(gè)租戶多個(gè)進(jìn)程,最終會(huì)導(dǎo)致mysql連接數(shù)占用完,還有就是消耗資源啊。。。
DB::connect 連接和它本身內(nèi)置的切換數(shù)據(jù)庫(kù)是 同理啊 你說(shuō)的多個(gè)進(jìn)程是指webman的啟用的進(jìn)程數(shù)嗎
復(fù)用一個(gè)數(shù)據(jù)庫(kù)連接,操作數(shù)據(jù)庫(kù)前用use 數(shù)據(jù)庫(kù)
語(yǔ)句切換數(shù)據(jù)庫(kù)。切換時(shí)機(jī)可以在中間件里自動(dòng)切換吧