docker.conf, env, webman/console, wandoubaba/res, log, exception

This commit is contained in:
wandoubaba 2023-10-18 17:04:31 +08:00
parent dee9ab3359
commit 5f1631de57
20 changed files with 1127 additions and 381 deletions

41
.env.example Normal file
View File

@ -0,0 +1,41 @@
# 开启DEBUG时客户端会看到详细的异常信息
DEBUG = true
# 主服务配置
SERVER_NAME = webman-jsonrpc
SERVER_LISTEN = http://0.0.0.0:7878
SERVER_COUNT = cpu_count()
MAX_PACKAGE_SIZE = 1024*1024*5
# REDIS配置
REDIS_HOST = 127.0.0.1
REDIS_PORT = 6379
REDIS_PASSWORD = null
REDIS_DATABASE = 0
# 数据库
DB_DEFAULT_DRIVER = pgsql
# mysql
MYSQL_HOST = 127.0.0.1
MYSQL_PORT = 3306
MYSQL_USERNAME =
MYSQL_PASSWORD =
MYSQL_DATABASE =
# pgsql
PG_HOST = 127.0.0.1
PG_PORT = 5432
PG_USERNAME =
PG_PASSWORD =
PG_DATABASE =
PG_SCHEMA = default
# sqlite
SQLITE_DATABASE = "base_path() . '/database.sqlite'"
SQLITE_PREFIX =
# log
LOG_MAX_FIlES = 30
LOG_MAX_FILES_DEBUG = 3
LOG_MAX_FIlES_ERROR = 90

View File

@ -1,59 +1,27 @@
<div style="padding:18px;max-width: 1024px;margin:0 auto;background-color:#fff;color:#333"> # 基于docker的webman-jsonrpc
<h1>webman</h1>
基于<a href="https://www.workerman.net" target="__blank">workerman</a>开发的超高性能PHP框架 我们在`php:8.1-cli`基础上安装了运行webman必要的一些扩展和开发中常用的扩展以及composer制作成`workerman:8.1`镜像因此在开发环境中不需要再额外配置php环境直接写业务代码即可。
## 依赖
<h1>学习</h1> 只要系统环境中有docker即可不需要安装php环境
<ul> ## 使用方法
<li>
<a href="https://www.workerman.net/webman" target="__blank">主页 / Home page</a>
</li>
<li>
<a href="https://www.workerman.net/doc/webman" target="__blank">文档 / Document</a>
</li>
<li>
<a href="https://www.workerman.net/doc/webman/install.html" target="__blank">安装 / Install</a>
</li>
<li>
<a href="https://www.workerman.net/questions" target="__blank">问答 / Questions</a>
</li>
<li>
<a href="https://www.workerman.net/apps" target="__blank">市场 / Apps</a>
</li>
<li>
<a href="https://www.workerman.net/sponsor" target="__blank">赞助 / Sponsors</a>
</li>
<li>
<a href="https://www.workerman.net/doc/webman/thanks.html" target="__blank">致谢 / Thanks</a>
</li>
</ul>
<div style="float:left;padding-bottom:30px;"> ```sh
# 启动
<h1>赞助商</h1> ./start
# composer
<h4>特别赞助</h4> ./composer install
<a href="https://www.crmeb.com/?form=workerman" target="__blank"> ./conposer require xxxx
<img src="https://www.workerman.net/img/sponsors/6429/20230719111500.svg" width="200"> ```
</a>
<h4>铂金赞助</h4>
<a href="https://www.fadetask.com/?from=workerman" target="__blank"><img src="https://www.workerman.net/img/sponsors/1/20230719084316.png" width="200"></a>
<a href="https://www.yilianyun.net/?from=workerman" target="__blank" style="margin-left:20px;"><img src="https://www.workerman.net/img/sponsors/6218/20230720114049.png" width="200"></a>
<h4>金牌赞助</h4>
</div>
<div style="clear: both">
<h1>LICENSE</h1>
The webman is open-sourced software licensed under the MIT.
</div>
</div>
## 一些有用的文件
| 文件 | 作用 | 用法或说明 |
|---|---|---|
|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配置文件|容器中已经安装的扩展都有单独的配置文件,这里不会有体现|

