perf: 优化初始化数据

This commit is contained in:
kuaifan 2024-11-11 22:44:18 +08:00
parent 6fda0bd548
commit 0c70613865
13 changed files with 487 additions and 222 deletions

View File

@ -1,27 +0,0 @@
<?php
namespace App\Events;
use Hhxsv5\LaravelS\Swoole\Events\ServerStartInterface;
use Swoole\Http\Server;
class ServerStartEvent implements ServerStartInterface
{
public function __construct()
{
}
public function handle(Server $server)
{
$server->startMsecTime = $this->msecTime();
}
private function msecTime()
{
list($msec, $sec) = explode(' ', microtime());
$time = explode(".", $sec . ($msec * 1000));
return $time[0];
}
}

View File

@ -17,8 +17,15 @@ class WorkerStartEvent implements WorkerStartInterface
public function handle(Server $server, $workerId)
{
if (isset($server->startMsecTime) && Cache::get("swooleServerStartMsecTime") != $server->startMsecTime) {
Cache::forever("swooleServerStartMsecTime", $server->startMsecTime);
// 仅在Worker进程启动时执行一次初始化代码
$initTable = app('swoole')->initFlagTable;
if ($initTable->incr('init_flag', 'value') === 1) {
$this->handleFirstWorkerTasks();
}
}
private function handleFirstWorkerTasks()
{
WebSocket::query()->delete();
//
$all = Base::json2array(Cache::get("User::online:all"));
@ -27,4 +34,3 @@ class WorkerStartEvent implements WorkerStartInterface
}
}
}
}

View File

@ -2107,8 +2107,6 @@ class UsersController extends AbstractController
{
$user = User::auth();
//
global $_A;
if (!isset($_A["__annual__report_".$user->userid])) {
$year = '2023';
$time = '2300-01-01 00:00:01';
$prefix = \DB::getTablePrefix();
@ -2194,7 +2192,7 @@ class UsersController extends AbstractController
->first();
//
$_A["__annual__report_".$user->userid] = [
$data = [
// 本人信息
'user' => [
'userid' => $user->userid,
@ -2259,8 +2257,7 @@ class UsersController extends AbstractController
->get()
]
];
}
//
return Base::retSuccess('success', $_A["__annual__report_".$user->userid]);
return Base::retSuccess('success', $data);
}
}

View File

@ -5,6 +5,7 @@ namespace App\Http\Middleware;
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
use App\Module\Doo;
use App\Services\RequestContext;
use Closure;
class WebApi
@ -18,11 +19,14 @@ class WebApi
*/
public function handle($request, Closure $next)
{
global $_A;
$_A = [];
// 为每个请求生成唯一ID
$request->requestId = RequestContext::generateRequestId();
RequestContext::set('start_time', microtime(true));
// 加载Doo类
Doo::load();
// 解密请求内容
$encrypt = Doo::pgpParseStr($request->header('encrypt'));
if ($request->isMethod('post')) {
$version = $request->header('version');
@ -47,6 +51,7 @@ class WebApi
$request->setTrustedProxies([$request->getClientIp()], $request::HEADER_X_FORWARDED_PROTO);
}
// 执行下一个中间件
$response = $next($request);
// 加密返回内容
@ -57,6 +62,16 @@ class WebApi
}
}
// 返回响应
return $response;
}
/**
* @return void
*/
public function terminate()
{
// 请求结束后清理上下文
RequestContext::clear();
}
}

View File

