Compare commits
10 Commits
6a4b97665a
...
e008a8900d
Author | SHA1 | Date | |
---|---|---|---|
e008a8900d | |||
c5150821b9 | |||
b24b9bbd00 | |||
a498fb6267 | |||
9fbff7ccb0 | |||
68f42f3955 | |||
643250b245 | |||
3b198b4212 | |||
1762a0a7b7 | |||
95e81c0f1f |
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,7 +1,3 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
*.log
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
||||
!.gitignore
|
||||
.idea
|
||||
.vscode
|
27
README.md
27
README.md
@ -1,27 +0,0 @@
|
||||
# 基于docker的webman-jsonrpc
|
||||
|
||||
我们在`php:8.1-cli`基础上安装了运行webman必要的一些扩展和开发中常用的扩展,以及composer,制作成`workerman:8.1`镜像,因此在开发环境中不需要再额外配置php环境,直接写业务代码即可。
|
||||
|
||||
## 依赖
|
||||
|
||||
只要系统环境中有docker即可,不需要安装php环境
|
||||
|
||||
## 使用方法
|
||||
|
||||
```sh
|
||||
# 启动
|
||||
./start
|
||||
# composer
|
||||
./composer install
|
||||
./conposer require xxxx
|
||||
```
|
||||
|
||||
## 一些有用的文件
|
||||
|
||||
| 文件 | 作用 | 用法或说明 |
|
||||
|---|---|---|
|
||||
|composer|调起容器中的`composer`命令的shell脚本|`./composer $args...`|
|
||||
|start|调起容器中的`php start.php`命令的shell脚本|`./start`或`./start -d`|
|
||||
|docker-compose.yml|运行容器的编排文件|一般不需要理会这个文件,composer和start脚本都需要依赖这个文件|
|
||||
|docker.conf|定义运行服务的容器名称和使用的镜像版本|注意container_name不要与系统中其他服务的容器重名|
|
||||
|php.ini|映射到容器中的php.ini配置文件|容器中已经安装的扩展都有单独的配置文件,这里不会有体现|
|
@ -7,15 +7,23 @@ SERVER_LISTEN = http://0.0.0.0:7878
|
||||
SERVER_COUNT = cpu_count()
|
||||
MAX_PACKAGE_SIZE = 1024*1024*5
|
||||
|
||||
# monitor进程
|
||||
MONITOR_ENABLED = false
|
||||
|
||||
# jsonrpc客户端配置
|
||||
DEFAULT_RPC_SERVER = tcp://127.0.0.1:8022
|
||||
USER_RPC_SERVER = tcp://127.0.0.1:8022
|
||||
|
||||
# jsonrcp服务配置
|
||||
JSONRPC_ENABLED = true
|
||||
JSONRPC_SERVER_NAME = jsonrpc
|
||||
JSONRPC_SERVER_PORT = 8022
|
||||
JSONRPC_SERVER_LISTEN = JsonNL://0.0.0.0:8022
|
||||
JSONRPC_SERVER_COUNT = cpu_count()
|
||||
|
||||
# REDIS配置
|
||||
REDIS_HOST = 127.0.0.1
|
||||
REDIS_PORT = 6379
|
||||
REDIS_PASSWORD = null
|
||||
REDIS_PASSWORD =
|
||||
REDIS_DATABASE = 0
|
||||
|
||||
# 数据库
|
||||
@ -43,4 +51,3 @@ SQLITE_PREFIX =
|
||||
# log
|
||||
LOG_MAX_FIlES = 30
|
||||
LOG_MAX_FILES_DEBUG = 3
|
||||
LOG_MAX_FIlES_ERROR = 90
|
7
api/.gitignore
vendored
Normal file
7
api/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
*.log
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
92
api/README.md
Normal file
92
api/README.md
Normal file
@ -0,0 +1,92 @@
|
||||
# 基于docker的webman-jsonrpc
|
||||
|
||||
我们在`php:8.1-cli`基础上安装了运行webman必要的一些扩展和开发中常用的扩展,以及composer,制作成`workerman:8.1`镜像,因此在开发环境中不需要再额外配置php环境,直接写业务代码即可。
|
||||
|
||||
## 依赖
|
||||
|
||||
只要系统环境中有docker即可,不需要安装php环境
|
||||
|
||||
## 使用方法
|
||||
|
||||
```sh
|
||||
# composer
|
||||
./composer install
|
||||
./composer require xxxx
|
||||
# 服务控制
|
||||
./server start|restart|stop|status|reload|connections|logs
|
||||
# 自动生成.env.example文件
|
||||
./envexample
|
||||
# 执行其它php命令
|
||||
./php -m
|
||||
./php webman build:bin
|
||||
```
|
||||
|
||||
## 一些有用的文件
|
||||
|
||||
| 文件 | 作用 | 用法或说明 |
|
||||
|---|---|---|
|
||||
|composer|调起容器中的`composer`命令的shell脚本|用法与主机中的compose完全一致,`./composer $args...`|
|
||||
|server|服务控制脚本|`./server`可以查看用法|
|
||||
|php|调起容器中的`php`命令的shell脚本|用法与主机中的php一致,但注意执行`./php start.php start`命令时不要加-d参数|
|
||||
|docker-compose.yml|运行容器的编排文件||
|
||||
|php.ini|映射到容器中的php.ini配置文件|容器中已经安装的扩展都有单独的配置文件,这里不会有体现|
|
||||
|
||||
## 服务端口
|
||||
|
||||
在.env文件中可以定义服务端口,默认情况下docker容器是在host网络下启动的,当然,实际使用中也可以改成端口映射模式。
|
||||
|
||||
## 已安装PHP扩展
|
||||
|
||||
```sh
|
||||
php -m
|
||||
[PHP Modules]
|
||||
Core
|
||||
ctype
|
||||
curl
|
||||
date
|
||||
dom
|
||||
event
|
||||
exif
|
||||
fileinfo
|
||||
filter
|
||||
ftp
|
||||
gd
|
||||
hash
|
||||
iconv
|
||||
json
|
||||
libxml
|
||||
mbstring
|
||||
mysqli
|
||||
mysqlnd
|
||||
openssl
|
||||
pcntl
|
||||
pcre
|
||||
PDO
|
||||
pdo_mysql
|
||||
pdo_pgsql
|
||||
pdo_sqlite
|
||||
pgsql
|
||||
Phar
|
||||
posix
|
||||
readline
|
||||
redis
|
||||
Reflection
|
||||
session
|
||||
SimpleXML
|
||||
sockets
|
||||
sodium
|
||||
SPL
|
||||
sqlite3
|
||||
standard
|
||||
tokenizer
|
||||
xlswriter
|
||||
xml
|
||||
xmlreader
|
||||
xmlwriter
|
||||
Zend OPcache
|
||||
zip
|
||||
zlib
|
||||
|
||||
[Zend Modules]
|
||||
Zend OPcache
|
||||
```
|
35
api/app/biz/ResCode.php
Normal file
35
api/app/biz/ResCode.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace app\biz;
|
||||
|
||||
class ResCode
|
||||
{
|
||||
const ERROR = 0; // 系统错误
|
||||
const SUCCESS = 200; // 正确
|
||||
const FAILED = -1; // 通用一般错误
|
||||
const HEARTBEAT = 1; // 自定义1表示心跳消息,可忽略
|
||||
const INTERNAL_ERROR = 500; // 500错误
|
||||
const LOGIN_FAILED = 301; // 自定义301表示登录失败
|
||||
const NOT_LOGGED = 306; // 自定义306表示未登录
|
||||
const NOT_ALLOWED = 308; // 自定义308表示没有权限
|
||||
const TOKEN_ERROR = 309; // 自定义309错误表示token失效
|
||||
const TIMEOUT = 400; // 400超时
|
||||
const NOT_FOUND = 404; // 404错误
|
||||
const NO_DATA = 407; // 自定义407表示数据不存在
|
||||
const NO_CHANGE = 408; // 自定义408表示无数据变化
|
||||
|
||||
const CODE_MESSAGES = [
|
||||
self::ERROR => '内部错误',
|
||||
self::SUCCESS => '操作成功',
|
||||
self::FAILED => '操作失败',
|
||||
self::NOT_LOGGED => '用户未登录',
|
||||
self::HEARTBEAT => '心跳',
|
||||
self::NOT_ALLOWED => '没有权限',
|
||||
self::NOT_FOUND => '请求路径不正确',
|
||||
self::INTERNAL_ERROR => '系统错误',
|
||||
self::NO_DATA => '数据不存在',
|
||||
self::LOGIN_FAILED => '登录失败',
|
||||
self::NO_CHANGE => '无数据变化',
|
||||
self::TOKEN_ERROR => '令牌无效',
|
||||
self::TIMEOUT => '超时',
|
||||
];
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Container;
|
||||
use support\Log;
|
||||
use support\Request;
|
||||
use Wandoubaba\Res;
|
||||
@ -10,7 +11,7 @@ class IndexController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$res = new Res();
|
||||
$res = Container::make(Res::class);
|
||||
$res1 = \jsonrpc\Client::service('default', 'Demo')->hello('Json');
|
||||
$res2 = \jsonrpc\Client::service('user', 'User')->login('admin', '123456');
|
||||
$res3 = \jsonrpc\Client::service('default', 'Demo')->text();
|
26
api/app/controller/TestController.php
Normal file
26
api/app/controller/TestController.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use Wandoubaba\Res;
|
||||
use support\Request;
|
||||
use support\Container;
|
||||
use support\Db;
|
||||
use support\Log;
|
||||
|
||||
class TestController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$res = Container::make(Res::class);
|
||||
// Log::channel('default')->info(__CLASS__ . DIRECTORY_SEPARATOR . __FUNCTION__, $_SERVER);
|
||||
$logs = Db::connection('mongolog')->collection('request')->get();
|
||||
// foreach ($logs as $log) {
|
||||
// $log->delete();
|
||||
// }
|
||||
// $logs->delete();
|
||||
$res->setData($logs);
|
||||
return json($res);
|
||||
}
|
||||
|
||||
}
|
23
api/app/middleware/AccessControl.php
Normal file
23
api/app/middleware/AccessControl.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
class AccessControl implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
|
||||
$response->withHeaders([
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
'Access-Control-Allow-Origin' => $request->header('Origin', '*'),
|
||||
'Access-Control-Allow-Methods' => '*',
|
||||
'Access-Control-Allow-Headers' => '*,ACCESSTOKEN',
|
||||
]);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
68
api/app/middleware/RequestLog.php
Normal file
68
api/app/middleware/RequestLog.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace app\middleware;
|
||||
|
||||
use support\Log;
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
class RequestLog implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* 需要中间件拦截的控制器清单,全部小写
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $controllerScope = [
|
||||
'app\controller\indexcontroller',
|
||||
'app\controller\testcontroller',
|
||||
];
|
||||
|
||||
/**
|
||||
* 在拦截的控制器中不需要被拦截的例外方法,如用户登录
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $actionWhiteList = [
|
||||
'app\controller\testcontroller\index', // oss里的download不校验
|
||||
];
|
||||
|
||||
public function process(Request $request, callable $next) : Response
|
||||
{
|
||||
$controller = strtolower($request->controller);
|
||||
$action = strtolower($request->action);
|
||||
$path = "{$controller}\\{$action}"; // 完整的控制器\方法字符串
|
||||
// 白名单方法的请求不拦截
|
||||
if (in_array($path, $this->actionWhiteList)) {
|
||||
return $next($request);
|
||||
}
|
||||
// 只拦截指定控制器的请求
|
||||
if (!in_array($controller, $this->controllerScope)) {
|
||||
return $next($request);
|
||||
}
|
||||
$info = [
|
||||
'session_id' => $request->sessionId(),
|
||||
'protocol_version' => $request->protocolVersion(),
|
||||
'method' => $request->method(),
|
||||
'ip' => $request->getRemoteIp(),
|
||||
'real_ip' => $request->getRealIp(),
|
||||
'host' => $request->host(),
|
||||
'path' => $request->path(),
|
||||
'uri' => $request->uri(),
|
||||
'url' => $request->url(),
|
||||
'full_url' => $request->fullUrl(),
|
||||
'query_string' => $request->queryString(),
|
||||
'get_params' => $request->get(),
|
||||
'post_params' => $request->post(),
|
||||
'local_ip' => $request->getLocalIp(),
|
||||
'local_port' => $request->getLocalPort(),
|
||||
'is_ajax' => $request->isAjax(),
|
||||
'is_pjax' => $request->isPjax(),
|
||||
'expects_json' => $request->expectsJson(),
|
||||
'accept_json' => $request->acceptJson(),
|
||||
];
|
||||
Log::channel('request')->info('', $info);
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
}
|
0
build/.gitignore → api/build/.gitignore
vendored
0
build/.gitignore → api/build/.gitignore
vendored
3
api/composer
Executable file
3
api/composer
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker compose run --rm webman-jsonrpc composer $@
|
@ -26,15 +26,16 @@
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.5.0",
|
||||
"monolog/monolog": "^2.0",
|
||||
"monolog/monolog": "^3.0",
|
||||
"vlucas/phpdotenv": "^5.5",
|
||||
"illuminate/database": "^8.83",
|
||||
"illuminate/pagination": "^8.83",
|
||||
"illuminate/events": "^8.83",
|
||||
"symfony/var-dumper": "^5.4",
|
||||
"illuminate/redis": "^8.83",
|
||||
"illuminate/database": "^10.0",
|
||||
"illuminate/pagination": "^10.0",
|
||||
"illuminate/events": "^10.0",
|
||||
"symfony/var-dumper": "^6.0",
|
||||
"illuminate/redis": "^10.0",
|
||||
"wandoubaba/res": "^1.0",
|
||||
"webman/console": "^1.2"
|
||||
"webman/console": "^1.2",
|
||||
"mongodb/laravel-mongodb": "^4.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
1443
composer.lock → api/composer.lock
generated
1443
composer.lock → api/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -12,4 +12,10 @@
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return new Webman\Container;
|
||||
// return new Webman\Container;
|
||||
|
||||
$builder = new \DI\ContainerBuilder();
|
||||
$builder->addDefinitions(config('dependence', []));
|
||||
$builder->useAutowiring(true);
|
||||
$builder->useAttributes(true);
|
||||
return $builder->build();
|
@ -46,5 +46,18 @@ return [
|
||||
'schema' => env('PG_SCHEMA', 'public'),
|
||||
'sslmode' => 'prefer',
|
||||
],
|
||||
'mongolog' => [
|
||||
'driver' => 'mongodb',
|
||||
'host' => env('MONGOLOG_HOST', '127.0.0.1'),
|
||||
'port' => env('MONGOLOG_PORT', 27017),
|
||||
'database' => env('MONGOLOG_DATABASE', 'log'),
|
||||
'username' => env('MONGOLOG_USERNAME', null),
|
||||
'password' => env('MONGOLOG_PASSWORD', null),
|
||||
'options' => [
|
||||
// here you can pass more settings to the Mongo Driver Manager
|
||||
// see https://www.php.net/manual/en/mongodb-driver-manager.construct.php under "Uri Options" for a list of complete parameters that you can use
|
||||
'appname' => 'homestead'
|
||||
],
|
||||
],
|
||||
]
|
||||
];
|
@ -12,4 +12,7 @@
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
||||
return [
|
||||
// 注入自定义错误码和错误提示
|
||||
'code_messages' => app\biz\ResCode::CODE_MESSAGES,
|
||||
];
|
@ -6,10 +6,10 @@
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'tcp://127.0.0.1:' . env('JSONRPC_SERVER_PORT', 8021), // rpc服务端的地址和端口
|
||||
env('DEFAULT_RPC_SERVER', 'tcp://127.0.0.1:8021'), // rpc服务端的地址和端口
|
||||
],
|
||||
'user' => [
|
||||
'tcp://127.0.0.1:8022',
|
||||
env('USER_RPC_SERVER', 'tcp://127.0.0.1:8022'), // rpc服务端的地址和端口
|
||||
],
|
||||
// 'server2' => [
|
||||
// /// ...
|
@ -1,4 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MongoDB\Client;
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
@ -19,13 +21,21 @@ return [
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
env('LOG_MAX_FIlES', 7), //$maxFiles
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
], [
|
||||
'class' => Monolog\Handler\MongoDBHandler::class,
|
||||
'constructor' => [
|
||||
new Client(env('MONGOLOG_URL', 'mongodb://localhost:27017')),
|
||||
env('MONGOLOG_DATABASE', 'log'),
|
||||
'default',
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
@ -36,24 +46,32 @@ return [
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/debug/debug.log',
|
||||
env('LOG_MAX_FILES_DEBUG') ?: env('LOG_MAX_FIlES') ?: 7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
|
||||
],
|
||||
], [
|
||||
'class' => Monolog\Handler\MongoDBHandler::class,
|
||||
'constructor' => [
|
||||
new Client(env('MONGOLOG_URL', 'mongodb://localhost:27017')),
|
||||
env('MONGOLOG_DATABASE', 'log'),
|
||||
'debug',
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
], [
|
||||
// 把日志输出到控制台
|
||||
'class' => Monolog\Handler\StreamHandler::class,
|
||||
'constructor' => [
|
||||
'php://stdout',
|
||||
Monolog\Logger::DEBUG,
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
'error' => [
|
||||
@ -63,18 +81,26 @@ return [
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/error/error.log',
|
||||
env('LOG_MAX_FILES_ERROR') ?: env('LOG_MAX_FIlES') ?: 7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
|
||||
],
|
||||
], [
|
||||
'class' => Monolog\Handler\MongoDBHandler::class,
|
||||
'constructor' => [
|
||||
new Client(env('MONGOLOG_URL', 'mongodb://localhost:27017')),
|
||||
env('MONGOLOG_DATABASE', 'log'),
|
||||
'error',
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
], [
|
||||
// 把日志输出到控制台
|
||||
'class' => Monolog\Handler\StreamHandler::class,
|
||||
'constructor' => [
|
||||
'php://stdout',
|
||||
Monolog\Logger::DEBUG,
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
@ -83,5 +109,18 @@ return [
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
// 记录请求日志
|
||||
'request' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\MongoDBHandler::class,
|
||||
'constructor' => [
|
||||
new Client(env('MONGOLOG_URL', 'mongodb://localhost:27017')),
|
||||
env('MONGOLOG_DATABASE', 'log'),
|
||||
'request',
|
||||
Monolog\Level::Debug,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
@ -12,4 +12,13 @@
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
||||
return [
|
||||
'' => [
|
||||
// 静态文件保护
|
||||
app\middleware\StaticFile::class,
|
||||
// 跨域请求
|
||||
app\middleware\AccessControl::class,
|
||||
// 记录请求日志
|
||||
app\middleware\RequestLog::class,
|
||||
],
|
||||
];
|
@ -15,9 +15,11 @@
|
||||
|
||||
global $argv;
|
||||
|
||||
return [
|
||||
// File update detection and automatic reload
|
||||
'monitor' => [
|
||||
$server_process = [];
|
||||
|
||||
// 是否启用monitor
|
||||
if (env('MONITOR_ENABLED', true)) {
|
||||
$server_process['monitor'] = [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
@ -39,10 +41,16 @@ return [
|
||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||
]
|
||||
]
|
||||
],
|
||||
env('JSONRPC_SERVER_NAME', 'jsonrpc') => [
|
||||
];
|
||||
}
|
||||
|
||||
// 是否启用jsonrpc
|
||||
if (env('JSONRPC_ENABLED', true)) {
|
||||
$server_process[env('JSONRPC_SERVER_NAME', 'jsonrpc')] = [
|
||||
'handler' => jsonrpc\Server::class,
|
||||
'listen' => 'JsonNL://0.0.0.0:' . env('JSONRPC_SERVER_PORT', '8021'),
|
||||
'listen' => env('JSONRPC_SERVER_LISTEN', 'JsonNL://0.0.0.0:8021'),
|
||||
'count' => eval("return " . env('JSONRPC_SERVER_COUNT', cpu_count() * 4) . ";"),
|
||||
],
|
||||
];
|
||||
];
|
||||
}
|
||||
|
||||
return $server_process;
|
12
api/docker-compose.yml
Normal file
12
api/docker-compose.yml
Normal file
@ -0,0 +1,12 @@
|
||||
version: "3.1"
|
||||
|
||||
services:
|
||||
webman-jsonrpc:
|
||||
image: wandoubaba517/workerman:8.1
|
||||
container_name: webman-jsonrpc
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./:/app/service
|
||||
- ./php.ini:/usr/local/etc/php/php.ini
|
||||
working_dir: /app/service
|
||||
stdin_open: true
|
31
api/envexample
Executable file
31
api/envexample
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 自动生成.env文件对应的.env.example文件
|
||||
generate_env_example() {
|
||||
# 清空原有的.env.example文件中的内容
|
||||
> .env.example
|
||||
|
||||
# 逐行读取.env文件
|
||||
while IFS= read -r line; do
|
||||
# 去除首尾空格
|
||||
line=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
||||
# 如果是注释行或空白行,直接写入.env.example文件
|
||||
if [[ $line == \#* || -z $line ]]; then
|
||||
echo "$line" >> .env.example
|
||||
# 如果是键值对行,判断键名是否包含指定字符串
|
||||
elif [[ $line == *=* ]]; then
|
||||
key=$(echo "$line" | cut -d= -f1)
|
||||
value=$(echo "$line" | cut -d= -f2-)
|
||||
# 如果键名包含指定字符串,将值清空写入.env.example文件
|
||||
if [[ $key == *KEY || $key == *PASSWORD* || $key == *SECRET* || $key == *PASS || $key == *TOKEN || $key == *ID ]]; then
|
||||
echo "$key=" >> .env.example
|
||||
# 否则,清除首尾空格后原样写入.env.example文件
|
||||
else
|
||||
echo "$key=$value" >> .env.example
|
||||
fi
|
||||
fi
|
||||
done < .env
|
||||
}
|
||||
|
||||
# 每次run后都自动生成.env.example文件
|
||||
generate_env_example
|
@ -17,62 +17,30 @@ namespace jsonrpc;
|
||||
|
||||
use Protocols\JsonNL;
|
||||
|
||||
/**
|
||||
* Aaron修改注释
|
||||
* 需要在config目录下创建jsonrpc.php文件,内容如下:
|
||||
*
|
||||
return [
|
||||
'default' => [
|
||||
'tcp://127.0.0.1:11002', // rpc服务端的地址和端口
|
||||
],
|
||||
'server1' => [
|
||||
/// ...
|
||||
],
|
||||
'server2' => [
|
||||
/// ...
|
||||
]
|
||||
];
|
||||
*
|
||||
* 客户端的调用方法
|
||||
// 调用default服务组中Demo类中的hello方法并传入参数$name
|
||||
$res = RpcClient::service('default', 'Demo')->hello($name);
|
||||
// 调用server1服务组中User类中的login方法并传入参数$name, $password,
|
||||
$res = RpcClient::service('server1', 'User')->login($userName, $userPassword);
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* RpcClient Rpc客户端
|
||||
*
|
||||
*
|
||||
* 示例
|
||||
* // 服务端列表
|
||||
$address_array = array(
|
||||
'tcp://127.0.0.1:2015',
|
||||
'tcp://127.0.0.1:2015'
|
||||
);
|
||||
// 配置服务端列表
|
||||
RpcClient::config($address_array);
|
||||
// ======== jsonrpc客户端使用方法 ========
|
||||
//
|
||||
// 需要在config目录下创建jsonrpc.php文件,内容如下:
|
||||
//
|
||||
// return [
|
||||
// 'default' => [
|
||||
// 'tcp://127.0.0.1:11002', // rpc服务端的地址和端口
|
||||
// ],
|
||||
// 'server1' => [
|
||||
// /// ...
|
||||
// ],
|
||||
// 'server2' => [
|
||||
// /// ...
|
||||
// ]
|
||||
// ];
|
||||
//
|
||||
// 客户端的调用方法:
|
||||
//
|
||||
// **** 调用default服务组中Demo类中的hello方法并传入参数$name
|
||||
// $res = RpcClient::service('default', 'Demo')->hello($name);
|
||||
// **** 调用server1服务组中User类中的login方法并传入参数$name, $password,
|
||||
// $res = RpcClient::service('server1', 'User')->login($userName, $userPassword);
|
||||
|
||||
$uid = 567;
|
||||
$user_client = RpcClient::instance('User');
|
||||
// ==同步调用==
|
||||
$ret_sync = $user_client->getInfoByUid($uid);
|
||||
|
||||
// ==异步调用==
|
||||
// 异步发送数据
|
||||
$user_client->asend_getInfoByUid($uid);
|
||||
$user_client->asend_getEmail($uid);
|
||||
|
||||
这里是其它的业务代码
|
||||
..............................................
|
||||
|
||||
// 异步接收数据
|
||||
$ret_async1 = $user_client->arecv_getEmail($uid);
|
||||
$ret_async2 = $user_client->arecv_getInfoByUid($uid);
|
||||
*
|
||||
* @author walkor <worker-man@qq.com>
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
/**
|
||||
@ -101,13 +69,13 @@ class Client
|
||||
|
||||
/**
|
||||
* 异步调用实例
|
||||
* @var string
|
||||
* @var array
|
||||
*/
|
||||
protected static $asyncInstances = array();
|
||||
|
||||
/**
|
||||
* 同步调用实例
|
||||
* @var string
|
||||
* @var array
|
||||
*/
|
||||
protected static $instances = array();
|
||||
|
||||
@ -182,7 +150,7 @@ class Client
|
||||
* @throws Exception
|
||||
* @return
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
public function __call($method, $arguments = [])
|
||||
{
|
||||
// 判断是否是异步发送
|
||||
if (0 === strpos($method, self::ASYNC_SEND_PREFIX)) {
|
||||
@ -219,9 +187,9 @@ class Client
|
||||
{
|
||||
$this->openConnection();
|
||||
$bin_data = JsonNL::encode(array(
|
||||
'class' => $this->serviceName,
|
||||
'method' => $method,
|
||||
'param_array' => $arguments,
|
||||
'class' => $this->serviceName,
|
||||
'method' => $method,
|
||||
'param_array' => $arguments,
|
||||
));
|
||||
if (fwrite($this->connection, $bin_data) !== strlen($bin_data)) {
|
||||
throw new \Exception('Can not send data');
|
3
api/php
Executable file
3
api/php
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker compose run --rm webman-jsonrpc php "$@"
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
47
api/server
Executable file
47
api/server
Executable file
@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 [start|stop|logs|restart|status|reload|connections]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
container_name="webman-jsonrpc-api"
|
||||
|
||||
if [ "$1" = "stop" ]; then
|
||||
if [ "$(docker inspect -f {{.State.Running}} $container_name 2>/dev/null)" = "true" ]; then
|
||||
docker stop $container_name
|
||||
else
|
||||
echo "Container $container_name is not running."
|
||||
fi
|
||||
else
|
||||
# 判断容器是否存在
|
||||
# if [ ! "$(docker ps -a -q -f name=$container_name)" ]; then
|
||||
# # 调用init脚本
|
||||
# ./init
|
||||
# fi
|
||||
# 判断容器是否在运行
|
||||
if [ ! "$(docker inspect -f {{.State.Running}} $container_name 2>/dev/null)" = "true" ]; then
|
||||
# 启动容器
|
||||
docker start $container_name
|
||||
fi
|
||||
if [ "$1" = "logs" ]; then
|
||||
docker logs -f $container_name
|
||||
elif [ "$1" = "start" ]; then
|
||||
# docker exec -itd $container_name bash -c "php start.php start"
|
||||
:
|
||||
elif [ "$1" = "restart" ]; then
|
||||
docker restart $container_name
|
||||
elif [ "$1" = "status" ]; then
|
||||
docker exec -it $container_name bash -c "php start.php status"
|
||||
elif [ "$1" = "reload" ]; then
|
||||
docker exec -it $container_name bash -c "php start.php reload"
|
||||
elif [ "$1" = "connections" ]; then
|
||||
docker exec -it $container_name bash -c "php start.php connections"
|
||||
else
|
||||
echo "Invalid command"
|
||||
echo "Usage: $0 [start|stop|logs|restart|status|reload|connections]"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
@ -380,7 +380,7 @@ function copy_dir(string $source, string $dest, bool $overwrite = false)
|
||||
$files = scandir($source);
|
||||
foreach ($files as $file) {
|
||||
if ($file !== "." && $file !== "..") {
|
||||
copy_dir("$source/$file", "$dest/$file");
|
||||
copy_dir("$source/$file", "$dest/$file", $overwrite);
|
||||
}
|
||||
}
|
||||
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
|
||||
@ -515,3 +515,14 @@ function cpu_count(): int
|
||||
}
|
||||
return $count > 0 ? $count : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* get GET or POST request parameters, if no parameter name is passed, an array of all values is returned, default values is supported
|
||||
* @param string|null $param param's name
|
||||
* @param string|null $default default value
|
||||
* @return mixed|null
|
||||
*/
|
||||
function input(string $param = null, string $default = null)
|
||||
{
|
||||
return is_null($param) ? request()->all() : request()->input($param, $default);
|
||||
}
|
@ -36,8 +36,20 @@ foreach (config('plugin', []) as $firm => $projects) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['command'] ?? [] as $command) {
|
||||
$cli->add(Container::get($command));
|
||||
foreach ($project['command'] ?? [] as $class_name) {
|
||||
$reflection = new \ReflectionClass($class_name);
|
||||
if ($reflection->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$properties = $reflection->getStaticProperties();
|
||||
$name = $properties['defaultName'];
|
||||
if (!$name) {
|
||||
throw new RuntimeException("Command {$class_name} has no defaultName");
|
||||
}
|
||||
$description = $properties['defaultDescription'] ?? '';
|
||||
$command = Container::get($class_name);
|
||||
$command->setName($name)->setDescription($description);
|
||||
$cli->add($command);
|
||||
}
|
||||
}
|
||||
}
|
@ -61,6 +61,7 @@ function write_process_file($runtimeProcessPath, $processName, $firm): string
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use Workerman\Worker;
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use Webman\Config;
|
||||
use support\App;
|
||||
|
||||
@ -77,6 +78,7 @@ worker_start('$processParam', $configParam);
|
||||
|
||||
if (DIRECTORY_SEPARATOR != "/") {
|
||||
Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
|
||||
TcpConnection::\$defaultMaxPackageSize = config('server')['max_package_size'] ?? 10*1024*1024;
|
||||
}
|
||||
|
||||
Worker::runAll();
|
15
composer
15
composer
@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 读取docker.conf文件
|
||||
source docker.conf
|
||||
|
||||
# 设置系统环境变量
|
||||
export WORKERMAN_CONTAINER_NAME=$container_name
|
||||
export WORKERMAN_IMAGE_VERSION=$image_version
|
||||
|
||||
# 判断WORKERMAN_CONTAINER_NAME的docker容器是否存在,如果存在,删除它
|
||||
if docker ps -a --format '{{.Names}}' | grep -q "^$WORKERMAN_CONTAINER_NAME$"; then
|
||||
docker rm -f $WORKERMAN_CONTAINER_NAME
|
||||
fi
|
||||
|
||||
docker compose run --rm $WORKERMAN_CONTAINER_NAME composer "$@"
|
19
console
19
console
@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 读取docker.conf文件
|
||||
source docker.conf
|
||||
|
||||
# 设置系统环境变量
|
||||
export WORKERMAN_CONTAINER_NAME=$container_name
|
||||
export WORKERMAN_IMAGE_VERSION=$image_version
|
||||
|
||||
# 判断WORKERMAN_CONTAINER_NAME的docker容器是否存在,如果存在,删除它
|
||||
if docker ps -a --format '{{.Names}}' | grep -q "^$WORKERMAN_CONTAINER_NAME$"; then
|
||||
docker rm -f $WORKERMAN_CONTAINER_NAME
|
||||
fi
|
||||
|
||||
if [[ $1 == "build" ]]; then
|
||||
docker compose run --rm $WORKERMAN_CONTAINER_NAME php webman build:bin $image_version && cp .env build/
|
||||
else
|
||||
docker compose run --rm $WORKERMAN_CONTAINER_NAME php webman "$@"
|
||||
fi
|
@ -1,15 +1,26 @@
|
||||
version: "3.1"
|
||||
|
||||
services:
|
||||
webman-jsonrpc:
|
||||
image: wandoubaba517/workerman:${WORKERMAN_IMAGE_VERSION}
|
||||
container_name: webman-jsonrpc
|
||||
api:
|
||||
image: wandoubaba517/workerman:8.1
|
||||
container_name: webman-jsonrpc-api
|
||||
network_mode: host
|
||||
restart: always
|
||||
volumes:
|
||||
- ./:/app/service
|
||||
- ./php.ini:/usr/local/etc/php/php.ini
|
||||
- ./api/:/app/service
|
||||
- ./api/php.ini:/usr/local/etc/php/php.ini
|
||||
working_dir: /app/service
|
||||
stdin_open: true
|
||||
command: ["php", "start.php", "start"]
|
||||
depends_on:
|
||||
- log
|
||||
command: ['php', 'start.php', 'start']
|
||||
|
||||
log:
|
||||
image: mongo:6.0
|
||||
container_name: webman-jsonrpc-log
|
||||
restart: always
|
||||
volumes:
|
||||
- ./log/db:/data/db
|
||||
- ./log/mongod.conf:/etc/mongod.conf
|
||||
network_mode: host
|
||||
command: ['mongod', '--config', '/etc/mongod.conf']
|
||||
|
@ -1,2 +0,0 @@
|
||||
container_name=webman-jsonrpc
|
||||
image_version=8.1
|
2
log/.gitignore
vendored
Normal file
2
log/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
!.gitignore
|
||||
db/*
|
40
log/mongod.conf
Normal file
40
log/mongod.conf
Normal file
@ -0,0 +1,40 @@
|
||||
# mongod.conf
|
||||
|
||||
# for documentation of all options, see:
|
||||
# http://docs.mongodb.org/manual/reference/configuration-options/
|
||||
|
||||
# Where and how to store data.
|
||||
storage:
|
||||
dbPath: /data/db
|
||||
# engine:
|
||||
# wiredTiger:
|
||||
|
||||
# where to write logging data.
|
||||
# systemLog:
|
||||
# destination: file
|
||||
# logAppend: true
|
||||
# path: /var/log/mongodb/mongod.log
|
||||
|
||||
# network interfaces
|
||||
net:
|
||||
port: 27019
|
||||
bindIp: 0.0.0.0
|
||||
|
||||
|
||||
# how the process runs
|
||||
# processManagement:
|
||||
# timeZoneInfo: /usr/share/zoneinfo
|
||||
|
||||
#security:
|
||||
|
||||
#operationProfiling:
|
||||
|
||||
#replication:
|
||||
|
||||
#sharding:
|
||||
|
||||
## Enterprise-Only Options:
|
||||
|
||||
#auditLog:
|
||||
|
||||
#snmp:
|
61
start
61
start
@ -1,61 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 读取docker.conf文件
|
||||
source docker.conf
|
||||
|
||||
# 设置系统环境变量
|
||||
export WORKERMAN_CONTAINER_NAME=$container_name
|
||||
export WORKERMAN_IMAGE_VERSION=$image_version
|
||||
|
||||
# 检查docker-compose.yml文件是否存在
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
echo "Error: docker-compose.yml file not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 定义帮助函数
|
||||
show_help() {
|
||||
echo "Usage: ./start [COMMAND]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " run once"
|
||||
echo " start run once"
|
||||
echo " -d run in daemon mode"
|
||||
echo " status service status(daemon mode only)"
|
||||
echo " reload reload files(daemon mode only)"
|
||||
echo " restart restart service(daemon mode only)"
|
||||
echo " stop stop service and container"
|
||||
echo " help show this help message"
|
||||
}
|
||||
|
||||
# 定义安装依赖的函数
|
||||
install_dependencies() {
|
||||
# 执行一次composer install
|
||||
docker compose run --rm $WORKERMAN_CONTAINER_NAME composer install
|
||||
}
|
||||
|
||||
# 根据参数执行不同的命令
|
||||
if [[ $# -eq 0 || $1 == "start" ]]; then
|
||||
install_dependencies
|
||||
docker compose run --rm $WORKERMAN_CONTAINER_NAME php start.php start
|
||||
elif [[ $1 == "-d" ]]; then
|
||||
install_dependencies
|
||||
docker compose up -d
|
||||
elif [[ $1 == "help" ]]; then
|
||||
show_help
|
||||
else
|
||||
# 判断WORKERMAN_CONTAINER_NAME的docker容器是否存在,如果不存在,直接退出
|
||||
if ! docker ps -a --format '{{.Names}}' | grep -q "^$WORKERMAN_CONTAINER_NAME$"; then
|
||||
echo "container not exist."
|
||||
exit 1
|
||||
fi
|
||||
if ! docker ps --format '{{.Names}}' | grep -q "^$WORKERMAN_CONTAINER_NAME$"; then
|
||||
echo "container is not running."
|
||||
exit 1
|
||||
fi
|
||||
# 执行php start命令
|
||||
docker exec -it $WORKERMAN_CONTAINER_NAME php start.php "$@"
|
||||
if [[ $1 == "stop" ]]; then
|
||||
docker stop $WORKERMAN_CONTAINER_NAME
|
||||
fi
|
||||
fi
|
Loading…
Reference in New Issue
Block a user