mirror of
http://124.126.16.154:8888/singularity/hyperf-admin.git
synced 2026-01-15 05:55:08 +08:00
perf: 增加remote module 请求转发模式
This commit is contained in:
@@ -4,4 +4,11 @@
|
|||||||
|
|
||||||
作业必须基于`App\Util\CronCenter\ClassJobAbstract`, 或`App/Util/CronCenter/CommandJobAbstract.php`抽象类进行实现, 才可进行执行状态的跟踪
|
作业必须基于`App\Util\CronCenter\ClassJobAbstract`, 或`App/Util/CronCenter/CommandJobAbstract.php`抽象类进行实现, 才可进行执行状态的跟踪
|
||||||
|
|
||||||
`CronCenter`的实现基于`hyperf-crontab`进行实现, 具体代码在`app/Util/CronCenter`, 更多细节可查看[文档](https://hyperf.wiki/#/zh-cn/crontab)
|
`CronCenter`的实现基于`hyperf-crontab`进行实现, 具体代码在`src/CronCenter`, 更多细节可查看[文档](https://hyperf.wiki/#/zh-cn/crontab)
|
||||||
|
|
||||||
|
开启`cron-center` `config/autoload/crontab.php`
|
||||||
|
```php
|
||||||
|
[
|
||||||
|
"enable" => true
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|||||||
@@ -68,4 +68,20 @@ php bin/hyperf.php
|
|||||||
|
|
||||||
然后将相应的菜单添加到后台即可使用.
|
然后将相应的菜单添加到后台即可使用.
|
||||||
|
|
||||||
!> 这里的组件菜单, 后期可以优化成配置文件导入的方式, 会更简单些
|
!> 这里的组件菜单, 后期可以优化成配置文件导入的方式, 会更简单些
|
||||||
|
|
||||||
|
业务组件的db依赖问题, 参见 `src/cron-center/src/ConfigProvider.php` 中 `databases`
|
||||||
|
|
||||||
|
```php
|
||||||
|
'databases' => [
|
||||||
|
'config_center' => db_complete([
|
||||||
|
'host' => env('CONFIG_CENTER_DB_HOST', env('HYPERF_ADMIN_DB_HOST')),
|
||||||
|
'database' => env('CONFIG_CENTER_DB_NAME', env('HYPERF_ADMIN_DB_NAME')),
|
||||||
|
'username' => env('CONFIG_CENTER_DB_USER', env('HYPERF_ADMIN_DB_USER')),
|
||||||
|
'password' => env('CONFIG_CENTER_DB_PWD', env('HYPERF_ADMIN_DB_PWD')),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
组件可以使用自己单独的库配置, 默认使用 `hyperf_amdin` 的主db配置.
|
||||||
|
|
||||||
|
|||||||
@@ -194,11 +194,9 @@ class MenuController extends AdminAbstractController
|
|||||||
'permission|权限标识' => [
|
'permission|权限标识' => [
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'default' => [],
|
'default' => [],
|
||||||
'options' => function ($field, $data) {
|
|
||||||
return $this->permission_service->getSystemRouteOptions();
|
|
||||||
},
|
|
||||||
'props' => [
|
'props' => [
|
||||||
'multiple' => true,
|
'multiple' => true,
|
||||||
|
'selectApi' => '/system/routes?module={module}'
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'pid|上级类目' => [
|
'pid|上级类目' => [
|
||||||
@@ -272,7 +270,7 @@ class MenuController extends AdminAbstractController
|
|||||||
[
|
[
|
||||||
'text' => '加子菜单',
|
'text' => '加子菜单',
|
||||||
'type' => 'form',
|
'type' => 'form',
|
||||||
'target' => '/menu/form?pid[]={id}&module={tab_id}',
|
'target' => '/menu/form?pid[]={id}&module={module}',
|
||||||
'formUi' => [
|
'formUi' => [
|
||||||
'form' => [
|
'form' => [
|
||||||
'labelWidth' => '80px',
|
'labelWidth' => '80px',
|
||||||
@@ -330,6 +328,7 @@ class MenuController extends AdminAbstractController
|
|||||||
'columns' => [
|
'columns' => [
|
||||||
['field' => 'id', 'hidden' => true],
|
['field' => 'id', 'hidden' => true],
|
||||||
['field' => 'pid', 'hidden' => true],
|
['field' => 'pid', 'hidden' => true],
|
||||||
|
['field' => 'module', 'hidden' => true],
|
||||||
[
|
[
|
||||||
'field' => 'label',
|
'field' => 'label',
|
||||||
'width' => '250px',
|
'width' => '250px',
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace HyperfAdmin\Admin\Controller;
|
namespace HyperfAdmin\Admin\Controller;
|
||||||
|
|
||||||
use HyperfAdmin\Admin\Model\ExportTasks;
|
use Hyperf\Utils\Str;
|
||||||
use HyperfAdmin\Admin\Service\CommonConfig;
|
use HyperfAdmin\Admin\Service\CommonConfig;
|
||||||
use HyperfAdmin\Admin\Service\ExportService;
|
use HyperfAdmin\Admin\Service\ModuleProxy;
|
||||||
use HyperfAdmin\BaseUtils\Constants\ErrorCode;
|
|
||||||
|
|
||||||
class SystemController extends AdminAbstractController
|
class SystemController extends AdminAbstractController
|
||||||
{
|
{
|
||||||
@@ -26,4 +25,19 @@ class SystemController extends AdminAbstractController
|
|||||||
|
|
||||||
return $this->success($config);
|
return $this->success($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function routes()
|
||||||
|
{
|
||||||
|
$module_proxy = make(ModuleProxy::class);
|
||||||
|
if ($module_proxy->needProxy()) {
|
||||||
|
return $this->success($module_proxy->request()['payload']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$kw = $this->request->input('kw', '');
|
||||||
|
$routes = $this->permission_service->getSystemRouteOptions();
|
||||||
|
$routes = array_filter($routes, function ($item) use ($kw) {
|
||||||
|
return Str::contains($item['value'], $kw);
|
||||||
|
});
|
||||||
|
return $this->success(array_values($routes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,25 @@
|
|||||||
*/
|
*/
|
||||||
namespace HyperfAdmin\Admin\Middleware;
|
namespace HyperfAdmin\Admin\Middleware;
|
||||||
|
|
||||||
|
use FastRoute\Dispatcher;
|
||||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||||
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
|
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
|
||||||
use Hyperf\HttpServer\CoreMiddleware;
|
use Hyperf\HttpServer\CoreMiddleware;
|
||||||
|
use Hyperf\HttpServer\Router\Dispatched;
|
||||||
use Hyperf\Logger\LoggerFactory;
|
use Hyperf\Logger\LoggerFactory;
|
||||||
|
use HyperfAdmin\Admin\Service\AuthService;
|
||||||
|
use HyperfAdmin\Admin\Service\CommonConfig;
|
||||||
|
use HyperfAdmin\Admin\Service\ModuleProxy;
|
||||||
|
use HyperfAdmin\Admin\Service\PermissionService;
|
||||||
|
use HyperfAdmin\BaseUtils\AKSK;
|
||||||
|
use HyperfAdmin\BaseUtils\Constants\ErrorCode;
|
||||||
|
use HyperfAdmin\BaseUtils\Guzzle;
|
||||||
|
use HyperfAdmin\BaseUtils\Log;
|
||||||
|
use HyperfAdmin\BaseUtils\Redis\Redis;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use HyperfAdmin\Admin\Service\PermissionService;
|
|
||||||
use HyperfAdmin\Admin\Service\AuthService;
|
|
||||||
use HyperfAdmin\BaseUtils\AKSK;
|
|
||||||
use HyperfAdmin\BaseUtils\Constants\ErrorCode;
|
|
||||||
|
|
||||||
class PermissionMiddleware extends CoreMiddleware
|
class PermissionMiddleware extends CoreMiddleware
|
||||||
{
|
{
|
||||||
@@ -61,6 +68,18 @@ class PermissionMiddleware extends CoreMiddleware
|
|||||||
$uri = $request->getUri();
|
$uri = $request->getUri();
|
||||||
$path = $uri->getPath();
|
$path = $uri->getPath();
|
||||||
$method = $request->getMethod();
|
$method = $request->getMethod();
|
||||||
|
|
||||||
|
$module_proxy = make(ModuleProxy::class);
|
||||||
|
if ($module_proxy->needProxy()) {
|
||||||
|
$res = $module_proxy->request();
|
||||||
|
if(isset($res['payload']) && $res['payload'] === []) {
|
||||||
|
$res['payload'] = (object)[];
|
||||||
|
}
|
||||||
|
$response = $this->response->json($res);
|
||||||
|
Log::get('http')->info('proxy_end', ['module' => $module_proxy->getTargetModule(), 'path' => $path, 'response' => $response]);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
// 其他系统调用,走AKSK中间件验证
|
// 其他系统调用,走AKSK中间件验证
|
||||||
$client_token = $request->getHeader('Authorization')[0] ?? '';
|
$client_token = $request->getHeader('Authorization')[0] ?? '';
|
||||||
if ($client_token) {
|
if ($client_token) {
|
||||||
|
|||||||
52
src/admin/src/Service/ModuleProxy.php
Normal file
52
src/admin/src/Service/ModuleProxy.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace HyperfAdmin\Admin\Service;
|
||||||
|
|
||||||
|
use HyperfAdmin\BaseUtils\Guzzle;
|
||||||
|
use HyperfAdmin\BaseUtils\Redis\Redis;
|
||||||
|
|
||||||
|
class ModuleProxy
|
||||||
|
{
|
||||||
|
protected $request;
|
||||||
|
protected $modules;
|
||||||
|
protected $target_module;
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->request = request();
|
||||||
|
$this->modules = Redis::getOrSet('hyperf_admin:system_modules', 500, function () {
|
||||||
|
$list = CommonConfig::getConfigByName('website_config')['value']['system_module'];
|
||||||
|
array_change_v2k($list, 'name');
|
||||||
|
return $list;
|
||||||
|
});
|
||||||
|
$this->target_module = $this->request->input('module') ?? (request_header('x-module')[0] ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function needProxy()
|
||||||
|
{
|
||||||
|
$no_proxy = request_header('x-no-proxy')[0] ?? false;
|
||||||
|
|
||||||
|
if ($no_proxy) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->modules[$this->target_module])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->modules[$this->target_module]['type'] != 'remote') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function request()
|
||||||
|
{
|
||||||
|
return Guzzle::proxy($this->modules[$this->target_module]['remote_base_uri'] . $this->request->getUri()->getPath(), $this->request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTargetModule()
|
||||||
|
{
|
||||||
|
return $this->target_module;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -243,7 +243,8 @@ class PermissionService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$user_open_apis = $this->getOpenResourceList('user_open_api');
|
$user_open_apis = $this->getOpenResourceList('user_open_api');
|
||||||
return array_merge($resources, $user_open_apis);
|
$system_user_open = config('system.user_open_resource', ['/system/routes']);
|
||||||
|
return array_merge($resources, $user_open_apis, $system_user_open);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOpenResourceList($field = 'open_api')
|
public function getOpenResourceList($field = 'open_api')
|
||||||
|
|||||||
@@ -38,3 +38,4 @@ register_route('/cconf', CommonConfigController::class, function ($controller) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Router::get('/system/config', [SystemController::class, 'config']);
|
Router::get('/system/config', [SystemController::class, 'config']);
|
||||||
|
Router::get('/system/routes', [SystemController::class, 'routes']);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ namespace HyperfAdmin\BaseUtils;
|
|||||||
|
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use Hyperf\Guzzle\ClientFactory;
|
use Hyperf\Guzzle\ClientFactory;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use GuzzleHttp\Cookie\CookieJar;
|
||||||
|
|
||||||
class Guzzle
|
class Guzzle
|
||||||
{
|
{
|
||||||
@@ -76,4 +78,50 @@ class Guzzle
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function proxy($url, ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
$client = self::create([
|
||||||
|
'timeout' => 10.0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$options = [];
|
||||||
|
|
||||||
|
$logger = Log::get('module_proxy');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$options['headers']['X-No-Proxy'] = true;
|
||||||
|
|
||||||
|
$options['headers'] = array_merge($options['headers'], array_map(function ($item) {
|
||||||
|
return $item[0];
|
||||||
|
}, request_header()));
|
||||||
|
|
||||||
|
$parse =parse_url($url);
|
||||||
|
$domain = isset($parse['port']) ? $parse['host'] . ':' . $parse['port'] : $parse['host'];
|
||||||
|
$options['cookies'] = CookieJar::fromArray(cookie(), $domain);
|
||||||
|
|
||||||
|
if ($query = $request->getQueryParams()) {
|
||||||
|
$options['query'] = $query;
|
||||||
|
}
|
||||||
|
if ($body = (array)json_decode($request->getBody()->getContents(), true)) {
|
||||||
|
$options['body'] = \GuzzleHttp\json_encode($body);
|
||||||
|
}
|
||||||
|
if ($form_data = $request->getParsedBody()) {
|
||||||
|
$options['form_params'] = $form_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = retry(3, function () use ($client, $request, $url, $options) {
|
||||||
|
return $client->request($request->getMethod(), $url, $options);
|
||||||
|
}, 50);
|
||||||
|
$content = $request->getBody()->getContents();
|
||||||
|
$logger->info('proxy_success', compact('url', 'options'));
|
||||||
|
return my_json_decode($content);
|
||||||
|
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
|
||||||
|
$logger->error('proxy_fail', compact('url', 'options', 'e'));
|
||||||
|
throw new \Exception("proxy exception {$e}", 500);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$logger->error('proxy_fail', compact('url', 'options', 'e'));
|
||||||
|
throw new \Exception("proxy exception {$e}", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user