mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 16:00:25 +08:00 
			
		
		
		
	套餐可以设置带宽限制
This commit is contained in:
		@@ -201,9 +201,10 @@ func (this *HTTPRequest) Do() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// 流量限制
 | 
							// 流量限制
 | 
				
			||||||
		if this.ReqServer.TrafficLimitStatus != nil && this.ReqServer.TrafficLimitStatus.IsValid() {
 | 
							if this.ReqServer.TrafficLimitStatus != nil && this.ReqServer.TrafficLimitStatus.IsValid() {
 | 
				
			||||||
			this.doTrafficLimit()
 | 
								if this.doTrafficLimit(this.ReqServer.TrafficLimitStatus) {
 | 
				
			||||||
			this.doEnd()
 | 
									this.doEnd()
 | 
				
			||||||
			return
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// WAF
 | 
							// WAF
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,19 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 流量限制
 | 
					// 流量限制
 | 
				
			||||||
func (this *HTTPRequest) doTrafficLimit() {
 | 
					func (this *HTTPRequest) doTrafficLimit(status *serverconfigs.TrafficLimitStatus) (blocked bool) {
 | 
				
			||||||
 | 
						if status == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 如果是网站单独设置的流量限制,则检查是否已关闭
 | 
				
			||||||
 | 
						var config = this.ReqServer.TrafficLimit
 | 
				
			||||||
 | 
						if (config == nil || !config.IsOn) && status.PlanId == 0 {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 如果是套餐设置的流量限制,即使套餐变更了(变更套餐或者变更套餐的限制),仍然会提示流量超限
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this.tags = append(this.tags, "trafficLimit")
 | 
						this.tags = append(this.tags, "trafficLimit")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var statusCode = 509
 | 
						var statusCode = 509
 | 
				
			||||||
@@ -17,10 +29,19 @@ func (this *HTTPRequest) doTrafficLimit() {
 | 
				
			|||||||
	this.writer.Header().Set("Content-Type", "text/html; charset=utf-8")
 | 
						this.writer.Header().Set("Content-Type", "text/html; charset=utf-8")
 | 
				
			||||||
	this.writer.WriteHeader(statusCode)
 | 
						this.writer.WriteHeader(statusCode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var config = this.ReqServer.TrafficLimit
 | 
						// check plan traffic limit
 | 
				
			||||||
 | 
						if (config == nil || !config.IsOn) && this.ReqServer.PlanId() > 0 && this.nodeConfig != nil {
 | 
				
			||||||
 | 
							var planConfig = this.nodeConfig.FindPlan(this.ReqServer.PlanId())
 | 
				
			||||||
 | 
							if planConfig != nil && planConfig.TrafficLimit != nil && planConfig.TrafficLimit.IsOn {
 | 
				
			||||||
 | 
								config = planConfig.TrafficLimit
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if config != nil && len(config.NoticePageBody) != 0 {
 | 
						if config != nil && len(config.NoticePageBody) != 0 {
 | 
				
			||||||
		_, _ = this.writer.WriteString(this.Format(config.NoticePageBody))
 | 
							_, _ = this.writer.WriteString(this.Format(config.NoticePageBody))
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		_, _ = this.writer.WriteString(this.Format(serverconfigs.DefaultTrafficLimitNoticePageBody))
 | 
							_, _ = this.writer.WriteString(this.Format(serverconfigs.DefaultTrafficLimitNoticePageBody))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -807,6 +807,8 @@ func (this *HTTPWriter) Write(data []byte) (n int, err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	n, err = this.writer.Write(data)
 | 
						n, err = this.writer.Write(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.checkPlanBandwidth(n)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,3 +11,7 @@ import (
 | 
				
			|||||||
func (this *HTTPWriter) canSendfile() (*os.File, bool) {
 | 
					func (this *HTTPWriter) canSendfile() (*os.File, bool) {
 | 
				
			||||||
	return nil, false
 | 
						return nil, false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *HTTPWriter) checkPlanBandwidth(n int) {
 | 
				
			||||||
 | 
						// stub
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,6 +102,8 @@ func (this *Node) execTask(rpcClient *rpc.RPCClient, task *pb.NodeTask) error {
 | 
				
			|||||||
		err = this.execNetworkSecurityPolicyChangedTask(rpcClient)
 | 
							err = this.execNetworkSecurityPolicyChangedTask(rpcClient)
 | 
				
			||||||
	case "webPPolicyChanged":
 | 
						case "webPPolicyChanged":
 | 
				
			||||||
		err = this.execWebPPolicyChangedTask(rpcClient)
 | 
							err = this.execWebPPolicyChangedTask(rpcClient)
 | 
				
			||||||
 | 
						case "planChanged":
 | 
				
			||||||
 | 
							err = this.execPlanChangedTask(rpcClient)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		// 特殊任务
 | 
							// 特殊任务
 | 
				
			||||||
		if strings.HasPrefix(task.Type, "ipListDeleted") { // 删除IP名单
 | 
							if strings.HasPrefix(task.Type, "ipListDeleted") { // 删除IP名单
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,3 +34,7 @@ func (this *Node) execNetworkSecurityPolicyChangedTask(rpcClient *rpc.RPCClient)
 | 
				
			|||||||
	// stub
 | 
						// stub
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Node) execPlanChangedTask(rpcClient *rpc.RPCClient) error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,7 @@ type RPCClient struct {
 | 
				
			|||||||
	ClientAgentIPRPC       pb.ClientAgentIPServiceClient
 | 
						ClientAgentIPRPC       pb.ClientAgentIPServiceClient
 | 
				
			||||||
	AuthorityKeyRPC        pb.AuthorityKeyServiceClient
 | 
						AuthorityKeyRPC        pb.AuthorityKeyServiceClient
 | 
				
			||||||
	UpdatingServerListRPC  pb.UpdatingServerListServiceClient
 | 
						UpdatingServerListRPC  pb.UpdatingServerListServiceClient
 | 
				
			||||||
 | 
						PlanRPC                pb.PlanServiceClient
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
					func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
				
			||||||
@@ -91,6 +92,7 @@ func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
				
			|||||||
	client.ClientAgentIPRPC = pb.NewClientAgentIPServiceClient(client)
 | 
						client.ClientAgentIPRPC = pb.NewClientAgentIPServiceClient(client)
 | 
				
			||||||
	client.AuthorityKeyRPC = pb.NewAuthorityKeyServiceClient(client)
 | 
						client.AuthorityKeyRPC = pb.NewAuthorityKeyServiceClient(client)
 | 
				
			||||||
	client.UpdatingServerListRPC = pb.NewUpdatingServerListServiceClient(client)
 | 
						client.UpdatingServerListRPC = pb.NewUpdatingServerListServiceClient(client)
 | 
				
			||||||
 | 
						client.PlanRPC = pb.NewPlanServiceClient(client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := client.init()
 | 
						err := client.init()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								internal/utils/ratelimit/bandwidth.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								internal/utils/ratelimit/bandwidth.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ratelimit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
 | 
				
			||||||
 | 
						"sync/atomic"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Bandwidth lossy bandwidth limiter
 | 
				
			||||||
 | 
					type Bandwidth struct {
 | 
				
			||||||
 | 
						totalBytes int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						currentTimestamp int64
 | 
				
			||||||
 | 
						currentBytes     int64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewBandwidth create new bandwidth limiter
 | 
				
			||||||
 | 
					func NewBandwidth(totalBytes int64) *Bandwidth {
 | 
				
			||||||
 | 
						return &Bandwidth{totalBytes: totalBytes}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Ack acquire next chance to send data
 | 
				
			||||||
 | 
					func (this *Bandwidth) Ack(ctx context.Context, newBytes int) {
 | 
				
			||||||
 | 
						if newBytes <= 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if this.totalBytes <= 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var timestamp = fasttime.Now().Unix()
 | 
				
			||||||
 | 
						if this.currentTimestamp != 0 && this.currentTimestamp != timestamp {
 | 
				
			||||||
 | 
							this.currentTimestamp = timestamp
 | 
				
			||||||
 | 
							this.currentBytes = int64(newBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 第一次发送直接放行,不需要判断
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if this.currentTimestamp == 0 {
 | 
				
			||||||
 | 
							this.currentTimestamp = timestamp
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if atomic.AddInt64(&this.currentBytes, int64(newBytes)) <= this.totalBytes {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var timeout = time.NewTimer(1 * time.Second)
 | 
				
			||||||
 | 
						if ctx != nil {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-timeout.C:
 | 
				
			||||||
 | 
							case <-ctx.Done():
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-timeout.C:
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								internal/utils/ratelimit/bandwidth_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								internal/utils/ratelimit/bandwidth_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ratelimit_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils/ratelimit"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils/testutils"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestBandwidth(t *testing.T) {
 | 
				
			||||||
 | 
						if !testutils.IsSingleTesting() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var bandwidth = ratelimit.NewBandwidth(32 << 10)
 | 
				
			||||||
 | 
						bandwidth.Ack(context.Background(), 123)
 | 
				
			||||||
 | 
						bandwidth.Ack(context.Background(), 16 << 10)
 | 
				
			||||||
 | 
						bandwidth.Ack(context.Background(), 32 << 10)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestBandwidth_0(t *testing.T) {
 | 
				
			||||||
 | 
						var bandwidth = ratelimit.NewBandwidth(0)
 | 
				
			||||||
 | 
						bandwidth.Ack(context.Background(), 123)
 | 
				
			||||||
 | 
						bandwidth.Ack(context.Background(), 123456)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,14 +1,20 @@
 | 
				
			|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package ratelimit
 | 
					package ratelimit_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils/ratelimit"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils/testutils"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestCounter_ACK(t *testing.T) {
 | 
					func TestCounter_ACK(t *testing.T) {
 | 
				
			||||||
	var counter = NewCounter(10)
 | 
						if !testutils.IsSingleTesting() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var counter = ratelimit.NewCounter(10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for i := 0; i < 10; i++ {
 | 
							for i := 0; i < 10; i++ {
 | 
				
			||||||
@@ -26,7 +32,7 @@ func TestCounter_ACK(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestCounter_Release(t *testing.T) {
 | 
					func TestCounter_Release(t *testing.T) {
 | 
				
			||||||
	var counter = NewCounter(10)
 | 
						var counter = ratelimit.NewCounter(10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < 10; i++ {
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
		counter.Ack()
 | 
							counter.Ack()
 | 
				
			||||||
@@ -34,5 +40,5 @@ func TestCounter_Release(t *testing.T) {
 | 
				
			|||||||
	for i := 0; i < 10; i++ {
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
		counter.Release()
 | 
							counter.Release()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	t.Log(len(counter.sem))
 | 
						t.Log(counter.Len())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user