@ -6,6 +6,7 @@ namespace App\Models;
use App\Exceptions\ApiException;
use App\Module\Base;
use App\Module\Doo;
use App\Services\RequestContext;
use Cache;
use Carbon\Carbon;
use Request;
@ -435,9 +436,8 @@ class User extends AbstractModel
*/
private static function authInfo()
{
global $_A;
if (isset($_A["__static_auth"])) {
return $_A["__static_auth"];
if (RequestContext::has('auth')) {
return RequestContext::get('auth');
}
if (Doo::userId() > 0
&& !Doo::userExpired()
@ -459,9 +459,9 @@ class User extends AbstractModel
$user->updateInstance($upArray);
$user->save();
}
return $_A["__static_auth"] = $user;
return RequestContext::save('auth', $user);
}
return $_A["__static_auth"] = false;
return RequestContext::save('auth', false);
}
/**
@ -497,20 +497,19 @@ class User extends AbstractModel
*/
public static function userid2basic($userid, $addField = [])
{
global $_A;
if (empty($userid)) {
return null;
}
$userid = intval($userid);
if (isset($_A["__static_userid2basic_" . $userid])) {
return $_A["__static_userid2basic_" . $userid];
if (RequestContext::has("userid2basic_" . $userid)) {
return RequestContext::get("userid2basic_" . $userid);
}
$userInfo = self::whereUserid($userid)->select(array_merge(User::$basicField, $addField))->first();
if ($userInfo) {
$userInfo->online = $userInfo->getOnlineStatus();
$userInfo->department_name = $userInfo->getDepartmentName();
}
return $_A["__static_userid2basic_" . $userid] = ($userInfo ?: []);
return RequestContext::save("userid2basic_" . $userid, $userInfo ?: []);
}

View File

@ -284,7 +284,7 @@ class UserBot extends AbstractModel
];
}
} elseif (preg_match('/^(manual|locat|face|checkin)-(\d+)$/i', $mac, $match)) {
$type = strtolower(str_replace('checkin', 'face', $match[1]));
$type = str_replace('checkin', 'face', strtolower($match[1]));
$mac = intval($match[2]);
$remark = match ($type) {
'manual' => $setting['manual_remark'] ?: 'Manual',

View File

@ -5,6 +5,7 @@ namespace App\Module;
use App\Exceptions\ApiException;
use App\Models\Setting;
use App\Models\Tmp;
use App\Services\RequestContext;
use Cache;
use Carbon\Carbon;
use League\CommonMark\CommonMarkConverter;
@ -125,11 +126,10 @@ class Base
*/
public static function getClientVersion()
{
global $_A;
if (!isset($_A["__static_client_version"])) {
$_A["__static_client_version"] = self::headerOrInput('version') ?: '0.0.1';
if (RequestContext::has('client_version')) {
return RequestContext::get('client_version');
}
return $_A["__static_client_version"];
return RequestContext::save('client_version', self::headerOrInput('version') ?: '0.0.1');
}
/**
@ -757,7 +757,6 @@ class Base
*/
public static function fillUrl($str = '')
{
global $_A;
if (is_array($str)) {
foreach ($str as $key => $item) {
$str[$key] = Base::fillUrl($item);
@ -776,7 +775,7 @@ class Base
) {
return $str;
} else {
if ($_A['__fill_url_remote_url'] === true) {
if (RequestContext::has('fill_url_remote_url')) {
return "{{RemoteURL}}" . $str;
}
try {
@ -1298,12 +1297,11 @@ class Base
*/
public static function setting($setname, $array = false, $isUpdate = false)
{
global $_A;
if (empty($setname)) {
return [];
}
if ($array === false && isset($_A["__static_setting_" . $setname])) {
return $_A["__static_setting_" . $setname];
if ($array === false && RequestContext::has('setting_' . $setname)) {
return RequestContext::get('setting_' . $setname);
}
$setting = [];
$row = Setting::whereName($setname)->first();
@ -1322,8 +1320,7 @@ class Base
$row->updateInstance(['setting' => $setting]);
$row->save();
}
$_A["__static_setting_" . $setname] = $setting;
return $setting;
return RequestContext::save('setting_' . $setname, $setting);
}
/**
@ -1739,16 +1736,11 @@ class Base
/**
* 获取时间戳
* @param bool $refresh
* @return int
*/
public static function time($refresh = false)
public static function time()
{
global $_A;
if (!isset($_A["__static_time"]) || $refresh === true) {
$_A["__static_time"] = time();
}
return $_A["__static_time"];
return intval(RequestContext::get("start_time", time()));
}
/**
@ -1833,8 +1825,9 @@ class Base
*/
public static function getIp()
{
global $_A;
if (!isset($_A["__static_ip"])) {
if (RequestContext::has("static_ip")) {
return RequestContext::get("static_ip");
}
if (getenv('HTTP_CLIENT_IP') and strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$onlineip = getenv('HTTP_CLIENT_IP');
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) and $_SERVER['HTTP_CLIENT_IP'] and strcasecmp($_SERVER['HTTP_CLIENT_IP'], 'unknown')) {
@ -1853,9 +1846,7 @@ class Base
$onlineip = '0,0,0,0';
}
preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/", $onlineip, $match);
$_A["__static_ip"] = $match ? ($match[0] ?: 'unknown') : '';
}
return $_A["__static_ip"];
return RequestContext::save("static_ip", $match ? ($match[0] ?: 'unknown') : '');
}
/**

View File

@ -0,0 +1,86 @@
<?php
namespace App\Module\Table;
use ReflectionClass;
use Swoole\Table;
abstract class AbstractData
{
/** @var self */
protected static $instance = null;
/** @var Table */
protected $table;
protected function getTableName(): string
{
$className = (new ReflectionClass(static::class))->getShortName();
return lcfirst($className) . 'Table';
}
private function __clone() {}
private function __wakeup() {}
protected function __construct()
{
$this->table = app('swoole')->{$this->getTableName()};
}
public function getTable()
{
return $this->table;
}
public static function instance()
{
if (static::$instance === null) {
static::$instance = new static();
}
return static::$instance;
}
public static function set($key, $value)
{
return self::instance()->table->set($key, ['value' => $value]);
}
public static function get($key, $default = null)
{
$data = self::instance()->table->get($key);
return $data ? $data['value'] : $default;
}
public static function del($key)
{
return self::instance()->table->del($key);
}
public static function exist($key)
{
return self::instance()->table->exist($key);
}
public static function setMultiple(array $items)
{
foreach ($items as $key => $value) {
self::set($key, $value);
}
}
public static function clear()
{
foreach (self::instance()->table as $key => $row) {
self::del($key);
}
}
public static function getAll()
{
$result = [];
foreach (self::instance()->table as $key => $row) {
$result[$key] = $row['value'];
}
return $result;
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace App\Module\Table;
class GlobalData extends AbstractData
{
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Module\Table;
class OnlineData extends AbstractData
{
public static function incr($userid)
{
$key = "online::" . $userid;
$value = intval(self::get($key, 0));
self::set($key, ++$value);
return $value;
}
public static function decr($userid)
{
$key = "online::" . $userid;
$value = intval(self::get($key, 0));
self::set($key, --$value);
return $value;
}
}

View File

@ -0,0 +1,142 @@
<?php
namespace App\Services;
use Illuminate\Http\Request;
class RequestContext
{
/** @var array<string, array<string, mixed>> */
private static array $context = [];
private const REQUEST_ID_PREFIX = 'req_';
/**
* 生成请求唯一ID
*/
public static function generateRequestId(): string
{
return self::REQUEST_ID_PREFIX . uniqid() . mt_rand(10000, 99999);
}
/**
* 获取当前请求ID
*/
private static function getCurrentRequestId(): ?string
{
/** @var Request $request */
$request = request();
return $request?->requestId;
}
/**
* 设置请求上下文
*
* @param string $key
* @param mixed $value
* @param string|null $requestId
* @return void
*/
public static function set(string $key, mixed $value, ?string $requestId = null): void
{
$requestId = $requestId ?? self::getCurrentRequestId();
if ($requestId === null) {
return;
}
self::$context[$requestId] ??= [];
self::$context[$requestId][$key] = $value;
}
// 与 set 方法的区别是save 方法会返回传入的 value 值
public static function save(string $key, mixed $value, ?string $requestId = null): mixed
{
self::set($key, $value, $requestId);
return $value;
}
/**
* 获取请求上下文
*
* @param string $key
* @param mixed $default
* @param string|null $requestId
* @return mixed
*/
public static function get(string $key, mixed $default = null, ?string $requestId = null): mixed
{
$requestId = $requestId ?? self::getCurrentRequestId();
if ($requestId === null) {
return $default;
}
return self::$context[$requestId][$key] ?? $default;
}
/**
* 判断请求上下文是否存在
*
* @param string $key
* @param string|null $requestId
* @return bool
*/
public static function has(string $key, ?string $requestId = null): bool
{
$requestId = $requestId ?? self::getCurrentRequestId();
if ($requestId === null) {
return false;
}
return isset(self::$context[$requestId][$key]);
}
/**
* 清理请求上下文
*
* @param string|null $requestId
* @return void
*/
public static function clear(?string $requestId = null): void
{
$requestId = $requestId ?? self::getCurrentRequestId();
if ($requestId === null) {
return;
}
unset(self::$context[$requestId]);
}
/**
* 获取当前请求的所有上下文数据
*
* @param string|null $requestId
* @return array<string, mixed>
*/
public static function getAll(?string $requestId = null): array
{
$requestId = $requestId ?? self::getCurrentRequestId();
if ($requestId === null) {
return [];
}
return self::$context[$requestId] ?? [];
}
/**
* 批量设置上下文数据
*
* @param array<string, mixed> $data
* @param string|null $requestId
* @return void
*/
public static function setMultiple(array $data, ?string $requestId = null): void
{
$requestId = $requestId ?? self::getCurrentRequestId();
if ($requestId === null) {
return;
}
self::$context[$requestId] ??= [];
self::$context[$requestId] = array_merge(self::$context[$requestId], $data);
}
}

View File

@ -10,6 +10,7 @@ use App\Models\WebSocketDialogMsg;
use App\Models\WebSocketDialogMsgRead;
use App\Module\Base;
use App\Module\Doo;
use App\Services\RequestContext;
use Carbon\Carbon;
use Hhxsv5\LaravelS\Swoole\Task\Task;
use Request;
@ -78,11 +79,7 @@ class WebSocketDialogMsgTask extends AbstractTask
public function start()
{
global $_A;
$_A = [
'__fill_url_remote_url' => true,
];
RequestContext::set('fill_url_remote_url', true);
//
$msg = WebSocketDialogMsg::find($this->id);
if (empty($msg)) {

View File

@ -134,7 +134,6 @@ return [
*/
'event_handlers' => [
'ServerStart' => \App\Events\ServerStartEvent::class,
'WorkerStart' => \App\Events\WorkerStartEvent::class,
],
@ -222,7 +221,38 @@ return [
|
*/
'swoole_tables' => [],
'swoole_tables' => [
'initFlag' => [
'size' => 1,
'column' => [
[
'name' => 'value',
'type' => \Swoole\Table::TYPE_INT,
'size' => 8
],
],
],
'globalData' => [
'size' => 1024,
'column' => [
[
'name' => 'value',
'type' => \Swoole\Table::TYPE_STRING,
'size' => 1024
],
],
],
'onlineData' => [
'size' => 10240,
'column' => [
[
'name' => 'value',
'type' => \Swoole\Table::TYPE_INT,
'size' => 8
],
],
],
],
/*
|--------------------------------------------------------------------------