View File

@ -2,17 +2,22 @@
namespace app\controller; namespace app\controller;
use ErrorException;
use Exception;
use support\Log;
use support\Request; use support\Request;
use Wandoubaba\Res;
class IndexController class IndexController
{ {
public function index(Request $request) public function index(Request $request)
{ {
static $readme; // var_dump(eval("return " . env('MAX_PACKAGE_SIZE', 10 * 1024 * 1024) . ";"));
if (!$readme) { // throw new Exception(config('redis.default.password') ?: 'null', 999);
$readme = file_get_contents(base_path('README.md')); $res = new Res();
} $res->setData([env('LOG_MAX_FILES_DEBUG') ?: env('LOG_MAX_FIlES') ?: 7]);
return $readme; Log::channel('error')->error('错了');
return json($res);
} }
public function view(Request $request) public function view(Request $request)

51
app/exception/Handler.php Normal file
View File

@ -0,0 +1,51 @@
<?php
namespace app\exception;
use Throwable;
use Webman\Http\Request;
use Webman\Http\Response;
use Wandoubaba\Res;
/**
* 自定义异常处理类
* 要使用这个类请在config/exception.php中配置
* '' => app\exception\Handler::class,
*/
class Handler extends \support\exception\Handler
{
/**
* 自定义异常响应
*
* @author Aaron <chenqiang@h024.cn>
*
* @param \Webman\Http\Request $request
* @param \Throwable $exception
*
* @return \Webman\Http\Response
*/
public function render(Request $request, Throwable $exception): Response
{
$res = new Res();
$resData = null;
if (config('app.debug') == 'true') {
$resData = [
'request_path' => $request->path(),
'post_data' => $request->post(),
'query_param' => $request->get(),
'headers' => $request->header(),
];
$resData['exception'] = [
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'message' => $exception->getMessage(),
'trace' => $exception->getTrace(),
];
}
$res->setCode($exception->getCode())
->setMsg($exception->getMessage())
->setData($resData);
return json($res);
}
}

4
app/global.php Normal file
View File

@ -0,0 +1,4 @@
<?php
/**
* Here is your custom global vars & constant.
*/

View File

@ -1,18 +1,15 @@
#!/bin/bash #!/bin/bash
service_name="webman-jsonrpc"
compose_file="docker-compose-dev.yml"
if docker ps --format '{{.Names}}' | grep -q "^$service_name$" # 读取docker.conf文件
then source docker.conf
docker exec $service_name composer "$@"
else # 设置系统环境变量
if docker-compose -f $compose_file up -d; then export WORKERMAN_CONTAINER_NAME=$container_name
docker exec $service_name composer "$@" export WORKERMAN_IMAGE_VERSION=$image_version
else
if docker compose -f $compose_file up -d; then # 判断WORKERMAN_CONTAINER_NAME的docker容器是否存在如果存在删除它
docker exec $service_name composer "$@" if docker ps -a --format '{{.Names}}' | grep -q "^$WORKERMAN_CONTAINER_NAME$"; then
else docker rm -f $WORKERMAN_CONTAINER_NAME
echo "Failed to start the container using docker-compose or docker compose."
fi
fi
fi fi
docker compose run --rm $WORKERMAN_CONTAINER_NAME composer "$@"

View File

@ -28,11 +28,13 @@
"workerman/webman-framework": "^1.5.0", "workerman/webman-framework": "^1.5.0",
"monolog/monolog": "^2.0", "monolog/monolog": "^2.0",
"vlucas/phpdotenv": "^5.5", "vlucas/phpdotenv": "^5.5",
"illuminate/database": "^10.28", "illuminate/database": "^8.83",
"illuminate/pagination": "^10.28", "illuminate/pagination": "^8.83",
"illuminate/events": "^10.28", "illuminate/events": "^8.83",
"symfony/var-dumper": "^6.3", "symfony/var-dumper": "^5.4",
"illuminate/redis": "^10.28" "illuminate/redis": "^8.83",
"wandoubaba/res": "^1.0",
"webman/console": "^1.2"
}, },
"suggest": { "suggest": {
"ext-event": "For better performance. " "ext-event": "For better performance. "

1074
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
use support\Request; use support\Request;
return [ return [
'debug' => true, 'debug' => env('DEBUG', false),
'error_reporting' => E_ALL, 'error_reporting' => E_ALL,
'default_timezone' => 'Asia/Shanghai', 'default_timezone' => 'Asia/Shanghai',
'request_class' => Request::class, 'request_class' => Request::class,

View File

@ -14,6 +14,7 @@
return [ return [
'files' => [ 'files' => [
base_path() . '/app/global.php',
base_path() . '/app/functions.php', base_path() . '/app/functions.php',
base_path() . '/support/Request.php', base_path() . '/support/Request.php',
base_path() . '/support/Response.php', base_path() . '/support/Response.php',

View File

@ -12,4 +12,39 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
return []; return [
'default' => env('DB_DEFAULT_DRIVER', 'mysql'),
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('MYSQL_HOST', '127.0.0.1'),
'port' => env('MYSQL_PORT', 3306),
'database' => env('MYSQL_DATABASE', 'webman'),
'username' => env('MYSQL_USERNAME', 'webman'),
'password' => env('MYSQL_PASSWORD', ''),
'unix_socket' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'sqlite' => [
'driver' => 'sqlite',
'database' => eval("return " . env('SQLITE_DATABASE', '') . ";"),
'prefix' => env('SQLITE_PREFIX', ''),
],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('PG_HOST', '127.0.0.1'),
'port' => env('PG_PORT', 5432),
'database' => env('PG_DATABASE', 'webman'),
'username' => env('PG_USERNAME', 'webman'),
'password' => env('PG_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => env('PG_SCHEMA', 'public'),
'sslmode' => 'prefer',
],
]
];

View File

@ -13,5 +13,6 @@
*/ */
return [ return [
'' => support\exception\Handler::class, // '' => support\exception\Handler::class,
'' => app\exception\Handler::class,
]; ];

View File

@ -29,4 +29,59 @@ return [
] ]
], ],
], ],
'debug' => [
'handlers' => [
[
'class' => Monolog\Handler\RotatingFileHandler::class,
'constructor' => [
runtime_path() . '/logs/debug/debug.log',
env('LOG_MAX_FILES_DEBUG') ?: env('LOG_MAX_FIlES') ?: 7, //$maxFiles
Monolog\Logger::DEBUG,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
],
], [
// 把日志输出到控制台
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'php://stdout',
Monolog\Logger::DEBUG,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
],
],
],
],
'error' => [
'handlers' => [
[
'class' => Monolog\Handler\RotatingFileHandler::class,
'constructor' => [
runtime_path() . '/logs/error/error.log',
env('LOG_MAX_FILES_ERROR') ?: env('LOG_MAX_FIlES') ?: 7, //$maxFiles
Monolog\Logger::DEBUG,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
],
], [
// 把日志输出到控制台
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'php://stdout',
Monolog\Logger::DEBUG,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [null, 'Y-m-d H:i:s.u', true, true],
],
],
],
],
]; ];

