diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index 11bdffc6..11a58728 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -219,6 +219,14 @@ func (this *RPCClient) HTTPCachePolicyRPC() pb.HTTPCachePolicyServiceClient { return pb.NewHTTPCachePolicyServiceClient(this.pickConn()) } +func (this *RPCClient) HTTPCacheTaskRPC() pb.HTTPCacheTaskServiceClient { + return pb.NewHTTPCacheTaskServiceClient(this.pickConn()) +} + +func (this *RPCClient) HTTPCacheTaskKeyRPC() pb.HTTPCacheTaskKeyServiceClient { + return pb.NewHTTPCacheTaskKeyServiceClient(this.pickConn()) +} + func (this *RPCClient) HTTPFirewallPolicyRPC() pb.HTTPFirewallPolicyServiceClient { return pb.NewHTTPFirewallPolicyServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/servers/components/cache/batch/deleteTask.go b/internal/web/actions/default/servers/components/cache/batch/deleteTask.go new file mode 100644 index 00000000..e3079033 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/deleteTask.go @@ -0,0 +1,28 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type DeleteTaskAction struct { + actionutils.ParentAction +} + +func (this *DeleteTaskAction) RunPost(params struct { + TaskId int64 +}) { + defer this.CreateLogInfo("删除缓存任务 %d", params.TaskId) + + _, err := this.RPC().HTTPCacheTaskRPC().DeleteHTTPCacheTask(this.AdminContext(), &pb.DeleteHTTPCacheTaskRequest{ + HttpCacheTaskId: params.TaskId, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/fetch.go b/internal/web/actions/default/servers/components/cache/batch/fetch.go new file mode 100644 index 00000000..e48192c5 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/fetch.go @@ -0,0 +1,96 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "strings" +) + +type FetchAction struct { + actionutils.ParentAction +} + +func (this *FetchAction) Init() { + this.Nav("", "", "fetch") +} + +func (this *FetchAction) RunGet(params struct{}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + } + + this.Show() +} + +func (this *FetchAction) RunPost(params struct { + Keys string + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("批量预热缓存Key") + + if len(params.Keys) == 0 { + this.Fail("请输入要预热的Key列表") + } + + // 检查Key + var realKeys = []string{} + for _, key := range strings.Split(params.Keys, "\n") { + key = strings.TrimSpace(key) + if len(key) == 0 { + continue + } + if lists.ContainsString(realKeys, key) { + continue + } + realKeys = append(realKeys, key) + } + + if len(realKeys) == 0 { + this.Fail("请输入要预热的Key列表") + } + + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) + if err != nil { + this.ErrorPage(err) + return + } + + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) + } + } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } + + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/index.go b/internal/web/actions/default/servers/components/cache/batch/index.go new file mode 100644 index 00000000..66c93d09 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/index.go @@ -0,0 +1,97 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "strings" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "purge") +} + +func (this *IndexAction) RunGet(params struct{}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + } + + this.Show() +} + +func (this *IndexAction) RunPost(params struct { + KeyType string + Keys string + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("批量刷新缓存Key") + + if len(params.Keys) == 0 { + this.Fail("请输入要刷新的Key列表") + } + + // 检查Key + var realKeys = []string{} + for _, key := range strings.Split(params.Keys, "\n") { + key = strings.TrimSpace(key) + if len(key) == 0 { + continue + } + if lists.ContainsString(realKeys, key) { + continue + } + realKeys = append(realKeys, key) + } + + if len(realKeys) == 0 { + this.Fail("请输入要刷新的Key列表") + } + + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) + if err != nil { + this.ErrorPage(err) + return + } + + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) + } + } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } + + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/init.go b/internal/web/actions/default/servers/components/cache/batch/init.go new file mode 100644 index 00000000..e4695be9 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/init.go @@ -0,0 +1,24 @@ +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)). + Data("teaMenu", "servers"). + Data("teaSubMenu", "cacheBatch"). + Prefix("/servers/components/cache/batch"). + GetPost("", new(IndexAction)). + GetPost("/fetch", new(FetchAction)). + Get("/tasks", new(TasksAction)). + Get("/task", new(TaskAction)). + Post("/deleteTask", new(DeleteTaskAction)). + Post("/resetTask", new(ResetTaskAction)). + EndAll() + }) +} diff --git a/internal/web/actions/default/servers/components/cache/batch/resetTask.go b/internal/web/actions/default/servers/components/cache/batch/resetTask.go new file mode 100644 index 00000000..c41b579e --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/resetTask.go @@ -0,0 +1,26 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type ResetTaskAction struct { + actionutils.ParentAction +} + +func (this *ResetTaskAction) RunPost(params struct { + TaskId int64 +}) { + this.CreateLogInfo("重置缓存任务 %d 状态", params.TaskId) + + _, err := this.RPC().HTTPCacheTaskRPC().ResetHTTPCacheTask(this.AdminContext(), &pb.ResetHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId}) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/task.go b/internal/web/actions/default/servers/components/cache/batch/task.go new file mode 100644 index 00000000..abd8018c --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/task.go @@ -0,0 +1,104 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" + "sort" +) + +type TaskAction struct { + actionutils.ParentAction +} + +func (this *TaskAction) Init() { + this.Nav("", "", "task") +} + +func (this *TaskAction) RunGet(params struct { + TaskId int64 +}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + return + } + + taskResp, err := this.RPC().HTTPCacheTaskRPC().FindEnabledHTTPCacheTask(this.AdminContext(), &pb.FindEnabledHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId}) + if err != nil { + this.ErrorPage(err) + return + } + var task = taskResp.HttpCacheTask + if task == nil { + this.NotFound("HTTPCacheTask", params.TaskId) + return + } + + // 用户 + var userMap = maps.Map{"id": 0, "username": "", "fullname": ""} + if task.User != nil { + userMap = maps.Map{ + "id": task.User.Id, + "username": task.User.Username, + "fullname": task.User.Fullname, + } + } + + // keys + var keyMaps = []maps.Map{} + for _, key := range task.HttpCacheTaskKeys { + // 错误信息 + var errorMaps = []maps.Map{} + + if len(key.ErrorsJSON) > 0 { + var m = map[int64]string{} + err = json.Unmarshal(key.ErrorsJSON, &m) + if err != nil { + this.ErrorPage(err) + return + } + for nodeId, errString := range m { + errorMaps = append(errorMaps, maps.Map{ + "nodeId": nodeId, + "error": errString, + }) + } + } + + // 错误信息排序 + if len(errorMaps) > 0 { + sort.Slice(errorMaps, func(i, j int) bool { + var m1 = errorMaps[i] + var m2 = errorMaps[j] + + return m1.GetInt64("nodeId") < m2.GetInt64("nodeId") + }) + } + + keyMaps = append(keyMaps, maps.Map{ + "key": key.Key, + "isDone": key.IsDone, + "errors": errorMaps, + }) + } + + this.Data["task"] = maps.Map{ + "id": task.Id, + "type": task.Type, + "keyType": task.KeyType, + "createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt), + "doneTime": timeutil.FormatTime("Y-m-d H:i:s", task.DoneAt), + "isDone": task.IsDone, + "isOk": task.IsOk, + "keys": keyMaps, + "user": userMap, + } + + this.Show() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/tasks.go b/internal/web/actions/default/servers/components/cache/batch/tasks.go new file mode 100644 index 00000000..b5b97255 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/tasks.go @@ -0,0 +1,72 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" +) + +type TasksAction struct { + actionutils.ParentAction +} + +func (this *TasksAction) Init() { + this.Nav("", "", "task") +} + +func (this *TasksAction) RunGet(params struct{}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + } + + // 任务数量 + countResp, err := this.RPC().HTTPCacheTaskRPC().CountHTTPCacheTasks(this.AdminContext(), &pb.CountHTTPCacheTasksRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + var count = countResp.Count + var page = this.NewPage(count) + this.Data["page"] = page.AsHTML() + + // 任务列表 + var taskMaps = []maps.Map{} + tasksResp, err := this.RPC().HTTPCacheTaskRPC().ListHTTPCacheTasks(this.AdminContext(), &pb.ListHTTPCacheTasksRequest{ + Offset: page.Offset, + Size: page.Size, + }) + if err != nil { + this.ErrorPage(err) + return + } + for _, task := range tasksResp.HttpCacheTasks { + var userMap = maps.Map{"id": 0, "username": "", "fullname": ""} + if task.User != nil { + userMap = maps.Map{ + "id": task.User.Id, + "username": task.User.Username, + "fullname": task.User.Fullname, + } + } + + taskMaps = append(taskMaps, maps.Map{ + "id": task.Id, + "type": task.Type, + "keyType": task.KeyType, + "isDone": task.IsDone, + "isOk": task.IsOk, + "createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt), + "description": task.Description, + "user": userMap, + }) + } + + this.Data["tasks"] = taskMaps + + this.Show() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/utils.go b/internal/web/actions/default/servers/components/cache/batch/utils.go new file mode 100644 index 00000000..ff1e3d49 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/utils.go @@ -0,0 +1,24 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/rpc" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +func InitMenu(parent *actionutils.ParentAction) error { + rpcClient, err := rpc.SharedRPC() + if err != nil { + return err + } + + countTasksResp, err := rpcClient.HTTPCacheTaskRPC().CountDoingHTTPCacheTasks(parent.AdminContext(), &pb.CountDoingHTTPCacheTasksRequest{}) + if err != nil { + return err + } + + parent.Data["countDoingTasks"] = countTasksResp.Count + return nil +} diff --git a/internal/web/actions/default/servers/components/cache/cacheutils/utils.go b/internal/web/actions/default/servers/components/cache/cacheutils/utils.go index d3fb9ab8..bef513b6 100644 --- a/internal/web/actions/default/servers/components/cache/cacheutils/utils.go +++ b/internal/web/actions/default/servers/components/cache/cacheutils/utils.go @@ -8,7 +8,7 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" ) -// 查找缓存策略名称并忽略错误 +// FindCachePolicyNameWithoutError 查找缓存策略名称并忽略错误 func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePolicyId int64) string { policy, err := FindCachePolicy(parent, cachePolicyId) if err != nil { @@ -20,7 +20,7 @@ func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePoli return policy.Name } -// 查找缓存策略配置 +// FindCachePolicy 查找缓存策略配置 func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*serverconfigs.HTTPCachePolicy, error) { resp, err := parent.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(parent.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId}) if err != nil { @@ -36,3 +36,20 @@ func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*se } return config, nil } + +// KeyFailReason Key相关失败原因 +func KeyFailReason(reasonCode string) string { + switch reasonCode { + case "requireKey": + return "空的Key" + case "requireDomain": + return "找不到Key对应的域名" + case "requireServer": + return "找不到Key对应的网站服务" + case "requireUser": + return "该域名不属于当前用户" + case "requireClusterId": + return "该网站没有部署到集群" + } + return "未知错误" +} diff --git a/internal/web/actions/default/servers/components/cache/preheat.go b/internal/web/actions/default/servers/components/cache/fetch.go similarity index 66% rename from internal/web/actions/default/servers/components/cache/preheat.go rename to internal/web/actions/default/servers/components/cache/fetch.go index 557a2d98..f87529cd 100644 --- a/internal/web/actions/default/servers/components/cache/preheat.go +++ b/internal/web/actions/default/servers/components/cache/fetch.go @@ -3,8 +3,7 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" @@ -15,15 +14,15 @@ import ( "strings" ) -type PreheatAction struct { +type FetchAction struct { actionutils.ParentAction } -func (this *PreheatAction) Init() { - this.Nav("", "", "preheat") +func (this *FetchAction) Init() { + this.Nav("", "", "fetch") } -func (this *PreheatAction) RunGet(params struct { +func (this *FetchAction) RunGet(params struct { CachePolicyId int64 }) { // 默认的集群ID @@ -50,7 +49,7 @@ func (this *PreheatAction) RunGet(params struct { this.Show() } -func (this *PreheatAction) RunPost(params struct { +func (this *FetchAction) RunPost(params struct { CachePolicyId int64 ClusterId int64 Keys string @@ -92,27 +91,38 @@ func (this *PreheatAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PreheatCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + // 校验Key + // 这里暂时不校验服务ID + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/components/cache/init.go b/internal/web/actions/default/servers/components/cache/init.go index 79b33b9a..1f85412e 100644 --- a/internal/web/actions/default/servers/components/cache/init.go +++ b/internal/web/actions/default/servers/components/cache/init.go @@ -19,7 +19,7 @@ func init() { Get("/policy", new(PolicyAction)). GetPost("/update", new(UpdateAction)). GetPost("/clean", new(CleanAction)). - GetPost("/preheat", new(PreheatAction)). + GetPost("/fetch", new(FetchAction)). GetPost("/purge", new(PurgeAction)). GetPost("/stat", new(StatAction)). GetPost("/test", new(TestAction)). diff --git a/internal/web/actions/default/servers/components/cache/purge.go b/internal/web/actions/default/servers/components/cache/purge.go index 191cdbe0..f9bdabf8 100644 --- a/internal/web/actions/default/servers/components/cache/purge.go +++ b/internal/web/actions/default/servers/components/cache/purge.go @@ -3,8 +3,7 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" @@ -53,7 +52,7 @@ func (this *PurgeAction) RunGet(params struct { func (this *PurgeAction) RunPost(params struct { CachePolicyId int64 ClusterId int64 - Type string + KeyType string Keys string Must *actions.Must }) { @@ -91,33 +90,37 @@ func (this *PurgeAction) RunPost(params struct { } realKeys = append(realKeys, key) } - - // 发送命令 - msg := &messageconfigs.PurgeCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - if params.Type == "prefix" { - msg.Type = messageconfigs.PurgeCacheMessageTypeDir - } else { - msg.Type = messageconfigs.PurgeCacheMessageTypeFile - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodePurgeCache, msg, 10) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/server/settings/cache/preheat.go b/internal/web/actions/default/servers/groups/group/settings/cache/fetch.go similarity index 70% rename from internal/web/actions/default/servers/server/settings/cache/preheat.go rename to internal/web/actions/default/servers/groups/group/settings/cache/fetch.go index b9099d73..17b0b9f3 100644 --- a/internal/web/actions/default/servers/server/settings/cache/preheat.go +++ b/internal/web/actions/default/servers/groups/group/settings/cache/fetch.go @@ -5,25 +5,26 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) -type PreheatAction struct { +type FetchAction struct { actionutils.ParentAction } -func (this *PreheatAction) Init() { - this.Nav("", "setting", "preheat") +func (this *FetchAction) Init() { + this.Nav("", "setting", "fetch") this.SecondMenu("cache") } -func (this *PreheatAction) RunGet(params struct { +func (this *FetchAction) RunGet(params struct { ServerId int64 }) { webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) @@ -38,7 +39,7 @@ func (this *PreheatAction) RunGet(params struct { this.Show() } -func (this *PreheatAction) RunPost(params struct { +func (this *FetchAction) RunPost(params struct { ServerId int64 WebId int64 Keys string @@ -117,27 +118,38 @@ func (this *PreheatAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PreheatCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/groups/group/settings/cache/init.go b/internal/web/actions/default/servers/groups/group/settings/cache/init.go index 92a1347c..4b26eea6 100644 --- a/internal/web/actions/default/servers/groups/group/settings/cache/init.go +++ b/internal/web/actions/default/servers/groups/group/settings/cache/init.go @@ -15,7 +15,7 @@ func init() { Prefix("/servers/groups/group/settings/cache"). GetPost("", new(IndexAction)). GetPost("/purge", new(PurgeAction)). - GetPost("/preheat", new(PreheatAction)). + GetPost("/fetch", new(FetchAction)). EndAll() }) } diff --git a/internal/web/actions/default/servers/groups/group/settings/cache/purge.go b/internal/web/actions/default/servers/groups/group/settings/cache/purge.go index e18fe292..59faf87c 100644 --- a/internal/web/actions/default/servers/groups/group/settings/cache/purge.go +++ b/internal/web/actions/default/servers/groups/group/settings/cache/purge.go @@ -5,12 +5,13 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) @@ -41,7 +42,7 @@ func (this *PurgeAction) RunGet(params struct { func (this *PurgeAction) RunPost(params struct { ServerId int64 WebId int64 - Type string + KeyType string Keys string Must *actions.Must @@ -118,32 +119,37 @@ func (this *PurgeAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PurgeCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - if params.Type == "prefix" { - msg.Type = messageconfigs.PurgeCacheMessageTypeDir - } else { - msg.Type = messageconfigs.PurgeCacheMessageTypeFile - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/groups/group/settings/cache/preheat.go b/internal/web/actions/default/servers/server/settings/cache/fetch.go similarity index 70% rename from internal/web/actions/default/servers/groups/group/settings/cache/preheat.go rename to internal/web/actions/default/servers/server/settings/cache/fetch.go index b9099d73..7f6054ce 100644 --- a/internal/web/actions/default/servers/groups/group/settings/cache/preheat.go +++ b/internal/web/actions/default/servers/server/settings/cache/fetch.go @@ -5,25 +5,26 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) -type PreheatAction struct { +type FetchAction struct { actionutils.ParentAction } -func (this *PreheatAction) Init() { - this.Nav("", "setting", "preheat") +func (this *FetchAction) Init() { + this.Nav("", "setting", "fetch") this.SecondMenu("cache") } -func (this *PreheatAction) RunGet(params struct { +func (this *FetchAction) RunGet(params struct { ServerId int64 }) { webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) @@ -38,7 +39,7 @@ func (this *PreheatAction) RunGet(params struct { this.Show() } -func (this *PreheatAction) RunPost(params struct { +func (this *FetchAction) RunPost(params struct { ServerId int64 WebId int64 Keys string @@ -117,27 +118,37 @@ func (this *PreheatAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PreheatCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/server/settings/cache/init.go b/internal/web/actions/default/servers/server/settings/cache/init.go index 9a814079..68677088 100644 --- a/internal/web/actions/default/servers/server/settings/cache/init.go +++ b/internal/web/actions/default/servers/server/settings/cache/init.go @@ -16,7 +16,7 @@ func init() { GetPost("", new(IndexAction)). GetPost("/createPopup", new(CreatePopupAction)). GetPost("/purge", new(PurgeAction)). - GetPost("/preheat", new(PreheatAction)). + GetPost("/fetch", new(FetchAction)). Post("/updateRefs", new(UpdateRefsAction)). EndAll() }) diff --git a/internal/web/actions/default/servers/server/settings/cache/purge.go b/internal/web/actions/default/servers/server/settings/cache/purge.go index e18fe292..59faf87c 100644 --- a/internal/web/actions/default/servers/server/settings/cache/purge.go +++ b/internal/web/actions/default/servers/server/settings/cache/purge.go @@ -5,12 +5,13 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) @@ -41,7 +42,7 @@ func (this *PurgeAction) RunGet(params struct { func (this *PurgeAction) RunPost(params struct { ServerId int64 WebId int64 - Type string + KeyType string Keys string Must *actions.Must @@ -118,32 +119,37 @@ func (this *PurgeAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PurgeCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - if params.Type == "prefix" { - msg.Type = messageconfigs.PurgeCacheMessageTypeDir - } else { - msg.Type = messageconfigs.PurgeCacheMessageTypeFile - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/helpers/menu.go b/internal/web/helpers/menu.go index 283a54a7..275fab03 100644 --- a/internal/web/helpers/menu.go +++ b/internal/web/helpers/menu.go @@ -34,11 +34,26 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread "url": "/servers/certs", "code": "cert", }, + { + "name": "服务分组", + "url": "/servers/groups", + "code": "group", + }, + { + "name": "-", + "url": "", + "code": "", + }, { "name": "缓存策略", "url": "/servers/components/cache", "code": "cache", }, + { + "name": "刷新预热", + "url": "/servers/components/cache/batch", + "code": "cacheBatch", + }, { "name": "-", "url": "", @@ -60,11 +75,6 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread "url": "", "code": "", }, - { - "name": "服务分组", - "url": "/servers/groups", - "code": "group", - }, { "name": "统计指标", "url": "/servers/metrics", diff --git a/web/public/js/components.js b/web/public/js/components.js index d4a03be6..d1fce1ba 100644 --- a/web/public/js/components.js +++ b/web/public/js/components.js @@ -333,7 +333,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio - + - + @@ -1356,7 +1356,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio @@ -1552,7 +1552,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio - + - + - + - + - + @@ -2872,7 +2872,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio - + - +
是否启用启用
@@ -402,7 +402,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否启用启用 PURGE Key * -

[随机生成]。需要在PURGE方法调用时加入Edge-Purge-Key: {{cacheConfig.purgeKey}} Header。只能包含字符、数字、下划线。

+

[随机生成]。需要在PURGE方法调用时加入X-Edge-Purge-Key: {{cacheConfig.purgeKey}} Header。只能包含字符、数字、下划线。

是否启用配置启用配置
@@ -2356,7 +2356,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否开启开启
@@ -2407,7 +2407,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否启用启用
@@ -2516,7 +2516,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否启用启用
@@ -2558,7 +2558,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否启用启用

启用后,将会在响应的Header中添加Expires字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。

是否启用反向代理启用反向代理
@@ -3377,7 +3377,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否启用配置启用配置
@@ -3868,7 +3868,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio - + - +
是否启用启用

启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。

@@ -4178,7 +4178,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
是否自动下线自动下线
diff --git a/web/public/js/components.src.js b/web/public/js/components.src.js index 75941881..46d5b3b4 100755 --- a/web/public/js/components.src.js +++ b/web/public/js/components.src.js @@ -1318,7 +1318,7 @@ Vue.component("ns-recursion-config-box", { - + - + @@ -4250,7 +4250,7 @@ Vue.component("http-cache-config-box", { @@ -5089,7 +5089,7 @@ Vue.component("http-websocket-box", { - + - + - + - + - + @@ -8431,7 +8431,7 @@ Vue.component("reverse-proxy-box", { - + - +
是否启用启用
@@ -1408,7 +1408,7 @@ Vue.component("ns-access-log-ref-box", {
是否启用启用 PURGE Key * -

[随机生成]。需要在PURGE方法调用时加入Edge-Purge-Key: {{cacheConfig.purgeKey}} Header。只能包含字符、数字、下划线。

+

[随机生成]。需要在PURGE方法调用时加入X-Edge-Purge-Key: {{cacheConfig.purgeKey}} Header。只能包含字符、数字、下划线。

是否启用配置启用配置
@@ -7096,7 +7096,7 @@ Vue.component("http-pages-and-shutdown-box", {
是否开启开启
@@ -7294,7 +7294,7 @@ Vue.component("http-compression-config-box", {
是否启用启用
@@ -7489,7 +7489,7 @@ Vue.component("http-charsets-box", {
是否启用启用
@@ -7570,7 +7570,7 @@ Vue.component("http-expires-time-config-box", {
是否启用启用

启用后,将会在响应的Header中添加Expires字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。

是否启用反向代理启用反向代理
@@ -9548,7 +9548,7 @@ Vue.component("http-fastcgi-box", {
是否启用配置启用配置
@@ -11063,7 +11063,7 @@ Vue.component("firewall-syn-flood-config-box", { - + - + - + - + diff --git a/web/public/js/components/ns/ns-recursion-config-box.js b/web/public/js/components/ns/ns-recursion-config-box.js index 81e8cd40..4470bf7c 100644 --- a/web/public/js/components/ns/ns-recursion-config-box.js +++ b/web/public/js/components/ns/ns-recursion-config-box.js @@ -98,7 +98,7 @@ Vue.component("ns-recursion-config-box", {
是否启用启用

启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。

@@ -12675,7 +12675,7 @@ Vue.component("health-check-config-box", {
是否自动下线自动下线
diff --git a/web/public/js/components/common/health-check-config-box.js b/web/public/js/components/common/health-check-config-box.js index d76e77fa..380f0baf 100644 --- a/web/public/js/components/common/health-check-config-box.js +++ b/web/public/js/components/common/health-check-config-box.js @@ -215,7 +215,7 @@ Vue.component("health-check-config-box", {
是否自动下线自动下线
diff --git a/web/public/js/components/ns/ns-access-log-ref-box.js b/web/public/js/components/ns/ns-access-log-ref-box.js index 625730f0..848e377f 100644 --- a/web/public/js/components/ns/ns-access-log-ref-box.js +++ b/web/public/js/components/ns/ns-access-log-ref-box.js @@ -22,7 +22,7 @@ Vue.component("ns-access-log-ref-box", {
是否启用启用
- +
是否启用启用
diff --git a/web/public/js/components/server/firewall-syn-flood-config-box.js b/web/public/js/components/server/firewall-syn-flood-config-box.js index 4220e30f..48cdfc31 100644 --- a/web/public/js/components/server/firewall-syn-flood-config-box.js +++ b/web/public/js/components/server/firewall-syn-flood-config-box.js @@ -56,7 +56,7 @@ Vue.component("firewall-syn-flood-config-box", { - + diff --git a/web/public/js/components/server/http-charsets-box.js b/web/public/js/components/server/http-charsets-box.js index 088fcf4c..44629e40 100644 --- a/web/public/js/components/server/http-charsets-box.js +++ b/web/public/js/components/server/http-charsets-box.js @@ -26,7 +26,7 @@ Vue.component("http-charsets-box", { - + - + - + diff --git a/web/public/js/components/server/http-fastcgi-box.js b/web/public/js/components/server/http-fastcgi-box.js index 58bac798..719a1a5c 100644 --- a/web/public/js/components/server/http-fastcgi-box.js +++ b/web/public/js/components/server/http-fastcgi-box.js @@ -61,7 +61,7 @@ Vue.component("http-fastcgi-box", { - + - + - + - + - +
是否启用启用

启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。

diff --git a/web/public/js/components/server/http-cache-config-box.js b/web/public/js/components/server/http-cache-config-box.js index 38988d77..984dc439 100644 --- a/web/public/js/components/server/http-cache-config-box.js +++ b/web/public/js/components/server/http-cache-config-box.js @@ -125,7 +125,7 @@ Vue.component("http-cache-config-box", {
PURGE Key * -

[随机生成]。需要在PURGE方法调用时加入Edge-Purge-Key: {{cacheConfig.purgeKey}} Header。只能包含字符、数字、下划线。

+

[随机生成]。需要在PURGE方法调用时加入X-Edge-Purge-Key: {{cacheConfig.purgeKey}} Header。只能包含字符、数字、下划线。

是否启用启用
diff --git a/web/public/js/components/server/http-compression-config-box.js b/web/public/js/components/server/http-compression-config-box.js index 60fa6e82..024744bc 100644 --- a/web/public/js/components/server/http-compression-config-box.js +++ b/web/public/js/components/server/http-compression-config-box.js @@ -148,7 +148,7 @@ Vue.component("http-compression-config-box", {
是否启用启用
diff --git a/web/public/js/components/server/http-expires-time-config-box.js b/web/public/js/components/server/http-expires-time-config-box.js index 9afc8b2c..41b8e53e 100644 --- a/web/public/js/components/server/http-expires-time-config-box.js +++ b/web/public/js/components/server/http-expires-time-config-box.js @@ -39,7 +39,7 @@ Vue.component("http-expires-time-config-box", {
是否启用启用

启用后,将会在响应的Header中添加Expires字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。

是否启用配置启用配置
diff --git a/web/public/js/components/server/http-pages-and-shutdown-box.js b/web/public/js/components/server/http-pages-and-shutdown-box.js index 76404981..b68df276 100644 --- a/web/public/js/components/server/http-pages-and-shutdown-box.js +++ b/web/public/js/components/server/http-pages-and-shutdown-box.js @@ -114,7 +114,7 @@ Vue.component("http-pages-and-shutdown-box", {
是否开启开启
diff --git a/web/public/js/components/server/http-websocket-box.js b/web/public/js/components/server/http-websocket-box.js index 0623b66e..333ef726 100644 --- a/web/public/js/components/server/http-websocket-box.js +++ b/web/public/js/components/server/http-websocket-box.js @@ -80,7 +80,7 @@ Vue.component("http-websocket-box", {
是否启用配置启用配置
diff --git a/web/public/js/components/server/reverse-proxy-box.js b/web/public/js/components/server/reverse-proxy-box.js index cce35a90..33a967b0 100644 --- a/web/public/js/components/server/reverse-proxy-box.js +++ b/web/public/js/components/server/reverse-proxy-box.js @@ -158,7 +158,7 @@ Vue.component("reverse-proxy-box", {
是否启用反向代理启用反向代理
diff --git a/web/views/@default/clusters/cluster/node/update.html b/web/views/@default/clusters/cluster/node/update.html index 95dfbdd5..4d0003ba 100644 --- a/web/views/@default/clusters/cluster/node/update.html +++ b/web/views/@default/clusters/cluster/node/update.html @@ -55,7 +55,7 @@
是否启用启用节点
diff --git a/web/views/@default/servers/components/cache/@policy_menu.html b/web/views/@default/servers/components/cache/@policy_menu.html index 26de2c11..a2f756b4 100644 --- a/web/views/@default/servers/components/cache/@policy_menu.html +++ b/web/views/@default/servers/components/cache/@policy_menu.html @@ -6,6 +6,6 @@ 统计 清理 删除 - 预热 + 预热 修改 diff --git a/web/views/@default/servers/components/cache/batch/@menu.html b/web/views/@default/servers/components/cache/batch/@menu.html new file mode 100644 index 00000000..a1246760 --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/@menu.html @@ -0,0 +1,6 @@ + + 刷新缓存 + 预热缓存 + | + 所有任务({{countDoingTasks}}) + \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/fetch.html b/web/views/@default/servers/components/cache/batch/fetch.html new file mode 100644 index 00000000..d7937a47 --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/fetch.html @@ -0,0 +1,28 @@ +{$layout} +{$template "menu"} + +
+ + + + + + + + + + +
要预热的Key列表 + +

每行一个Key。

+
操作结果 +
数据发送中...
+ 失败:{{message}} +
+
+ {{failKey.key}}: {{failKey.reason}} +
+
+
+ 提交 +
\ No newline at end of file diff --git a/web/views/@default/servers/groups/group/settings/cache/preheat.js b/web/views/@default/servers/components/cache/batch/fetch.js similarity index 67% rename from web/views/@default/servers/groups/group/settings/cache/preheat.js rename to web/views/@default/servers/components/cache/batch/fetch.js index 121c5489..3e09a3f2 100644 --- a/web/views/@default/servers/groups/group/settings/cache/preheat.js +++ b/web/views/@default/servers/components/cache/batch/fetch.js @@ -2,22 +2,28 @@ Tea.context(function () { this.isRequesting = false this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] this.before = function () { this.isRequesting = true this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] } this.success = function (resp) { this.isOk = true - this.results = resp.data.results + + let f = NotifyReloadSuccess("任务提交成功") + f() } this.fail = function (resp) { this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } } this.done = function () { diff --git a/web/views/@default/servers/components/cache/batch/index.css b/web/views/@default/servers/components/cache/batch/index.css new file mode 100644 index 00000000..1cb0c2af --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/index.css @@ -0,0 +1,8 @@ +.fail-keys-box { + max-height: 10em; + overflow-y: auto; +} +.fail-keys-box::-webkit-scrollbar { + width: 6px; +} +/*# sourceMappingURL=index.css.map */ \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/index.css.map b/web/views/@default/servers/components/cache/batch/index.css.map new file mode 100644 index 00000000..b712b7da --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/index.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,gBAAA;EACA,gBAAA;;AAGD,cAAc;EACb,UAAA","file":"index.css"} \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/index.html b/web/views/@default/servers/components/cache/batch/index.html new file mode 100644 index 00000000..8ad9172d --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/index.html @@ -0,0 +1,41 @@ +{$layout} +{$template "menu"} + +
+ +
+ + + + + + + + + + + + + + +
缓存Key类型 + 根据Key   + 根据前缀 +
+ 要刷新的Key列表 + 要刷新的Key前缀列表 + + +

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

+

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

+
操作结果 +
数据发送中...
+ 失败:{{message}} +
+
+ {{failKey.key}}: {{failKey.reason}} +
+
+
+ 提交 +
\ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/index.js b/web/views/@default/servers/components/cache/batch/index.js new file mode 100644 index 00000000..ff18a9da --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/index.js @@ -0,0 +1,43 @@ +Tea.context(function () { + this.isRequesting = false + this.isOk = false + this.message = "" + this.failKeys = [] + + this.$delay(function () { + this.$refs.keysBox.focus() + this.$watch("keyType", function () { + this.$refs.keysBox.focus() + }) + }) + + this.before = function () { + this.isRequesting = true + this.isOk = false + this.message = "" + this.failKeys = [] + } + + this.success = function () { + this.isOk = true + let f = NotifyReloadSuccess("任务提交成功") + f() + } + + this.fail = function (resp) { + this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } + } + + this.done = function () { + this.isRequesting = false + } + + /** + * 操作类型 + */ + this.keyType = "key" // key | prefix +}) \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/index.less b/web/views/@default/servers/components/cache/batch/index.less new file mode 100644 index 00000000..cd3e669d --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/index.less @@ -0,0 +1,8 @@ +.fail-keys-box { + max-height: 10em; + overflow-y: auto; +} + +.fail-keys-box::-webkit-scrollbar { + width: 6px; +} \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/task.html b/web/views/@default/servers/components/cache/batch/task.html new file mode 100644 index 00000000..24664a09 --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/task.html @@ -0,0 +1,94 @@ +{$layout} +{$template "menu"} + + + 所有任务 + » + 任务详情 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
任务编号{{task.id}}
任务类型 + 刷新 + 预热 +
Key类型 + URL + 前缀 +
创建时间 + {{task.createdTime}} +
完成时间 + {{task.doneTime}} + 尚未完成 +
所属用户 + + - +
任务状态 + 已完成 + 失败 + 等待执行 +
操作 + [删除]     + [重置状态] +
+ +

要操作的缓存Key

+ + + + + + + + + + + + + +
+ URL + 前缀 + 状态
{{key.key}} + + + + 完成 + 失败 + 未执行 +
\ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/task.js b/web/views/@default/servers/components/cache/batch/task.js new file mode 100644 index 00000000..abbf9e92 --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/task.js @@ -0,0 +1,23 @@ +Tea.context(function () { + this.deleteTask = function (taskId) { + teaweb.confirm("确定要删除此任务吗?", function () { + this.$post(".deleteTask") + .params({ + taskId: taskId + }) + .success(function () { + window.location = Tea.url(".tasks") + }) + }) + } + + this.resetTask = function (taskId) { + teaweb.confirm("确定要重置任务状态吗?", function () { + this.$post(".resetTask") + .params({ + taskId: taskId + }) + .refresh() + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/tasks.html b/web/views/@default/servers/components/cache/batch/tasks.html new file mode 100644 index 00000000..17bd218f --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/tasks.html @@ -0,0 +1,48 @@ +{$layout} +{$template "menu"} + +

暂时还没有任务。

+ + + + + + + + + + + + + + + + + + + + + + + + +
任务编号任务类型Key类型创建时间所属用户任务状态操作
{{task.id}} + 刷新 + 预热 + + URL + 前缀 + {{task.createdTime}} + + {{task.description}} + - + + 已完成 + 失败 + 等待执行 + + 详情   + 删除 +
+ + \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/batch/tasks.js b/web/views/@default/servers/components/cache/batch/tasks.js new file mode 100644 index 00000000..5a74fddc --- /dev/null +++ b/web/views/@default/servers/components/cache/batch/tasks.js @@ -0,0 +1,11 @@ +Tea.context(function () { + this.deleteTask = function (taskId) { + teaweb.confirm("确定要删除此任务吗?", function () { + this.$post(".deleteTask") + .params({ + taskId: taskId + }) + .refresh() + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/components/cache/preheat.html b/web/views/@default/servers/components/cache/fetch.html similarity index 60% rename from web/views/@default/servers/components/cache/preheat.html rename to web/views/@default/servers/components/cache/fetch.html index 06ce4f25..01715a74 100644 --- a/web/views/@default/servers/components/cache/preheat.html +++ b/web/views/@default/servers/components/cache/fetch.html @@ -1,15 +1,8 @@ {$layout} {$template "policy_menu"} -

选择集群

- -
-
- @@ -23,9 +16,10 @@ diff --git a/web/views/@default/servers/server/settings/cache/preheat.js b/web/views/@default/servers/components/cache/fetch.js similarity index 67% rename from web/views/@default/servers/server/settings/cache/preheat.js rename to web/views/@default/servers/components/cache/fetch.js index 121c5489..3e09a3f2 100644 --- a/web/views/@default/servers/server/settings/cache/preheat.js +++ b/web/views/@default/servers/components/cache/fetch.js @@ -2,22 +2,28 @@ Tea.context(function () { this.isRequesting = false this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] this.before = function () { this.isRequesting = true this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] } this.success = function (resp) { this.isOk = true - this.results = resp.data.results + + let f = NotifyReloadSuccess("任务提交成功") + f() } this.fail = function (resp) { this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } } this.done = function () { diff --git a/web/views/@default/servers/components/cache/purge.html b/web/views/@default/servers/components/cache/purge.html index fcb5d9d2..b93c3c69 100644 --- a/web/views/@default/servers/components/cache/purge.html +++ b/web/views/@default/servers/components/cache/purge.html @@ -1,34 +1,26 @@ {$layout} {$template "policy_menu"} -

选择集群

- -
- -

批量删除

可以在这里批量删除一组Key。

-
Key列表
数据发送中...
失败:{{message}} -
- 此集群下没有任何可用的节点。 -
{{one.nodeName}}:{{one.message}}
+
+
+ {{failKey.key}}: {{failKey.reason}} +
@@ -36,9 +28,10 @@ diff --git a/web/views/@default/servers/components/cache/purge.js b/web/views/@default/servers/components/cache/purge.js index a267998d..ff18a9da 100644 --- a/web/views/@default/servers/components/cache/purge.js +++ b/web/views/@default/servers/components/cache/purge.js @@ -1,31 +1,35 @@ Tea.context(function () { - if (this.clusterId == null) { - if (this.clusters.length > 0) { - this.clusterId = this.clusters[0].id - } else { - this.clusterId = 0 - } - } - this.isRequesting = false this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] + + this.$delay(function () { + this.$refs.keysBox.focus() + this.$watch("keyType", function () { + this.$refs.keysBox.focus() + }) + }) this.before = function () { this.isRequesting = true this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] } - this.success = function (resp) { + this.success = function () { this.isOk = true - this.results = resp.data.results + let f = NotifyReloadSuccess("任务提交成功") + f() } this.fail = function (resp) { this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } } this.done = function () { @@ -35,5 +39,5 @@ Tea.context(function () { /** * 操作类型 */ - this.type = "key" // key | prefix + this.keyType = "key" // key | prefix }) \ No newline at end of file diff --git a/web/views/@default/servers/groups/group/settings/cache/@menu.html b/web/views/@default/servers/groups/group/settings/cache/@menu.html index ebb46566..407691c3 100644 --- a/web/views/@default/servers/groups/group/settings/cache/@menu.html +++ b/web/views/@default/servers/groups/group/settings/cache/@menu.html @@ -1,5 +1,5 @@ 设置 清理 - 预热 + 预热 \ No newline at end of file diff --git a/web/views/@default/servers/groups/group/settings/cache/preheat.html b/web/views/@default/servers/groups/group/settings/cache/fetch.html similarity index 80% rename from web/views/@default/servers/groups/group/settings/cache/preheat.html rename to web/views/@default/servers/groups/group/settings/cache/fetch.html index c01baa93..41cbeac7 100644 --- a/web/views/@default/servers/groups/group/settings/cache/preheat.html +++ b/web/views/@default/servers/groups/group/settings/cache/fetch.html @@ -26,9 +26,10 @@ diff --git a/web/views/@default/servers/components/cache/preheat.js b/web/views/@default/servers/groups/group/settings/cache/fetch.js similarity index 63% rename from web/views/@default/servers/components/cache/preheat.js rename to web/views/@default/servers/groups/group/settings/cache/fetch.js index 45555f9e..3e09a3f2 100644 --- a/web/views/@default/servers/components/cache/preheat.js +++ b/web/views/@default/servers/groups/group/settings/cache/fetch.js @@ -1,31 +1,29 @@ Tea.context(function () { - if (this.clusterId == null) { - if (this.clusters.length > 0) { - this.clusterId = this.clusters[0].id - } else { - this.clusterId = 0 - } - } - this.isRequesting = false this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] this.before = function () { this.isRequesting = true this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] } this.success = function (resp) { this.isOk = true - this.results = resp.data.results + + let f = NotifyReloadSuccess("任务提交成功") + f() } this.fail = function (resp) { this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } } this.done = function () { diff --git a/web/views/@default/servers/groups/group/settings/cache/purge.html b/web/views/@default/servers/groups/group/settings/cache/purge.html index 54912971..d65beecb 100644 --- a/web/views/@default/servers/groups/group/settings/cache/purge.html +++ b/web/views/@default/servers/groups/group/settings/cache/purge.html @@ -18,19 +18,19 @@ @@ -38,9 +38,10 @@ diff --git a/web/views/@default/servers/groups/group/settings/cache/purge.js b/web/views/@default/servers/groups/group/settings/cache/purge.js index 69899cf0..ff18a9da 100644 --- a/web/views/@default/servers/groups/group/settings/cache/purge.js +++ b/web/views/@default/servers/groups/group/settings/cache/purge.js @@ -2,22 +2,34 @@ Tea.context(function () { this.isRequesting = false this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] + + this.$delay(function () { + this.$refs.keysBox.focus() + this.$watch("keyType", function () { + this.$refs.keysBox.focus() + }) + }) this.before = function () { this.isRequesting = true this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] } - this.success = function (resp) { + this.success = function () { this.isOk = true - this.results = resp.data.results + let f = NotifyReloadSuccess("任务提交成功") + f() } this.fail = function (resp) { this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } } this.done = function () { @@ -27,5 +39,5 @@ Tea.context(function () { /** * 操作类型 */ - this.type = "key" // key | prefix + this.keyType = "key" // key | prefix }) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/@menu.html b/web/views/@default/servers/server/settings/cache/@menu.html index ebb46566..407691c3 100644 --- a/web/views/@default/servers/server/settings/cache/@menu.html +++ b/web/views/@default/servers/server/settings/cache/@menu.html @@ -1,5 +1,5 @@ 设置 清理 - 预热 + 预热 \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/preheat.html b/web/views/@default/servers/server/settings/cache/fetch.html similarity index 77% rename from web/views/@default/servers/server/settings/cache/preheat.html rename to web/views/@default/servers/server/settings/cache/fetch.html index 21ff665b..504e83c2 100644 --- a/web/views/@default/servers/server/settings/cache/preheat.html +++ b/web/views/@default/servers/server/settings/cache/fetch.html @@ -7,7 +7,7 @@
-

没有开启缓存,不需要清理。

+

没有开启缓存,暂时无法预热缓存。

可以在这里批量预热一组Key。

@@ -27,9 +27,10 @@
diff --git a/web/views/@default/servers/server/settings/cache/fetch.js b/web/views/@default/servers/server/settings/cache/fetch.js new file mode 100644 index 00000000..3e09a3f2 --- /dev/null +++ b/web/views/@default/servers/server/settings/cache/fetch.js @@ -0,0 +1,32 @@ +Tea.context(function () { + this.isRequesting = false + this.isOk = false + this.message = "" + this.failKeys = [] + + this.before = function () { + this.isRequesting = true + this.isOk = false + this.message = "" + this.failKeys = [] + } + + this.success = function (resp) { + this.isOk = true + + let f = NotifyReloadSuccess("任务提交成功") + f() + } + + this.fail = function (resp) { + this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } + } + + this.done = function () { + this.isRequesting = false + } +}); \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/purge.html b/web/views/@default/servers/server/settings/cache/purge.html index a0f504b2..d1d17984 100644 --- a/web/views/@default/servers/server/settings/cache/purge.html +++ b/web/views/@default/servers/server/settings/cache/purge.html @@ -19,19 +19,19 @@ @@ -39,9 +39,10 @@ diff --git a/web/views/@default/servers/server/settings/cache/purge.js b/web/views/@default/servers/server/settings/cache/purge.js index 69899cf0..ff18a9da 100644 --- a/web/views/@default/servers/server/settings/cache/purge.js +++ b/web/views/@default/servers/server/settings/cache/purge.js @@ -2,22 +2,34 @@ Tea.context(function () { this.isRequesting = false this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] + + this.$delay(function () { + this.$refs.keysBox.focus() + this.$watch("keyType", function () { + this.$refs.keysBox.focus() + }) + }) this.before = function () { this.isRequesting = true this.isOk = false this.message = "" - this.results = [] + this.failKeys = [] } - this.success = function (resp) { + this.success = function () { this.isOk = true - this.results = resp.data.results + let f = NotifyReloadSuccess("任务提交成功") + f() } this.fail = function (resp) { this.message = resp.message + + if (resp.data.failKeys != null) { + this.failKeys = resp.data.failKeys + } } this.done = function () { @@ -27,5 +39,5 @@ Tea.context(function () { /** * 操作类型 */ - this.type = "key" // key | prefix + this.keyType = "key" // key | prefix }) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/serverNames/index.html b/web/views/@default/servers/server/settings/serverNames/index.html index bd1720d1..aa8a93d0 100644 --- a/web/views/@default/servers/server/settings/serverNames/index.html +++ b/web/views/@default/servers/server/settings/serverNames/index.html @@ -56,7 +56,7 @@
操作类型 - 根据Key   - 根据前缀 + 根据Key   + 根据前缀
- Key列表 - Key前缀列表 + Key列表 + Key前缀列表 - -

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

-

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

+ +

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

+

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

数据发送中...
失败:{{message}} -
- 此集群下没有任何可用的节点。 -
{{one.nodeName}}:{{one.message}}
+
+
+ {{failKey.key}}: {{failKey.reason}} +
数据发送中...
失败:{{message}} -
- 此集群下没有任何可用的节点。 -
{{one.nodeName}}:{{one.message}}
+
+
+ {{failKey.key}}: {{failKey.reason}} +
操作类型 - 根据Key   - 根据前缀 + 根据Key   + 根据前缀
- Key列表 - Key前缀列表 + Key列表 + Key前缀列表 - -

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

-

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

+ +

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

+

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

数据发送中...
失败:{{message}} -
- 此集群下没有任何可用的节点。 -
{{one.nodeName}}:{{one.message}}
+
+
+ {{failKey.key}}: {{failKey.reason}} +
数据发送中...
失败:{{message}} -
- 此集群下没有任何可用的节点。 -
{{one.nodeName}}:{{one.message}}
+
+
+ {{failKey.key}}: {{failKey.reason}} +
操作类型 - 根据Key   - 根据前缀 + 根据Key   + 根据前缀
- Key列表 - Key前缀列表 + Key列表 + Key前缀列表 - -

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

-

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

+ +

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

+

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

数据发送中...
失败:{{message}} -
- 此集群下没有任何可用的节点。 -
{{one.nodeName}}:{{one.message}}
+
+
+ {{failKey.key}}: {{failKey.reason}} +
已绑定的域名 -

终端用户可以通过这些域名访问当前网站服务。

+

用户可以通过这些域名访问当前网站服务。