From e76836f3940aa9a73ab8215435aadedd5beef189 Mon Sep 17 00:00:00 2001
From: CityFun <31820853+zhengkunwang223@users.noreply.github.com>
Date: Thu, 7 Aug 2025 21:39:33 +0800
Subject: [PATCH] feat: Add concurrency configuration for PHP performance
optimization (#9877)
---
agent/app/service/app_utils.go | 8 +-
frontend/src/lang/modules/en.ts | 1 +
frontend/src/lang/modules/ja.ts | 3 +-
frontend/src/lang/modules/ko.ts | 3 +-
frontend/src/lang/modules/ms.ts | 3 +-
frontend/src/lang/modules/pt-br.ts | 3 +-
frontend/src/lang/modules/ru.ts | 3 +-
frontend/src/lang/modules/tr.ts | 1 +
frontend/src/lang/modules/zh-Hant.ts | 3 +-
frontend/src/lang/modules/zh.ts | 3 +-
.../website/runtime/dotnet/operate/index.vue | 2 +-
.../runtime/php/config/performance/index.vue | 83 +++++++++++++++++++
12 files changed, 104 insertions(+), 12 deletions(-)
diff --git a/agent/app/service/app_utils.go b/agent/app/service/app_utils.go
index 9ec206c9c..8e236b5fa 100644
--- a/agent/app/service/app_utils.go
+++ b/agent/app/service/app_utils.go
@@ -873,9 +873,9 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
_ = fileOp.CreateDir(appVersionDir, constant.DirPerm)
}
if logger == nil {
- global.LOG.Infof("download app[%s] from %s", app.Name, appDetail.DownloadUrl)
+ global.LOG.Infof("download app [%s] from %s", app.Name, appDetail.DownloadUrl)
} else {
- logger.Printf("download app[%s] from %s", app.Name, appDetail.DownloadUrl)
+ logger.Printf("download app [%s] from %s", app.Name, appDetail.DownloadUrl)
}
filePath := path.Join(appVersionDir, app.Key+"-"+appDetail.Version+".tar.gz")
@@ -891,9 +891,9 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
if err = files.DownloadFileWithProxy(appDetail.DownloadUrl, filePath); err != nil {
if logger == nil {
- global.LOG.Errorf("download app[%s] error %v", app.Name, err)
+ global.LOG.Errorf("download app [%s] error %v", app.Name, err)
} else {
- logger.Printf("download app[%s] error %v", app.Name, err)
+ logger.Printf("download app [%s] error %v", app.Name, err)
}
return
}
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index a1d6725ab..1cd7ee09e 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -2795,6 +2795,7 @@ const message = {
'Provide a full startup command. For example, "pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000".',
dotnetHelper: 'Provide a full startup command. For example, "dotnet MyWebApp.dll".',
dirHelper: 'Note: Please fill in the directory path inside the container',
+ concurrency: 'Concurrency Scheme',
},
process: {
pid: 'Process ID',
diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts
index efa7af64e..59651b168 100644
--- a/frontend/src/lang/modules/ja.ts
+++ b/frontend/src/lang/modules/ja.ts
@@ -2685,8 +2685,9 @@ const message = {
goDirHelper: 'ディレクトリまたはサブディレクトリには、goファイルまたはバイナリファイルを含める必要があります。',
pythonHelper:
'完全な起動コマンドを提供します。たとえば、「PIP Install -R Repormations.txt && python manage.py runserver 0.0.0.0:5000」。',
- donetHelper: '完全な起動コマンドを入力してください。例えば、dotnet MyWebApp.dll',
+ dotnetHelper: '完全な起動コマンドを入力してください。例えば、dotnet MyWebApp.dll',
dirHelper: 'ノート: コンテナ内のディレクトリパスを入力してください',
+ concurrency: '並行処理スキーム',
},
process: {
pid: 'プロセスID',
diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts
index a22cc74ce..16b5deef9 100644
--- a/frontend/src/lang/modules/ko.ts
+++ b/frontend/src/lang/modules/ko.ts
@@ -2637,8 +2637,9 @@ const message = {
goDirHelper: '디렉터리 또는 하위 디렉터리는 Go 또는 바이너리 파일을 포함해야 합니다.',
pythonHelper:
'전체 시작 명령을 제공하세요. 예: "pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000".',
- donetHelper: '완전한 시작 명령을 입력하세요. 예: dotnet MyWebApp.dll',
+ dotnetHelper: '완전한 시작 명령을 입력하세요. 예: dotnet MyWebApp.dll',
dirHelper: '주의: 컨테이너 내의 디렉토리 경로를 입력하세요',
+ concurrency: '동시성 체계',
},
process: {
pid: '프로세스 ID',
diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts
index a2e90089e..64c0bb669 100644
--- a/frontend/src/lang/modules/ms.ts
+++ b/frontend/src/lang/modules/ms.ts
@@ -2746,8 +2746,9 @@ const message = {
goDirHelper: 'Direktori atau subdirektori mesti mengandungi fail Go atau binari.',
pythonHelper:
'Sediakan arahan permulaan penuh. Contohnya, "pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000".',
- donetHelper: 'Sila isi arahan pelancaran lengkap, contohnya dotnet MyWebApp.dll',
+ dotnetHelper: 'Sila isi arahan pelancaran lengkap, contohnya dotnet MyWebApp.dll',
dirHelper: 'Nota: Sila isi laluan direktori di dalam bekas',
+ concurrency: 'Skim Serentak',
},
process: {
pid: 'Process ID',
diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts
index b5dbe29ef..2a9ce7f66 100644
--- a/frontend/src/lang/modules/pt-br.ts
+++ b/frontend/src/lang/modules/pt-br.ts
@@ -2750,8 +2750,9 @@ const message = {
goDirHelper: 'O diretório ou subdiretório deve conter arquivos Go ou binários.',
pythonHelper:
'Forneça um comando completo de inicialização. Por exemplo, "pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000".',
- donetHelper: 'Por favor, preencha o comando completo de inicialização, por exemplo, dotnet MyWebApp.dll',
+ dotnetHelper: 'Por favor, preencha o comando completo de inicialização, por exemplo, dotnet MyWebApp.dll',
dirHelper: 'Nota: Preencha o caminho do diretório dentro do contêiner',
+ concurrency: 'Esquema de Concorrência',
},
process: {
pid: 'ID do Processo',
diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts
index f642e4a1a..eb36cd5ac 100644
--- a/frontend/src/lang/modules/ru.ts
+++ b/frontend/src/lang/modules/ru.ts
@@ -2742,8 +2742,9 @@ const message = {
goDirHelper: 'Директория или поддиректория должна содержать файлы Go или бинарные файлы.',
pythonHelper:
'Укажите полную команду запуска. Например, "pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000".',
- donetHelper: 'Пожалуйста, укажите полную команду запуска, например, dotnet MyWebApp.dll',
+ dotnetHelper: 'Пожалуйста, укажите полную команду запуска, например, dotnet MyWebApp.dll',
dirHelper: 'Примечание: Укажите путь к каталогу внутри контейнера',
+ concurrency: 'Схема параллелизма',
},
process: {
pid: 'ID процесса',
diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts
index 98e95e4d4..a0cb38ff3 100644
--- a/frontend/src/lang/modules/tr.ts
+++ b/frontend/src/lang/modules/tr.ts
@@ -2832,6 +2832,7 @@ const message = {
'Tam bir başlatma komutu sağlayın. Örneğin, "pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000".',
dotnetHelper: 'Tam bir başlatma komutu sağlayın. Örneğin, "dotnet MyWebApp.dll".',
dirHelper: 'Not: Lütfen kapsayıcı içindeki dizin yolunu doldurun',
+ concurrency: 'Eşzamanlılık Şeması',
},
process: {
pid: 'İşlem Kimliği',
diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts
index d000baba7..52cea588e 100644
--- a/frontend/src/lang/modules/zh-Hant.ts
+++ b/frontend/src/lang/modules/zh-Hant.ts
@@ -2603,8 +2603,9 @@ const message = {
environment: '環境變數',
pythonHelper:
'請填寫完整啟動指令,例如:pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000',
- donetHelper: '請填寫完整的啟動命令,例如 dotnet MyWebApp.dll',
+ dotnetHelper: '請填寫完整的啟動命令,例如 dotnet MyWebApp.dll',
dirHelper: '說明:請填寫容器內的目錄路徑',
+ concurrency: '並發方案',
},
process: {
pid: '進程ID',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index 2bae8ad81..710fccec7 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -2593,8 +2593,9 @@ const message = {
environment: '环境变量',
pythonHelper:
'请填写完整启动命令,例如:pip install -r requirements.txt && python manage.py runserver 0.0.0.0:5000',
- donetHelper: '请填写完整启动命令,例如 dotnet MyWebApp.dll',
+ dotnetHelper: '请填写完整启动命令,例如 dotnet MyWebApp.dll',
dirHelper: '说明:请填写容器内的目录路径',
+ concurrency: '并发方案',
},
process: {
pid: '进程ID',
diff --git a/frontend/src/views/website/runtime/dotnet/operate/index.vue b/frontend/src/views/website/runtime/dotnet/operate/index.vue
index f3639e1d3..dfaa3add3 100644
--- a/frontend/src/views/website/runtime/dotnet/operate/index.vue
+++ b/frontend/src/views/website/runtime/dotnet/operate/index.vue
@@ -19,7 +19,7 @@
-
+
diff --git a/frontend/src/views/website/runtime/php/config/performance/index.vue b/frontend/src/views/website/runtime/php/config/performance/index.vue
index 3529fae0a..f11481325 100644
--- a/frontend/src/views/website/runtime/php/config/performance/index.vue
+++ b/frontend/src/views/website/runtime/php/config/performance/index.vue
@@ -2,6 +2,16 @@
+
+
+
+
+
@@ -85,6 +95,79 @@ const variablesRules = reactive({
'pm.min_spare_servers': [checkNumberRange(0, 99999)],
'pm.max_spare_servers': [checkNumberRange(0, 99999)],
});
+const concurrency = ref('');
+const concurrencyOptions = ref([
+ { label: '4 GB', value: '4' },
+ { label: '8 GB', value: '8' },
+ { label: '16 GB', value: '16' },
+ { label: '32 GB', value: '32' },
+ { label: '48 GB', value: '48' },
+ { label: '64 GB', value: '64' },
+ { label: '96 GB', value: '96' },
+ { label: '128 GB', value: '128' },
+]);
+
+const fpmConfigMap = {
+ '4': {
+ max_children: 80,
+ start_servers: 10,
+ min_spare_servers: 10,
+ max_spare_servers: 30,
+ },
+ '8': {
+ max_children: 120,
+ start_servers: 10,
+ min_spare_servers: 10,
+ max_spare_servers: 30,
+ },
+ '16': {
+ max_children: 200,
+ start_servers: 15,
+ min_spare_servers: 15,
+ max_spare_servers: 50,
+ },
+ '32': {
+ max_children: 300,
+ start_servers: 20,
+ min_spare_servers: 20,
+ max_spare_servers: 50,
+ },
+ '48': {
+ max_children: 400,
+ start_servers: 20,
+ min_spare_servers: 20,
+ max_spare_servers: 50,
+ },
+ '64': {
+ max_children: 500,
+ start_servers: 30,
+ min_spare_servers: 30,
+ max_spare_servers: 60,
+ },
+ '96': {
+ max_children: 700,
+ start_servers: 40,
+ min_spare_servers: 40,
+ max_spare_servers: 70,
+ },
+ '128': {
+ max_children: 1000,
+ start_servers: 50,
+ min_spare_servers: 50,
+ max_spare_servers: 100,
+ },
+};
+
+const changeConcurrency = () => {
+ const config = fpmConfigMap[concurrency.value];
+
+ if (config) {
+ params['pm.max_children'] = config.max_children;
+ params['pm.start_servers'] = config.start_servers;
+ params['pm.min_spare_servers'] = config.min_spare_servers;
+ params['pm.max_spare_servers'] = config.max_spare_servers;
+ }
+};
const get = () => {
loading.value = true;