我還是希望群主能想辦法,把這個action-hook應該改為 全局中間件->用戶應用中間件->路由中間件-> action-hook中間件->控制器的某個方法,就想__consturct一樣,但是我又不想 關閉 控制器復用模式,
<?php
return [
'' => [
\app\middleware\AccessOptionRequestMiddleware::class
],
'app_admin'=>[
\app\app_admin\MiddlewareAppAdmin::class
],
'app_user'=>[
\app\app_user\MiddlewareAppUser::class
],
];
<?php
namespace app\app_admin;
use app\api\service\JwtService;
use app\api\service\ResponseJson;
use app\ConstMap\HttpStatusConst;
use app\ConstMap\JwtConst;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
class MiddlewareAppAdmin implements MiddlewareInterface
{
public function process(Request $request, callable $handler): Response
{
return \response('不執(zhí)行這里');
}
}
<?php
namespace app\app_admin\controller;
use app\model\Recharge;
use app\model\Users;
use support\Request;
use Webman\View;
class AdminDashboard
{
public function beforeAction(Request $request){
var_dump('111');
// \support\View::assign('username',Users::where('uid',$request->jwt->uid)->value('username'));
}
}
var_dump(111);
\response('不執(zhí)行這里');
docker
你會不會url訪問錯了?
我已經找到原因了,因為 action-hook插件會注冊,全局中間件,我自己的應用中間件是后執(zhí)行的,應用中間件里我加了$request->jwt 變量傳遞,action-hook先執(zhí)行 public function beforeAction當然就報錯了。
我還是希望群主能想辦法,把這個action-hook應該改為 全局中間件->用戶應用中間件->路由中間件-> action-hook中間件->控制器的某個方法,就想__consturct一樣,但是我又不想 開啟 控制器復用模式
action-hook插件時為了解決控制器復用時__consturct無法執(zhí)行問題。目前webman已經支持關閉復用控制器了,action-hook已經不推薦用了,推薦關閉控制器復用,使用__consturct。
為了給過時的action-hook插件開綠燈更改內核不是好主意。
如果關閉了復用控制器,會導致 每次都new std(),因為靜態(tài)變量持久化內存的特性,現在的代碼都是把一些 從數據庫讀取的信息 永久儲存在 控制器靜態(tài)變量中。
目前我手動在/config/action-hook/app.php 中關閉了enable,并且人工在 /config/middleware.php中注冊順序。
我目前就是有個疑問,在composer install的時候,會不會更改或覆蓋 /config/action-hook/app.php 文件
@admin 我后來升級到最新,也是想關閉控制器復用,碰到的問題和你一樣,所以還是用action-hook。同時,我想問一下,假如,兩4個進程,是不是就有4個控制器常駐內存?也就是控制器里的靜態(tài)變量也有四份?
需要持久保存的數據放在靜態(tài)屬性里,然后關閉控制器復用。這樣即持久化保存了數據,又能每個請求自動調用__construct()初始化控制器實例??刂破黛o態(tài)屬性保存數據和關閉控制器復用沒有沖突。
控制器復用,直接取消了更好。
復用的時候需要在請求結束處理里面的用戶數據,省內存和避免程序bug導致數據被下一個用戶拿到。
但是如果復用但是不在里面存數據,那復用也沒多大用,就是節(jié)省了new 的開銷。
開啟控制器復用,控制器里面可以存一些公共數據,公共數據不需要請求結束時處理,這樣沒任何問題。
如果需要控制器存當前請求狀態(tài)數據,每次請求后需要清理,所以這種情況還是不開的好。
不要小看這個new開銷,關閉控制器復用,helloworld壓力測試QPS降低20-30%左右,帶數據庫業(yè)務性能降低10%左右。
公共數據沒必要存控制器,單獨弄一個類,搞靜態(tài)屬性。不然浪費內存,每個控制器4份,然后幾十上百個控制器。
難道 你單獨的靜態(tài)類 不是4份? 不是每個進程一份?難道是每個進程用同一份?那怎么沒做鎖呢
你說的是靜態(tài)屬性,那掛任何類上都是一樣的,包括控制器。既然是靜態(tài)屬性,就跟new不new無關。
protected static $Val1;//靜態(tài)屬性 份數=進程數,new無關,復用與不復用無區(qū)別
protected $Val2;//非靜態(tài)屬性 份數=進程*控制器數,new相關,復用與不復用有區(qū)別
@喵了個咪
不要小看這個new開銷,關閉控制器復用,helloworld壓力測試QPS降低20-30%左右,帶數據庫業(yè)務性能降低10%左右。
說實在的,一個框架里面要new的東西估計有點多。
如果new一個控制器就有那么大影響,那真的是應該都用靜態(tài)方法了,這樣就不需要new。
設想一下,假如開了控制復用,控制器里面有個helloworld方法。
public function helloworld()
{
$servcice =new \app\common\helloworldService;
$response = $servcice->doSomething();
return $response;
}
你看,開啟復用了,但是每次執(zhí)行都new 了一個\app\common\helloworldService
來處理請求,可能我在doSomething
里面有new了一堆其他東西。
所以new控制器節(jié)省的那點性能,是真實的嗎?估計你的測試就是 return 'helloworld'吧。
除非你要求程序員處理請求的過程中不要new 任何東西,我覺得不現實。
好吧,我把helloworldService
弄成靜態(tài)屬性了,這樣就不用每次都new一次了。
protected static $servcice;
public function __construct()
{
$this->servcice =new \app\common\helloworldService;
}
public function helloworld()
{
$response = $this->servcice->doSomething();
return $response;
}
但是doSomething
仍然不是靜態(tài)的呀,萬一在里面new了其他東西呢?
把helloworldService的doSomething也搞靜態(tài)化?
所以還是那句話:
除非你要求程序員處理請求的過程中不要new 任何東西,我覺得不現實。這個要求有點過分!
@喵了個咪
你節(jié)省的new控制器的那點開銷,只要后面過程中有任何一個new,就被抵消了。
就算你寫的代碼全程靜態(tài)方法靜態(tài)屬性,復用控制器以后不需要重復new任何東西。
但是你不使用composer的東西嗎?
第三方庫里面也許會給你new個東西出來吧!
哈哈,氣不氣呀。
所以我覺得這個框架節(jié)省的應該是類加載的開銷,而不是new的開銷。
我上面表達的觀點是站在框架角度,不要小看這個new開銷。當然你站在分業(yè)務角度,多一個new確實所謂。
關閉控制器復用,webman可以做到一個請求幾乎不new任何東西的。
大部分業(yè)務中節(jié)省一個new確實沒意義,但是站在框架角度,框架因節(jié)省一個new將極限性能提升20-30%意義很大
所以webman框架應該支持控制器復用的功能,你可以關閉它不用,但是不能像你說的直接取消它。
class Somecontroller
{
protected $thing2;
protected static $thing3;
public function __construct()
{
$this->thing2 = new someThing;
if (!static::$thing3) {
static::$thing3 = new someThing;
}
}
public function someFunctin()
{
//方式1,直接new,每次調用此方法都重新new
$thing1 = new someThing;
$response = $thing1->someFunctin();
//方式2,內部屬性,不用每次都new。
$response = $this->thing2->someFunctin();
//方式3,靜態(tài)屬性,不用每次都new。
$response = static::$thing3->someFunctin();
//方式4,使用容器生產實例,應該和3等效吧
$response = $container->make(someThing::class)->someFunctin();
return $response;
}
}
class SomeThing
{
public function someFunctin()
{
//這里用需要用到SomeThing2的someFunctin2
//和上面類似
}
}
class SomeThing2
{
public function someFunctin2()
{
//這里用需要用到SomeThing3的someFunctin3
//和上面類似
}
}
class SomeThing3
{
public function someFunctin3()
{
//這里用需要用到SomeThing4的someFunctin4
//和上面類似
}
}
class SomeThing4
{
//1個請求用到3~4個類不夸張吧
public function someFunctin4()
{
//這里使用了一個composer的東西,超出控制范圍了,它里面可能new了什么東西,我不可能去改它
}
}
整個流程中的幾次方法調用,能做到保持相同的姿勢,不使用[方式1]?
我再重申一遍,我是站在框架角度,框架支持控制器復用減少一次new調用能讓框架極限性能提升20-30%,對于框架而言是值得的,它能提升框架性能上限,不能像你說的取消支持控制器復用功能,我只是表達這個觀點。
至于你自己的業(yè)務怎么怎么調用,不在我的討論范疇。
站在框架的角度,不能只看到性能的提升。
框架底層邏輯是有的區(qū)別,這是可能會產生一些差異的,不能只看到是性能的差異。
在未開啟控制器復用的情況下,如果安裝了action-hook
插件,是會拖慢性能的。
當然,現在修復了,未開啟控制器復用但安裝了action-hook
,不會生效而已也不拖性能。
https://github.com/webman-php/action-hook/pull/2
你要覺得我在裝逼,那也沒辦法。