mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-14 01:34:47 +08:00
feat: PHP 增加性能调整配置 (#6420)
This commit is contained in:
parent
7aefd0df1a
commit
ad3670c9ad
@ -76,6 +76,13 @@ func (b *BaseApi) DeleteRuntime(c *gin.Context) {
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Delete runtime
|
||||
// @Description 删除运行环境校验
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /installed/delete/check/:id [get]
|
||||
func (b *BaseApi) DeleteRuntimeCheck(c *gin.Context) {
|
||||
runTimeId, err := helper.GetIntParamByKey(c, "runTimeId")
|
||||
if err != nil {
|
||||
@ -362,7 +369,6 @@ func (b *BaseApi) UpdatePHPFile(c *gin.Context) {
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// 写一个调用 GetPHPConfigFile 的方法
|
||||
// @Tags Runtime
|
||||
// @Summary Get php conf file
|
||||
// @Description 获取 php 配置文件
|
||||
@ -383,3 +389,45 @@ func (b *BaseApi) GetPHPConfigFile(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Update fpm config
|
||||
// @Description 更新 fpm 配置
|
||||
// @Accept json
|
||||
// @Param request body request.FPMConfig true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/php/fpm/config [post]
|
||||
func (b *BaseApi) UpdateFPMConfig(c *gin.Context) {
|
||||
var req request.FPMConfig
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := runtimeService.UpdateFPMConfig(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Get fpm config
|
||||
// @Description 获取 fpm 配置
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
// @Success 200 {object} response.FPMConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/php/fpm/config/:id [get]
|
||||
func (b *BaseApi) GetFPMConfig(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
|
||||
return
|
||||
}
|
||||
data, err := runtimeService.GetFPMConfig(id)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
@ -95,3 +95,8 @@ type PHPFileReq struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
}
|
||||
|
||||
type FPMConfig struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Params map[string]interface{} `json:"params" validate:"required"`
|
||||
}
|
||||
|
@ -37,6 +37,14 @@ func (r *Runtime) GetPath() string {
|
||||
return path.Join(constant.RuntimeDir, r.Type, r.Name)
|
||||
}
|
||||
|
||||
func (r *Runtime) GetFPMPath() string {
|
||||
return path.Join(constant.RuntimeDir, r.Type, r.Name, "conf", "php-fpm.conf")
|
||||
}
|
||||
|
||||
func (r *Runtime) GetPHPPath() string {
|
||||
return path.Join(constant.RuntimeDir, r.Type, r.Name, "conf", "php.ini")
|
||||
}
|
||||
|
||||
func (r *Runtime) GetLogPath() string {
|
||||
return path.Join(r.GetPath(), "build.log")
|
||||
}
|
||||
|
@ -58,6 +58,8 @@ type IRuntimeService interface {
|
||||
UpdatePHPConfig(req request.PHPConfigUpdate) (err error)
|
||||
UpdatePHPConfigFile(req request.PHPFileUpdate) error
|
||||
GetPHPConfigFile(req request.PHPFileReq) (*response.FileInfo, error)
|
||||
UpdateFPMConfig(req request.FPMConfig) error
|
||||
GetFPMConfig(id uint) (*request.FPMConfig, error)
|
||||
}
|
||||
|
||||
func NewRuntimeService() IRuntimeService {
|
||||
@ -833,7 +835,7 @@ func (r *RuntimeService) UpdatePHPConfig(req request.PHPConfigUpdate) (err error
|
||||
phpConfigPath := path.Join(runtime.GetPath(), "conf", "php.ini")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(phpConfigPath) {
|
||||
return buserr.WithMap("ErrFileNotFound", map[string]interface{}{"name": "php.ini"}, nil)
|
||||
return buserr.WithName("ErrFileNotFound", "php.ini")
|
||||
}
|
||||
configFile, err := fileOp.OpenFile(phpConfigPath)
|
||||
if err != nil {
|
||||
@ -931,3 +933,64 @@ func (r *RuntimeService) UpdatePHPConfigFile(req request.PHPFileUpdate) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) UpdateFPMConfig(req request.FPMConfig) error {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg, err := ini.Load(runtime.GetFPMPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range req.Params {
|
||||
var valueStr string
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
valueStr = v
|
||||
case int:
|
||||
valueStr = fmt.Sprintf("%d", v)
|
||||
case float64:
|
||||
valueStr = fmt.Sprintf("%.f", v)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
cfg.Section("www").Key(k).SetValue(valueStr)
|
||||
}
|
||||
if err := cfg.SaveTo(runtime.GetFPMPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var PmKeys = map[string]struct {
|
||||
}{
|
||||
"pm": {},
|
||||
"pm.max_children": {},
|
||||
"pm.start_servers": {},
|
||||
"pm.min_spare_servers": {},
|
||||
"pm.max_spare_servers": {},
|
||||
}
|
||||
|
||||
func (r *RuntimeService) GetFPMConfig(id uint) (*request.FPMConfig, error) {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(runtime.GetFPMPath()) {
|
||||
return nil, buserr.WithName("ErrFileNotFound", "php-fpm.conf")
|
||||
}
|
||||
params := make(map[string]interface{})
|
||||
cfg, err := ini.Load(runtime.GetFPMPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, key := range cfg.Section("www").Keys() {
|
||||
if _, ok := PmKeys[key.Name()]; ok {
|
||||
params[key.Name()] = key.Value()
|
||||
}
|
||||
}
|
||||
res := &request.FPMConfig{Params: params}
|
||||
return res, nil
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
|
||||
baseApi := v2.ApiGroupApp.BaseApi
|
||||
{
|
||||
groupRouter.GET("/installed/delete/check/:runTimeId", baseApi.DeleteRuntimeCheck)
|
||||
groupRouter.GET("/installed/delete/check/:id", baseApi.DeleteRuntimeCheck)
|
||||
groupRouter.POST("/search", baseApi.SearchRuntimes)
|
||||
groupRouter.POST("", baseApi.CreateRuntime)
|
||||
groupRouter.POST("/del", baseApi.DeleteRuntime)
|
||||
@ -39,6 +39,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
groupRouter.POST("/php/config", baseApi.UpdatePHPConfig)
|
||||
groupRouter.POST("/php/update", baseApi.UpdatePHPFile)
|
||||
groupRouter.POST("/php/file", baseApi.GetPHPConfigFile)
|
||||
groupRouter.POST("/php/fpm/config", baseApi.UpdateFPMConfig)
|
||||
groupRouter.GET("/php/fpm/config/:id", baseApi.GetFPMConfig)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -166,4 +166,9 @@ export namespace Runtime {
|
||||
id: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface FPMConfig {
|
||||
id: number;
|
||||
params: any;
|
||||
}
|
||||
}
|
||||
|
@ -96,3 +96,11 @@ export const UpdatePHPFile = (req: Runtime.PHPUpdate) => {
|
||||
export const GetPHPConfigFile = (req: Runtime.PHPFileReq) => {
|
||||
return http.post<File.File>(`/runtimes/php/file`, req);
|
||||
};
|
||||
|
||||
export const UpdateFPMConfig = (req: Runtime.FPMConfig) => {
|
||||
return http.post(`/runtimes/php/fpm/config`, req);
|
||||
};
|
||||
|
||||
export const GetFPMConfig = (id: number) => {
|
||||
return http.get<Runtime.FPMConfig>(`/runtimes/php/fpm/config/${id}`);
|
||||
};
|
||||
|
@ -2443,6 +2443,20 @@ const message = {
|
||||
uninstallExtension: 'Are you sure you want to uninstall the extension {0}',
|
||||
phpConfigHelper:
|
||||
'Modifying the configuration requires restarting the operating environment, do you want to continue',
|
||||
operateMode: 'operation mode',
|
||||
dynamic: 'dynamic',
|
||||
static: 'static',
|
||||
ondemand: 'on-demand',
|
||||
dynamicHelper:
|
||||
'dynamically adjust the number of processes, high flexibility, suitable for websites with large traffic fluctuations or low memory',
|
||||
staticHelper:
|
||||
'fixed number of processes, suitable for websites with high concurrency and stable traffic, high resource consumption',
|
||||
ondemandHelper:
|
||||
'processes are started and destroyed on demand, resource utilization is optimal, but the initial response may be slow',
|
||||
max_children: 'maximum number of processes allowed to be created',
|
||||
start_servers: 'number of processes created at startup',
|
||||
min_spare_servers: 'minimum number of idle processes',
|
||||
max_spare_servers: 'maximum number of idle processes',
|
||||
},
|
||||
process: {
|
||||
pid: 'Process ID',
|
||||
|
@ -2266,6 +2266,17 @@ const message = {
|
||||
popularExtension: '常用擴充',
|
||||
uninstallExtension: '是否確認卸載擴充功能 {0}',
|
||||
phpConfigHelper: '修改配置需要重新啟動運行環境,是否繼續',
|
||||
operateMode: '運行模式',
|
||||
dynamic: '動態',
|
||||
static: '靜態',
|
||||
ondemand: '按需',
|
||||
dynamicHelper: '動態調整進程數,彈性高,適合流量波動較大或低記憶體的網站',
|
||||
staticHelper: '固定進程數,適合高併發穩定流量的網站,資源消耗較高',
|
||||
ondemandHelper: '進程按需啟動和銷毀,資源利用最優,但初始回應可能較慢',
|
||||
max_children: '允許創建的最大進程數',
|
||||
start_servers: '啟動時所建立的進程數',
|
||||
min_spare_servers: '最小空閒行程數',
|
||||
max_spare_servers: '最大空閒行程數',
|
||||
},
|
||||
process: {
|
||||
pid: '進程ID',
|
||||
|
@ -2268,6 +2268,17 @@ const message = {
|
||||
popularExtension: '常用扩展',
|
||||
uninstallExtension: '是否确认卸载扩展 {0}',
|
||||
phpConfigHelper: '修改配置需要重启运行环境,是否继续',
|
||||
operateMode: '运行模式',
|
||||
dynamic: '动态',
|
||||
static: '静态',
|
||||
ondemand: '按需',
|
||||
dynamicHelper: '动态调整进程数,灵活性高,适合流量波动较大或者低内存的网站',
|
||||
staticHelper: '固定进程数,适合高并发和稳定流量的网站,资源消耗较高',
|
||||
ondemandHelper: '进程按需启动和销毁,资源利用最优,但初始响应可能较慢',
|
||||
max_children: '允许创建的最大进程数',
|
||||
start_servers: '启动时创建的进程数',
|
||||
min_spare_servers: '最小空闲进程数',
|
||||
max_spare_servers: '最大空闲进程数',
|
||||
},
|
||||
process: {
|
||||
pid: '进程ID',
|
||||
|
@ -16,7 +16,6 @@
|
||||
</el-input>
|
||||
<span class="input-help">{{ $t('php.max_execution_time') }}</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="post_max_size" prop="post_max_size">
|
||||
<el-input clearable v-model.number="form.post_max_size" maxlength="15">
|
||||
<template #append>M</template>
|
||||
|
@ -11,12 +11,15 @@
|
||||
<el-tab-pane :label="$t('php.uploadMaxSize')" name="2">
|
||||
<Upload :id="runtime.id" v-if="index == '2'"></Upload>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'php-fpm'" name="3">
|
||||
<PHP :id="runtime.id" v-if="index == '3'" :type="'fpm'"></PHP>
|
||||
<el-tab-pane :label="$t('website.nginxPer')" name="5">
|
||||
<Performance :id="runtime.id" v-if="index == '5'"></Performance>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'php'" name="4">
|
||||
<el-tab-pane :label="$t('website.source')" name="4">
|
||||
<PHP :id="runtime.id" v-if="index == '4'" :type="'php'"></PHP>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'FPM ' + $t('website.source')" name="3">
|
||||
<PHP :id="runtime.id" v-if="index == '3'" :type="'fpm'"></PHP>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
@ -24,11 +27,12 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import Config from './config/index.vue';
|
||||
import Function from './function/index.vue';
|
||||
import Upload from './upload/index.vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import PHP from './php-fpm/index.vue';
|
||||
import Performance from './performance/index.vue';
|
||||
|
||||
const index = ref('0');
|
||||
const open = ref(false);
|
||||
|
@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<el-form :model="params" :rules="variablesRules" ref="phpFormRef" label-position="top" v-loading="loading">
|
||||
<el-row v-loading="loading">
|
||||
<el-col :span="22" :offset="1">
|
||||
<el-form-item :label="$t('runtime.operateMode')" prop="pm">
|
||||
<el-select v-model="params.pm">
|
||||
<el-option :label="$t('runtime.dynamic')" :value="'dynamic'"></el-option>
|
||||
<el-option :label="$t('runtime.static')" :value="'static'"></el-option>
|
||||
<el-option :label="$t('runtime.ondemand')" :value="'ondemand'"></el-option>
|
||||
</el-select>
|
||||
<span class="input-help">
|
||||
<el-text v-if="params.pm == 'dynamic'">{{ $t('runtime.dynamicHelper') }}</el-text>
|
||||
<el-text v-if="params.pm == 'static'">{{ $t('runtime.staticHelper') }}</el-text>
|
||||
<el-text v-if="params.pm == 'ondemand'">{{ $t('runtime.ondemandHelper') }}</el-text>
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="max_children" prop="pm.max_children">
|
||||
<el-input clearable v-model.number="params['pm.max_children']" maxlength="15"></el-input>
|
||||
<span class="input-help">
|
||||
{{ $t('runtime.max_children') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="start_servers" prop="pm.start_servers">
|
||||
<el-input clearable v-model.number="params['pm.start_servers']" maxlength="15"></el-input>
|
||||
<span class="input-help">
|
||||
{{ $t('runtime.start_servers') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="min_spare_servers" prop="pm.min_spare_servers">
|
||||
<el-input clearable v-model.number="params['pm.min_spare_servers']" maxlength="15"></el-input>
|
||||
<span class="input-help">
|
||||
{{ $t('runtime.min_spare_servers') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="max_spare_servers" prop="pm.max_spare_servers">
|
||||
<el-input clearable v-model.number="params['pm.max_spare_servers']" maxlength="15"></el-input>
|
||||
<span class="input-help">
|
||||
{{ $t('runtime.max_spare_servers') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSaveStart(phpFormRef)">
|
||||
{{ $t('commons.button.save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { GetFPMConfig, UpdateFPMConfig } from '@/api/modules/runtime';
|
||||
import { checkNumberRange, Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const id = computed(() => {
|
||||
return props.id;
|
||||
});
|
||||
const loading = ref(false);
|
||||
const phpFormRef = ref();
|
||||
const initData = () => {
|
||||
return {
|
||||
pm: 'dynamic',
|
||||
'pm.max_children': 150,
|
||||
'pm.start_servers': 10,
|
||||
'pm.min_spare_servers': 10,
|
||||
'pm.max_spare_servers': 30,
|
||||
};
|
||||
};
|
||||
const params = reactive(initData());
|
||||
const variablesRules = reactive({
|
||||
pm: [Rules.requiredSelect],
|
||||
'pm.max_children': [checkNumberRange(0, 5000)],
|
||||
'pm.start_servers': [checkNumberRange(0, 99999)],
|
||||
'pm.min_spare_servers': [checkNumberRange(0, 99999)],
|
||||
'pm.max_spare_servers': [checkNumberRange(0, 99999)],
|
||||
});
|
||||
|
||||
const get = () => {
|
||||
loading.value = true;
|
||||
GetFPMConfig(id.value)
|
||||
.then((res) => {
|
||||
const resParams = res.data.params;
|
||||
params['pm'] = resParams['pm'];
|
||||
params['pm.max_children'] = Number(resParams['pm.max_children']);
|
||||
params['pm.start_servers'] = Number(resParams['pm.start_servers']);
|
||||
params['pm.min_spare_servers'] = Number(resParams['pm.min_spare_servers']);
|
||||
params['pm.max_spare_servers'] = Number(resParams['pm.max_spare_servers']);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const onSaveStart = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
const action = await ElMessageBox.confirm(
|
||||
i18n.global.t('runtime.phpConfigHelper'),
|
||||
i18n.global.t('database.confChange'),
|
||||
{
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
type: 'info',
|
||||
},
|
||||
);
|
||||
if (action === 'confirm') {
|
||||
loading.value = true;
|
||||
submit();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
loading.value = true;
|
||||
UpdateFPMConfig({ id: id.value, params: params })
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||
get();
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
get();
|
||||
});
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user