View File

@ -0,0 +1,24 @@
<?php
return [
'enable' => true,
'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
'phar_filename' => 'webman.phar',
'bin_filename' => 'webman.bin',
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#',
'exclude_files' => [
'.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin'
],
'custom_ini' => '
memory_limit = 256M
',
];

View File

@ -14,9 +14,9 @@
return [ return [
'default' => [ 'default' => [
'host' => '127.0.0.1', 'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => null, 'password' => env('REDIS_PASSWORD', null),
'port' => 6379, 'port' => env('REDIS_PORT', 6379),
'database' => 0, 'database' => env('REDIS_DATABASE', 0),
], ],
]; ];

View File

@ -13,11 +13,11 @@
*/ */
return [ return [
'listen' => '', 'listen' => env('SERVER_LISTEN', 'http://0.0.0.0:8787'),
'transport' => 'tcp', 'transport' => 'tcp',
'context' => [], 'context' => [],
'name' => 'webman', 'name' => env('SERVER_NAME', 'webman'),
'count' => 1, 'count' => eval("return " . env('SERVER_COUNT', cpu_count() * 4) . ";"),
'user' => '', 'user' => '',
'group' => '', 'group' => '',
'reusePort' => false, 'reusePort' => false,
@ -27,5 +27,5 @@ return [
'status_file' => runtime_path() . '/webman.status', 'status_file' => runtime_path() . '/webman.status',
'stdout_file' => runtime_path() . '/logs/stdout.log', 'stdout_file' => runtime_path() . '/logs/stdout.log',
'log_file' => runtime_path() . '/logs/workerman.log', 'log_file' => runtime_path() . '/logs/workerman.log',
'max_package_size' => 10 * 1024 * 1024 'max_package_size' => eval("return " . env('MAX_PACKAGE_SIZE', 10 * 1024 * 1024) . ";"),
]; ];

View File

@ -2,7 +2,7 @@ version: "3.1"
services: services:
webman-jsonrpc: webman-jsonrpc:
image: registry.cn-shanghai.aliyuncs.com/wandoubaba/workerman:8.1 image: registry.cn-shanghai.aliyuncs.com/wandoubaba/workerman:${WORKERMAN_IMAGE_VERSION}
container_name: webman-jsonrpc container_name: webman-jsonrpc
network_mode: host network_mode: host
restart: always restart: always

2
docker.conf Normal file
View File

@ -0,0 +1,2 @@
container_name=webman-jsonrpc
image_version=8.1

23
start
View File

@ -1,9 +1,22 @@
#!/bin/bash #!/bin/bash
service_name="webman-jsonrpc"
compose_file="docker-compose-dev.yml"
if docker inspect -f '{{.State.Running}}' $service_name >/dev/null 2>&1; then # 读取docker.conf文件
docker rm -f $service_name 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 fi
docker compose -f $compose_file up docker compose run --rm $WORKERMAN_CONTAINER_NAME composer install
# 根据参数执行docker compose up命令
if [[ $1 == "-d" ]]; then
docker compose up -d
else
docker compose up
fi

45
webman Executable file
View File

@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php
use Webman\Config;
use Webman\Console\Command;
use Webman\Console\Util;
use support\Container;
require_once __DIR__ . '/vendor/autoload.php';
if (!in_array($argv[1] ?? '', ['start', 'restart', 'stop', 'status', 'reload', 'connections'])) {
require_once __DIR__ . '/support/bootstrap.php';
} else {
if (class_exists('Support\App')) {
Support\App::loadAllConfig(['route']);
} else {
Config::reload(config_path(), ['route', 'container']);
}
}
$cli = new Command();
$cli->setName('webman cli');
$cli->installInternalCommands();
if (is_dir($command_path = Util::guessPath(app_path(), '/command', true))) {
$cli->installCommands($command_path);
}
foreach (config('plugin', []) as $firm => $projects) {
if (isset($projects['app'])) {
if ($command_str = Util::guessPath(base_path() . "/plugin/$firm", 'command')) {
$command_path = base_path() . "/plugin/$firm/$command_str";
$cli->installCommands($command_path, "plugin\\$firm\\$command_str");
}
}
foreach ($projects as $name => $project) {
if (!is_array($project)) {
continue;
}
foreach ($project['command'] ?? [] as $command) {
$cli->add(Container::get($command));
}
}
}
$cli->run();