From ddf6555250dd1ffc561bb4f7c1b9a5273b1eb89f Mon Sep 17 00:00:00 2001 From: zhengkunwang223 Date: Thu, 24 Nov 2022 10:28:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0nginx=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E8=B0=83=E6=95=B4=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/nginx/versions/1.23.1/conf/nginx.conf | 16 +- backend/app/api/v1/nginx.go | 32 ++++ backend/app/dto/nginx.go | 35 +++-- backend/app/service/app_utils.go | 20 ++- backend/app/service/nginx.go | 27 +++- backend/app/service/nginx_utils.go | 90 +++++++++++ backend/app/service/website_utils.go | 23 ++- backend/router/ro_nginx.go | 2 + backend/utils/nginx/components/config.go | 10 ++ backend/utils/nginx/components/http.go | 21 ++- cmd/server/nginx_conf/http_per.conf | 14 ++ cmd/server/nginx_conf/nginx_conf.go | 3 + frontend/src/api/interface/nginx.ts | 18 ++- frontend/src/api/interface/website.ts | 1 - frontend/src/api/modules/nginx.ts | 9 ++ frontend/src/components/app-status/index.vue | 1 + frontend/src/lang/modules/zh.ts | 10 ++ .../website/config/basic/limit-conn/index.vue | 1 - frontend/src/views/website/website/index.vue | 83 +++++----- .../src/views/website/website/nginx/index.vue | 4 + .../website/nginx/performance/index.vue | 142 ++++++++++++++++++ .../website/website/nginx/source/index.vue | 2 +- 22 files changed, 482 insertions(+), 82 deletions(-) create mode 100644 backend/app/service/nginx_utils.go create mode 100644 cmd/server/nginx_conf/http_per.conf create mode 100644 frontend/src/views/website/website/nginx/performance/index.vue diff --git a/apps/nginx/versions/1.23.1/conf/nginx.conf b/apps/nginx/versions/1.23.1/conf/nginx.conf index 85ce0d72f..8a03e229f 100644 --- a/apps/nginx/versions/1.23.1/conf/nginx.conf +++ b/apps/nginx/versions/1.23.1/conf/nginx.conf @@ -20,7 +20,21 @@ http { access_log /var/log/nginx/access.log main; sendfile on; - keepalive_timeout 65; + + server_names_hash_bucket_size 512; + client_header_buffer_size 32k; + client_max_body_size 50m; + keepalive_timeout 60; + + gzip on; + gzip_min_length 1k; + gzip_buffers 4 16k; + gzip_http_version 1.1; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml; + gzip_vary on; + gzip_proxied expired no-cache no-store private auth; + gzip_disable "MSIE [1-6]\."; include /etc/nginx/conf.d/*.conf; } \ No newline at end of file diff --git a/backend/app/api/v1/nginx.go b/backend/app/api/v1/nginx.go index 33b687361..c919e5abe 100644 --- a/backend/app/api/v1/nginx.go +++ b/backend/app/api/v1/nginx.go @@ -2,6 +2,7 @@ package v1 import ( "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/gin-gonic/gin" ) @@ -15,3 +16,34 @@ func (b *BaseApi) GetNginx(c *gin.Context) { } helper.SuccessWithData(c, fileInfo) } + +func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) { + + var req dto.NginxScopeReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + params, err := nginxService.GetConfigByScope(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, params) +} + +func (b *BaseApi) UpdateNginxConfigBy(c *gin.Context) { + + var req dto.NginxConfigReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + if err := nginxService.UpdateConfigByScope(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/dto/nginx.go b/backend/app/dto/nginx.go index 7f9c3e492..12e64aee9 100644 --- a/backend/app/dto/nginx.go +++ b/backend/app/dto/nginx.go @@ -10,18 +10,23 @@ type NginxConfig struct { } type NginxConfigReq struct { - Scope NginxScope `json:"scope"` + Scope NginxKey `json:"scope"` Operate NginxOp `json:"operate"` - WebSiteID uint `json:"webSiteId" validate:"required"` + WebSiteID uint `json:"webSiteId"` Params interface{} `json:"params"` } -type NginxScope string +type NginxScopeReq struct { + Scope NginxKey `json:"scope"` +} + +type NginxKey string const ( - Index NginxScope = "index" - LimitConn NginxScope = "limit-conn" - SSL NginxScope = "ssl" + Index NginxKey = "index" + LimitConn NginxKey = "limit-conn" + SSL NginxKey = "ssl" + HttpPer NginxKey = "http-per" ) type NginxOp string @@ -32,12 +37,21 @@ const ( ConfigDel NginxOp = "delete" ) -var ScopeKeyMap = map[NginxScope][]string{ +var ScopeKeyMap = map[NginxKey][]string{ Index: {"index"}, LimitConn: {"limit_conn", "limit_rate", "limit_conn_zone"}, SSL: {"ssl_certificate", "ssl_certificate_key"}, + HttpPer: {"server_names_hash_bucket_size", "client_header_buffer_size", "client_max_body_size", "keepalive_timeout", "gzip", "gzip_min_length", "gzip_comp_level"}, } +type NginxScope string + +const ( + NginxHttp NginxScope = "http" + NginxServer NginxScope = "server" + NginxEvents NginxScope = "events" +) + var RepeatKeys = map[string]struct { }{ "limit_conn": {}, @@ -45,8 +59,7 @@ var RepeatKeys = map[string]struct { } type NginxParam struct { - Name string `json:"name"` - SecondKey string `json:"secondKey"` - IsRepeatKey bool `json:"isRepeatKey"` - Params []string `json:"params"` + Name string `json:"name"` + SecondKey string `json:"secondKey"` + Params []string `json:"params"` } diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index b919b72ae..a13a28e6e 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -211,18 +211,10 @@ func updateInstall(installId uint, detailId uint) error { if err != nil { return err } - //oldDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(install.AppDetailId)) - //if err != nil { - // return err - //} - detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(detailId)) if err != nil { return err } - //if oldDetail.LastVersion == detail.Version { - // install.CanUpdate = false - //} if install.Version == detail.Version { return errors.New("two version is same") } @@ -592,3 +584,15 @@ func handleInstalled(installed []model.AppInstall) ([]dto.AppInstalled, error) { return res, nil } + +func getAppInstallByKey(key string) (model.AppInstall, error) { + app, err := appRepo.GetFirst(appRepo.WithKey(key)) + if err != nil { + return model.AppInstall{}, err + } + appInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID)) + if err != nil { + return model.AppInstall{}, err + } + return appInstall, nil +} diff --git a/backend/app/service/nginx.go b/backend/app/service/nginx.go index fefab2841..109235d3d 100644 --- a/backend/app/service/nginx.go +++ b/backend/app/service/nginx.go @@ -10,12 +10,9 @@ import ( type NginxService struct { } -func (w NginxService) GetNginxConfig() (dto.FileInfo, error) { - nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx")) - if err != nil { - return dto.FileInfo{}, err - } - nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) +func (n NginxService) GetNginxConfig() (dto.FileInfo, error) { + + nginxInstall, err := getAppInstallByKey("nginx") if err != nil { return dto.FileInfo{}, err } @@ -31,3 +28,21 @@ func (w NginxService) GetNginxConfig() (dto.FileInfo, error) { } return dto.FileInfo{FileInfo: *info}, nil } + +func (n NginxService) GetConfigByScope(req dto.NginxScopeReq) ([]dto.NginxParam, error) { + + keys, ok := dto.ScopeKeyMap[req.Scope] + if !ok || len(keys) == 0 { + return nil, nil + } + + return getHttpConfigByKeys(keys) +} + +func (n NginxService) UpdateConfigByScope(req dto.NginxConfigReq) error { + keys, ok := dto.ScopeKeyMap[req.Scope] + if !ok || len(keys) == 0 { + return nil + } + return updateHttpNginxConfig(getNginxParams(req.Params, keys)) +} diff --git a/backend/app/service/nginx_utils.go b/backend/app/service/nginx_utils.go new file mode 100644 index 000000000..7d10527bc --- /dev/null +++ b/backend/app/service/nginx_utils.go @@ -0,0 +1,90 @@ +package service + +import ( + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/utils/nginx" + "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" + "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser" + "os" + "path" +) + +func getDefaultNginxConfig() (dto.NginxConfig, error) { + var nginxConfig dto.NginxConfig + + nginxInstall, err := getAppInstallByKey("nginx") + if err != nil { + return nginxConfig, err + } + + configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "nginx.conf") + content, err := os.ReadFile(configPath) + if err != nil { + return nginxConfig, err + } + config := parser.NewStringParser(string(content)).Parse() + config.FilePath = configPath + nginxConfig.Config = config + nginxConfig.OldContent = string(content) + nginxConfig.ContainerName = nginxInstall.ContainerName + nginxConfig.FilePath = configPath + + return nginxConfig, nil +} + +func getHttpConfigByKeys(keys []string) ([]dto.NginxParam, error) { + nginxConfig, err := getDefaultNginxConfig() + if err != nil { + return nil, err + } + config := nginxConfig.Config + http := config.FindHttp() + + var res []dto.NginxParam + for _, key := range keys { + dirs := http.FindDirectives(key) + for _, dir := range dirs { + nginxParam := dto.NginxParam{ + Name: dir.GetName(), + Params: dir.GetParameters(), + } + if isRepeatKey(key) { + nginxParam.SecondKey = dir.GetParameters()[0] + } + res = append(res, nginxParam) + } + if len(dirs) == 0 { + nginxParam := dto.NginxParam{ + Name: key, + Params: []string{}, + } + res = append(res, nginxParam) + } + } + return res, nil +} + +func updateHttpNginxConfig(params []dto.NginxParam) error { + nginxConfig, err := getDefaultNginxConfig() + if err != nil { + return err + } + config := nginxConfig.Config + http := config.FindHttp() + for _, p := range params { + newDir := components.Directive{ + Name: p.Name, + Parameters: p.Params, + } + if isRepeatKey(p.Name) { + http.UpdateDirectiveBySecondKey(p.Name, p.SecondKey, newDir) + } else { + http.UpdateDirectives(p.Name, newDir) + } + } + if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { + return err + } + return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName) +} diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go index f991a8fc2..3427d83aa 100644 --- a/backend/app/service/website_utils.go +++ b/backend/app/service/website_utils.go @@ -175,11 +175,8 @@ func nginxCheckAndReload(oldContent string, filePath string, containerName strin func getNginxConfig(alias string) (dto.NginxConfig, error) { var nginxConfig dto.NginxConfig - nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx")) - if err != nil { - return nginxConfig, err - } - nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) + + nginxInstall, err := getAppInstallByKey("nginx") if err != nil { return nginxConfig, err } @@ -257,7 +254,6 @@ func getNginxConfigByKeys(website model.WebSite, keys []string) ([]dto.NginxPara Params: dir.GetParameters(), } if isRepeatKey(key) { - nginxParam.IsRepeatKey = true nginxParam.SecondKey = dir.GetParameters()[0] } res = append(res, nginxParam) @@ -266,7 +262,7 @@ func getNginxConfigByKeys(website model.WebSite, keys []string) ([]dto.NginxPara return res, nil } -func updateNginxConfig(website model.WebSite, params []dto.NginxParam, scope dto.NginxScope) error { +func updateNginxConfig(website model.WebSite, params []dto.NginxParam, scope dto.NginxKey) error { nginxConfig, err := getNginxConfig(website.Alias) if err != nil { return err @@ -279,7 +275,7 @@ func updateNginxConfig(website model.WebSite, params []dto.NginxParam, scope dto Name: p.Name, Parameters: p.Params, } - if p.IsRepeatKey { + if isRepeatKey(p.Name) { server.UpdateDirectiveBySecondKey(p.Name, p.SecondKey, newDir) } else { server.UpdateDirectives(p.Name, newDir) @@ -291,7 +287,7 @@ func updateNginxConfig(website model.WebSite, params []dto.NginxParam, scope dto return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName) } -func updateConfig(config *components.Config, scope dto.NginxScope) { +func updateConfig(config *components.Config, scope dto.NginxKey) { newConfig := &components.Config{} switch scope { case dto.LimitConn: @@ -306,11 +302,15 @@ func updateConfig(config *components.Config, scope dto.NginxScope) { Name: dir.GetName(), Parameters: dir.GetParameters(), } - config.UpdateDirectiveBySecondKey(dir.GetName(), dir.GetParameters()[0], newDir) + if isRepeatKey(dir.GetName()) { + config.UpdateDirectiveBySecondKey(dir.GetName(), dir.GetParameters()[0], newDir) + } else { + config.UpdateDirectives(dir.GetName(), newDir) + } } } -func getNginxParamsFromStaticFile(scope dto.NginxScope) []dto.NginxParam { +func getNginxParamsFromStaticFile(scope dto.NginxKey) []dto.NginxParam { var nginxParams []dto.NginxParam newConfig := &components.Config{} switch scope { @@ -429,7 +429,6 @@ func handleParamMap(paramMap map[string]string, keys []string) []dto.NginxParam Params: getParamArray(k, v), } if isRepeatKey(k) { - param.IsRepeatKey = true param.SecondKey = param.Params[0] } nginxParams = append(nginxParams, param) diff --git a/backend/router/ro_nginx.go b/backend/router/ro_nginx.go index afd91218e..67f151c67 100644 --- a/backend/router/ro_nginx.go +++ b/backend/router/ro_nginx.go @@ -16,5 +16,7 @@ func (a *NginxRouter) InitNginxRouter(Router *gin.RouterGroup) { baseApi := v1.ApiGroupApp.BaseApi { groupRouter.GET("", baseApi.GetNginx) + groupRouter.POST("/scope", baseApi.GetNginxConfigByScope) + groupRouter.POST("/update", baseApi.UpdateNginxConfigBy) } } diff --git a/backend/utils/nginx/components/config.go b/backend/utils/nginx/components/config.go index 342ddbb7c..aab4d183e 100644 --- a/backend/utils/nginx/components/config.go +++ b/backend/utils/nginx/components/config.go @@ -26,3 +26,13 @@ func (c *Config) FindServers() []*Server { } return servers } + +func (c *Config) FindHttp() *Http { + var http *Http + directives := c.Block.FindDirectives("http") + if len(directives) > 0 { + http = directives[0].(*Http) + } + + return http +} diff --git a/backend/utils/nginx/components/http.go b/backend/utils/nginx/components/http.go index 2b8f50087..849054949 100644 --- a/backend/utils/nginx/components/http.go +++ b/backend/utils/nginx/components/http.go @@ -67,9 +67,9 @@ func (h *Http) FindDirectives(directiveName string) []IDirective { } func (h *Http) UpdateDirectives(directiveName string, directive Directive) { - directives := make([]IDirective, len(h.GetDirectives())) + directives := h.Directives index := -1 - for i, dir := range h.GetDirectives() { + for i, dir := range directives { if dir.GetName() == directiveName { index = i break @@ -107,3 +107,20 @@ func (h *Http) RemoveDirectives(names []string) { func (h *Http) GetBlock() IBlock { return h } + +func (h *Http) UpdateDirectiveBySecondKey(name string, key string, directive Directive) { + directives := h.Directives + index := -1 + for i, dir := range directives { + if dir.GetName() == name && dir.GetParameters()[0] == key { + index = i + break + } + } + if index > -1 { + directives[index] = &directive + } else { + directives = append(directives, &directive) + } + h.Directives = directives +} diff --git a/cmd/server/nginx_conf/http_per.conf b/cmd/server/nginx_conf/http_per.conf new file mode 100644 index 000000000..661c4bac4 --- /dev/null +++ b/cmd/server/nginx_conf/http_per.conf @@ -0,0 +1,14 @@ +server_names_hash_bucket_size 512; +client_header_buffer_size 32k; +client_max_body_size 50m; +keepalive_timeout 60; + +gzip on; +gzip_min_length 1k; +gzip_buffers 4 16k; +gzip_http_version 1.1; +gzip_comp_level 2; +gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml; +gzip_vary on; +gzip_proxied expired no-cache no-store private auth; +gzip_disable "MSIE [1-6]\."; \ No newline at end of file diff --git a/cmd/server/nginx_conf/nginx_conf.go b/cmd/server/nginx_conf/nginx_conf.go index ec674a9d9..1ffad8997 100644 --- a/cmd/server/nginx_conf/nginx_conf.go +++ b/cmd/server/nginx_conf/nginx_conf.go @@ -18,3 +18,6 @@ var Limit []byte //go:embed index.html var Index []byte + +//go:embed http_per.conf +var HttpPer []byte diff --git a/frontend/src/api/interface/nginx.ts b/frontend/src/api/interface/nginx.ts index a7785ba70..c398c144d 100644 --- a/frontend/src/api/interface/nginx.ts +++ b/frontend/src/api/interface/nginx.ts @@ -1 +1,17 @@ -export namespace Nginx {} +export namespace Nginx { + export interface NginxScopeReq { + scope: string; + } + export interface NginxParam { + name: string; + secondKey: string; + params: string[]; + } + + export interface NginxConfigReq { + operate: string; + websiteId?: number; + scope: string; + params?: any; + } +} diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 22f3e1dbf..03537b946 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -94,7 +94,6 @@ export namespace WebSite { export interface NginxParam { name: string; secondKey: string; - isRepeatKey: string; params: string[]; } diff --git a/frontend/src/api/modules/nginx.ts b/frontend/src/api/modules/nginx.ts index 8c0525bdc..3f734fd30 100644 --- a/frontend/src/api/modules/nginx.ts +++ b/frontend/src/api/modules/nginx.ts @@ -1,6 +1,15 @@ import http from '@/api'; import { File } from '../interface/file'; +import { Nginx } from '../interface/nginx'; export const GetNginx = () => { return http.get(`/nginx`); }; + +export const GetNginxConfigByScope = (req: Nginx.NginxScopeReq) => { + return http.post(`/nginx/scope`, req); +}; + +export const UpdateNginxConfigByScope = (req: Nginx.NginxConfigReq) => { + return http.post(`/nginx/update`, req); +}; diff --git a/frontend/src/components/app-status/index.vue b/frontend/src/components/app-status/index.vue index 8920628e2..863f9f0bb 100644 --- a/frontend/src/components/app-status/index.vue +++ b/frontend/src/components/app-status/index.vue @@ -29,6 +29,7 @@ {{ $t('app.restart') }} + {{ $t('commons.button.set') }} diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 8abb80dd3..ea922a7b3 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -759,5 +759,15 @@ export default { security: '安全', backup: '备份', log: '日志', + nginxPer: '性能调整', + }, + nginx: { + serverNamesHashBucketSizeHelper: '服务器名字的hash表大小', + clientHeaderBufferSizeHelper: '客户端请求的头buffer大小', + clientMaxBodySizeHelper: '最大上传文件', + keepaliveTimeoutHelper: '连接超时时间', + gzipMinLengthHelper: '最小压缩文件', + gzipCompLevelHelper: '压缩率', + gzipHelper: '是否开启压缩传输', }, }; diff --git a/frontend/src/views/website/website/config/basic/limit-conn/index.vue b/frontend/src/views/website/website/config/basic/limit-conn/index.vue index 1f42a1781..c7a2d3046 100644 --- a/frontend/src/views/website/website/config/basic/limit-conn/index.vue +++ b/frontend/src/views/website/website/config/basic/limit-conn/index.vue @@ -76,7 +76,6 @@ const search = (req: WebSite.NginxConfigReq) => { } } if (param.name === 'limit_rate') { - console.log(param.params[0].match(/\d+/g)?.join('')); form.rate = Number(param.params[0].match(/\d+/g)); } } diff --git a/frontend/src/views/website/website/index.vue b/frontend/src/views/website/website/index.vue index 5b5fbdb11..f5fcdfdf4 100644 --- a/frontend/src/views/website/website/index.vue +++ b/frontend/src/views/website/website/index.vue @@ -1,45 +1,52 @@ diff --git a/frontend/src/views/website/website/nginx/source/index.vue b/frontend/src/views/website/website/nginx/source/index.vue index 5d32ef824..4a4378542 100644 --- a/frontend/src/views/website/website/nginx/source/index.vue +++ b/frontend/src/views/website/website/nginx/source/index.vue @@ -14,7 +14,7 @@ v-model="content" :readOnly="true" /> -
+
{{ $t('commons.button.save') }}