Golang实现用户每秒的请求次数的限制

参考链接

  • 限制用户单位时间请求接口次数

代码总意

在模拟演示并发请求的情况下,然后来限制用户1s内只能请求3,如果请求超过3次,则返回错误的提示信息,

代码实现

  • main.go
package main

import (
	"net/http"
	"sync"
)

func main() {
	wg := sync.WaitGroup{}
	wg.Add(5)
	go func(){
		defer wg.Done()
		http.Get("http://localhost:8080/user/query")
	}()
	go func(){
		defer wg.Done()
		http.Get("http://localhost:8080/user/query")
	}()
	go func(){
		defer wg.Done()
		http.Get("http://localhost:8080/user/query")
	}()
	go func(){
		defer wg.Done()
		http.Get("http://localhost:8080/user/query")
	}()
	go func(){
		defer wg.Done()
		http.Get("http://localhost:8080/user/query")
	}()
	wg.Wait()
}
  • router.go
package main

import (
	"fmt"
	"net/http"
	"sync"
	"time"
)

var myServer = MyServer{}

func main() {
	//这样就把请求转换到了你的myServer的ServerHttp函数来处理了
	_ = http.ListenAndServe(":8080",myServer)
}



type MyServer struct {}
type RequestCountTime struct {
	//请求的词素
	count int64
	//最后的访问时间
	lastTime int64
}

//所有的请求的
func (recv MyServer)ServeHTTP(resp http.ResponseWriter, req *http.Request){
	//拦截
	filterRequest(resp,req)
}

func query(resp http.ResponseWriter, req *http.Request){
	_,_ = fmt.Fprint(resp,req.URL.Path)
}

func get(resp http.ResponseWriter, req *http.Request){
	_,_ = fmt.Fprint(resp,req.URL.Path)
}

//key   : uid+url
//value : RequestCountTime
var cacheMap = make(map[string]RequestCountTime)
var mu = sync.Mutex{}
const(
	ONE_SECOND = 1
	REQUEST_COUNT = 3
)

//限制用户的每秒的请求的次数,1s10次的频率
func filterRequest(resp http.ResponseWriter,req *http.Request){
	uid := "userXPH123"
	reqUrl := req.URL.Path
	key := uid+reqUrl
	mu.Lock()
	value,ok := cacheMap[key]
	fmt.Println("value的值——> ",value)
	//在cacheMap中有

	if ok{
		//看该请求是否在这1s内,如果不在则请零
		//如果在,则看该请求的次数是否超过限制的请求次数
		//(当前请求的时间-最后一次访问的时间) > 1s || 请求次数 > 限制次数
		//则返回错误
		res := time.Now().Unix() - value.lastTime
		fmt.Println("访问时间——>",res,ONE_SECOND)
		if time.Duration(res) >=ONE_SECOND || value.count >= REQUEST_COUNT{
			fmt.Println("对不起你的请求此时已超限")
			_, _ = fmt.Fprint(resp,"对不起你的请求此时已超限")
			return
		}
		value.count++
		cacheMap[key] = value
	}else{
		//如果去不到值则是第一次访问
		cacheMap[key] = RequestCountTime{count:1,lastTime:time.Now().Unix()}
	}
	mu.Unlock()

	fmt.Println(reqUrl)
	switch reqUrl {
	case "/user/query":
		query(resp,req)
	case "/user/get":
		get(resp,req)
	default:
		_,_ = fmt.Fprint(resp,"找不到请求资源")
	}
}

你可能感兴趣的:(golang)