From 58aca9ea9ebaccb24c09c11b193443c7c600711f Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Mon, 10 Dec 2018 07:09:55 +0000 Subject: [PATCH 1/3] =?UTF-8?q?loadbalancers:=20=E7=A7=BB=E9=99=A4Bandwidt?= =?UTF-8?q?h=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 未在使用,且名称太泛,不便于日后扩展维护 --- pkg/compute/models/loadbalancerlisteners.go | 1 - pkg/mcclient/models/loadbalancers.go | 1 - pkg/mcclient/options/loadbalancerlisteners.go | 3 --- 3 files changed, 5 deletions(-) diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index ea16d3e9a4..7445c0ed75 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -69,7 +69,6 @@ type SLoadbalancerListener struct { ListenerPort int `nullable:"false" list:"user" create:"required"` BackendGroupId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional" update:"user"` - Bandwidth int `nullable:"false" list:"user" create:"optional" update:"user"` Scheduler string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"required" update:"user"` ClientRequestTimeout int `nullable:"false" list:"user" create:"optional" update:"user"` diff --git a/pkg/mcclient/models/loadbalancers.go b/pkg/mcclient/models/loadbalancers.go index e2ec149582..0ae4a5128f 100644 --- a/pkg/mcclient/models/loadbalancers.go +++ b/pkg/mcclient/models/loadbalancers.go @@ -42,7 +42,6 @@ type LoadbalancerListener struct { VirtualResource LoadbalancerId string - Bandwidth int ListenerType string ListenerPort int diff --git a/pkg/mcclient/options/loadbalancerlisteners.go b/pkg/mcclient/options/loadbalancerlisteners.go index 7b232ae365..11b6c093a2 100644 --- a/pkg/mcclient/options/loadbalancerlisteners.go +++ b/pkg/mcclient/options/loadbalancerlisteners.go @@ -9,7 +9,6 @@ type LoadbalancerListenerCreateOptions struct { BackendGroup string Scheduler string `required:"true" choices:"rr|wrr|wlc|sch|tch"` - Bandwidth *int ClientRequestTimeout *int ClientIdleTimeout *int @@ -57,7 +56,6 @@ type LoadbalancerListenerListOptions struct { BackendGroup string Scheduler string `choices:"rr|wrr|wlc|sch|tch"` - Bandwidth *int ClientRequestTimeout *int ClientIdleTimeout *int @@ -103,7 +101,6 @@ type LoadbalancerListenerUpdateOptions struct { BackendGroup string Scheduler string `choices:"rr|wrr|wlc|sch|tch"` - Bandwidth *int ClientRequestTimeout *int ClientIdleTimeout *int From 93e1e7799edace52d48ee9d00e64f3e63b76a60d Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Mon, 10 Dec 2018 07:33:57 +0000 Subject: [PATCH 2/3] =?UTF-8?q?loadbalancers:=20=E6=B8=85=E7=90=86?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E9=80=89=E9=A1=B9=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/models/loadbalancerlisteners.go | 2 -- pkg/mcclient/models/loadbalancers.go | 9 ++------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index 7445c0ed75..143a782ca7 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -43,8 +43,6 @@ type SLoadbalancerHTTPListener struct { StickySessionCookie string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"optional" update:"user"` StickySessionCookieTimeout int `nullable:"false" list:"user" create:"optional" update:"user"` - //XForwardedForSLBIP bool `nullable:"false" list:"user" create:"optional"` - //XForwardedForSLBID bool `nullable:"false" list:"user" create:"optional"` XForwardedFor bool `nullable:"false" list:"user" create:"optional" update:"user"` Gzip bool `nullable:"false" list:"user" create:"optional" update:"user"` } diff --git a/pkg/mcclient/models/loadbalancers.go b/pkg/mcclient/models/loadbalancers.go index 0ae4a5128f..667fdbe8d2 100644 --- a/pkg/mcclient/models/loadbalancers.go +++ b/pkg/mcclient/models/loadbalancers.go @@ -25,10 +25,8 @@ type LoadbalancerHTTPListener struct { StickySessionCookie string StickySessionCookieTimeout int - XForwardedFor bool - XForwardedForSLBIP bool - XForwardedForSLBID bool - Gzip bool + XForwardedFor bool + Gzip bool } // CACertificate string @@ -77,9 +75,6 @@ type LoadbalancerListener struct { LoadbalancerUDPListener LoadbalancerHTTPListener LoadbalancerHTTPSListener - - XForwardedFor bool - Gzip bool } type LoadbalancerListenerRule struct { From 5564929e349985f4c0ddbd07f13ebf7aa23f9dbc Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Mon, 10 Dec 2018 08:05:55 +0000 Subject: [PATCH 3/3] =?UTF-8?q?loadbalancers:=20=E5=A2=9E=E5=8A=A0rps?= =?UTF-8?q?=E9=99=90=E9=80=9F=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/lbagent/main.go | 3 + .../models/loadbalancerlistenerrules.go | 19 ++++-- pkg/compute/models/loadbalancerlisteners.go | 13 ++++ pkg/lbagent/models/haproxy.go | 59 +++++++++++++++++-- pkg/mcclient/models/loadbalancers.go | 9 +++ pkg/mcclient/options/loadbalancerlisteners.go | 9 +++ 6 files changed, 104 insertions(+), 8 deletions(-) diff --git a/cmd/lbagent/main.go b/cmd/lbagent/main.go index 1943948512..9215a1ece1 100644 --- a/cmd/lbagent/main.go +++ b/cmd/lbagent/main.go @@ -9,10 +9,13 @@ import ( "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudcommon" + "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/lbagent" ) func main() { + consts.SetServiceType("lbagent") + opts := &lbagent.Options{} commonOpts := &opts.CommonOpts { diff --git a/pkg/compute/models/loadbalancerlistenerrules.go b/pkg/compute/models/loadbalancerlistenerrules.go index 3e3d3bccc8..26f6540822 100644 --- a/pkg/compute/models/loadbalancerlistenerrules.go +++ b/pkg/compute/models/loadbalancerlistenerrules.go @@ -39,6 +39,8 @@ type SLoadbalancerListenerRule struct { Domain string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"optional"` Path string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"optional"` + + SLoadbalancerHTTPRateLimiter } func loadbalancerListenerRuleCheckUniqueness(ctx context.Context, lbls *SLoadbalancerListener, domain, path string) error { @@ -101,6 +103,9 @@ func (man *SLoadbalancerListenerRuleManager) ValidateCreateData(ctx context.Cont "backend_group": backendGroupV, "domain": domainV.AllowEmpty(true).Default(""), "path": pathV.Default(""), + + "http_request_rate": validators.NewNonNegativeValidator("http_request_rate").Default(0), + "http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src").Default(0), } for _, v := range keyV { if err := v.Validate(data); err != nil { @@ -131,10 +136,16 @@ func (lbr *SLoadbalancerListenerRule) AllowPerformStatus(ctx context.Context, us func (lbr *SLoadbalancerListenerRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { backendGroupV := validators.NewModelIdOrNameValidator("backend_group", "loadbalancerbackendgroup", lbr.GetOwnerProjectId()) - backendGroupV.Optional(true) - err := backendGroupV.Validate(data) - if err != nil { - return nil, err + keyV := map[string]validators.IValidator{ + "backend_group": backendGroupV, + "http_request_rate": validators.NewNonNegativeValidator("http_request_rate"), + "http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src"), + } + for _, v := range keyV { + v.Optional(true) + if err := v.Validate(data); err != nil { + return nil, err + } } if backendGroup, ok := backendGroupV.Model.(*SLoadbalancerBackendGroup); ok && backendGroup.Id != lbr.BackendGroupId { listenerM, err := LoadbalancerListenerManager.FetchById(lbr.ListenerId) diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index 143a782ca7..458502672c 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -33,6 +33,11 @@ func init() { } } +type SLoadbalancerHTTPRateLimiter struct { + HTTPRequestRate int `nullable:"false" list:"user" create:"optional" update:"user"` + HTTPRequestRatePerSrc int `nullable:"false" list:"user" create:"optional" update:"user"` +} + type SLoadbalancerTCPListener struct{} type SLoadbalancerUDPListener struct{} @@ -97,6 +102,8 @@ type SLoadbalancerListener struct { SLoadbalancerUDPListener SLoadbalancerHTTPListener SLoadbalancerHTTPSListener + + SLoadbalancerHTTPRateLimiter } func (man *SLoadbalancerListenerManager) checkListenerUniqueness(ctx context.Context, lb *SLoadbalancer, listenerType string, listenerPort int64) error { @@ -198,6 +205,9 @@ func (man *SLoadbalancerListenerManager) ValidateCreateData(ctx context.Context, "x_forwarded_for": validators.NewBoolValidator("x_forwarded_for").Default(true), "gzip": validators.NewBoolValidator("gzip").Default(false), + + "http_request_rate": validators.NewNonNegativeValidator("http_request_rate").Default(0), + "http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src").Default(0), } for _, v := range keyV { if err := v.Validate(data); err != nil { @@ -342,6 +352,9 @@ func (lblis *SLoadbalancerListener) ValidateUpdateData(ctx context.Context, user "x_forwarded_for": validators.NewBoolValidator("x_forwarded_for"), "gzip": validators.NewBoolValidator("gzip"), + "http_request_rate": validators.NewNonNegativeValidator("http_request_rate").Default(0), + "http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src").Default(0), + "certificate": certV, "tls_cipher_policy": tlsCipherPolicyV, "enable_http2": validators.NewBoolValidator("enable_http2").Default(true), diff --git a/pkg/lbagent/models/haproxy.go b/pkg/lbagent/models/haproxy.go index 59830b036d..d19f172ff7 100644 --- a/pkg/lbagent/models/haproxy.go +++ b/pkg/lbagent/models/haproxy.go @@ -318,6 +318,43 @@ func (b *LoadbalancerCorpus) genHaproxyConfigBackend(data map[string]interface{} return nil } +func (b *LoadbalancerCorpus) genHaproxyConfigHttpRate(data map[string]interface{}, requestRate, requestRatePerSrc int) error { + periodSecond := 10 + id := data["id"].(string) + dummyBackends := []map[string]string{} + rateRules := []string{} + + // order matters here: every src uses up his own quota before touching + // the shared one + if requestRatePerSrc > 0 { + idPerSrc := id + "_persrc" + dummyBackends = append(dummyBackends, map[string]string{ + "id": idPerSrc, + "stick_table": fmt.Sprintf("stick-table type ip size 1m expire 1m store http_req_rate(%ds)", periodSecond), + }) + rateRules = append(rateRules, + fmt.Sprintf("http-request deny deny_status 429 if { src_http_req_rate(%s) gt %d }", + idPerSrc, requestRatePerSrc*periodSecond), + fmt.Sprintf("http-request track-sc0 src table %s", + idPerSrc)) + } + if requestRate > 0 { + idTotal := id + "_total" + dummyBackends = append(dummyBackends, map[string]string{ + "id": idTotal, + "stick_table": fmt.Sprintf("stick-table type integer size 1 expire 1m store http_req_rate(%ds)", periodSecond), + }) + rateRules = append(rateRules, + fmt.Sprintf("http-request deny deny_status 429 if { int(1),table_http_req_rate(%s) gt %d }", + idTotal, requestRate*periodSecond), + fmt.Sprintf("http-request track-sc1 int(1) table %s", + idTotal)) + } + data["rate_rules"] = rateRules + data["dummy_backends"] = dummyBackends + return nil +} + func (b *LoadbalancerCorpus) genHaproxyConfigHttp(buf *bytes.Buffer, listener *LoadbalancerListener, opts *AgentParams) error { lb := listener.loadbalancer rules := listener.rules.OrderedEnabledList() @@ -366,8 +403,10 @@ func (b *LoadbalancerCorpus) genHaproxyConfigHttp(buf *bytes.Buffer, listener *L backendGroup.Name, backendGroup.Id), "id": ruleBackendIdGen(rule.Id), } - err := b.genHaproxyConfigBackend(backendData, lb, listener, backendGroup) - if err != nil { + if err := b.genHaproxyConfigBackend(backendData, lb, listener, backendGroup); err != nil { + return err + } + if err := b.genHaproxyConfigHttpRate(backendData, rule.HTTPRequestRate, rule.HTTPRequestRatePerSrc); err != nil { return err } backends = append(backends, backendData) @@ -381,8 +420,10 @@ func (b *LoadbalancerCorpus) genHaproxyConfigHttp(buf *bytes.Buffer, listener *L backendGroup.Name, backendGroup.Id), "id": fmt.Sprintf("backends_listener_default-%s", listener.Id), } - err := b.genHaproxyConfigBackend(backendData, lb, listener, backendGroup) - if err != nil { + if err := b.genHaproxyConfigBackend(backendData, lb, listener, backendGroup); err != nil { + return err + } + if err := b.genHaproxyConfigHttpRate(backendData, listener.HTTPRequestRate, listener.HTTPRequestRatePerSrc); err != nil { return err } backends = append(backends, backendData) @@ -436,12 +477,17 @@ listen {{ .id }} {{ define "httpListen" -}} # {{ .listener_type }} listener: {{ .comment }} +{{- range .dummy_backends }} +backend {{ .id }} + {{ println .stick_table }} +{{- end }} frontend {{ .id }} bind {{ .bind }} mode http {{- println }} {{- if .log }} {{ println "option httplog clf" }} {{- end }} {{- if .acl }} {{ println .acl }} {{- end}} + {{- range .rate_rules }} {{ println . }} {{- end }} {{- if .client_request_timeout }} timeout http-request {{ println .client_request_timeout }} {{- end}} {{- if .client_idle_timeout }} timeout http-keep-alive {{ println .client_idle_timeout }} {{- end}} {{- if .xforwardedfor }} {{ println "option forwardfor" }} {{- end}} @@ -455,10 +501,15 @@ frontend {{ .id }} {{ define "backend" -}} # {{ .comment }} +{{- range .dummy_backends }} +backend {{ .id }} + {{ println .stick_table }} +{{- end }} backend {{ .id }} mode {{ .mode }} balance {{ .balanceAlgorithm }} {{- println }} + {{- range .rate_rules }} {{ println . }} {{- end }} {{- if .backend_connect_timeout }} timeout connect {{ println .backend_connect_timeout }} {{- end}} {{- if .backend_idle_timeout }} timeout server {{ println .backend_idle_timeout }} {{- end}} {{- if .timeout_check }} {{ println .timeout_check }} {{- end }} diff --git a/pkg/mcclient/models/loadbalancers.go b/pkg/mcclient/models/loadbalancers.go index 667fdbe8d2..7f7358f4fa 100644 --- a/pkg/mcclient/models/loadbalancers.go +++ b/pkg/mcclient/models/loadbalancers.go @@ -36,6 +36,11 @@ type LoadbalancerHTTPSListener struct { EnableHttp2 bool } +type LoadbalancerHTTPRateLimiter struct { + HTTPRequestRate int + HTTPRequestRatePerSrc int +} + type LoadbalancerListener struct { VirtualResource @@ -75,6 +80,8 @@ type LoadbalancerListener struct { LoadbalancerUDPListener LoadbalancerHTTPListener LoadbalancerHTTPSListener + + LoadbalancerHTTPRateLimiter } type LoadbalancerListenerRule struct { @@ -85,6 +92,8 @@ type LoadbalancerListenerRule struct { Domain string Path string + + LoadbalancerHTTPRateLimiter } type LoadbalancerBackendGroup struct { diff --git a/pkg/mcclient/options/loadbalancerlisteners.go b/pkg/mcclient/options/loadbalancerlisteners.go index 11b6c093a2..7f2ddd087e 100644 --- a/pkg/mcclient/options/loadbalancerlisteners.go +++ b/pkg/mcclient/options/loadbalancerlisteners.go @@ -45,6 +45,9 @@ type LoadbalancerListenerCreateOptions struct { Certificate string TLSCipherPolicy string EnableHttp2 string `choices:"true|false"` + + HTTPRequestRate *int + HTTPRequestRatePerSrc *int } type LoadbalancerListenerListOptions struct { @@ -92,6 +95,9 @@ type LoadbalancerListenerListOptions struct { Certificate string TLSCipherPolicy string EnableHttp2 string `choices:"true|false"` + + HTTPRequestRate *int + HTTPRequestRatePerSrc *int } type LoadbalancerListenerUpdateOptions struct { @@ -137,6 +143,9 @@ type LoadbalancerListenerUpdateOptions struct { Certificate string TLSCipherPolicy string EnableHttp2 string `choices:"true|false"` + + HTTPRequestRate *int + HTTPRequestRatePerSrc *int } type LoadbalancerListenerGetOptions struct {