ZBLOG

请用golang 实现一个限制每天http请求次数的 方法。并封装

这里提供一个使用 golang 实现限制每天 http 请求次数的方法,并进行封装的示例代码:

package main

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

// 定义 HTTP 请求处理函数
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello, world!")
}

// 封装每天最大访问次数控制方法
func LimitDailyRequest(maxCount int, fn http.HandlerFunc) http.HandlerFunc {
	// 定义一个读写并发安全的映射对象
	var m sync.Map

	// 返回一个新的 HTTP 请求处理函数,用于在原有请求处理基础上增加每天最大访问次数限制功能
	return func(w http.ResponseWriter, r *http.Request) {
	    // 获取当前时间和当天日期字符串(例如20220101)
	    nowTime := time.Now()
	    todayStr := nowTime.Truncate(24*time.Hour).Format("20060102")

	    // 构建已处理请求数量、上一次请求时间和访问计数器的 key
	    countKey := fmt.Sprintf("%s:%s", "requests", todayStr)
	    timeKey := fmt.Sprintf("%s:%s", "last_request_time", todayStr)
	    counterKey := fmt.Sprintf("%s:%s", "counter", todayStr)

	    // 使用读写锁来保证并发安全性
	    var mu sync.RWMutex
	    mu.RLock()
	    defer mu.RUnlock()

		// 从映射中获取已处理请求数量、上一次请求时间和访问计数器,并判断是否超出限制
		currentCount, found := m.LoadOrStore(countKey, 0) // 如果不存在,则设置为0;否则返回已有值
		lastRequestTime, found := m.LoadOrStore(timeKey, nowTime.Add(-time.Second)) // 如果不存在,则设置为当前时间的前一秒;否则返回已有值
	    counter, found := m.LoadOrStore(counterKey, 0)

		// 判断是否超出限制
		if currentCount.(int) >= maxCount {
			http.Error(w, "Exceeding the maximum number of requests per day", http.StatusTooManyRequests)
		    return // 超出限制直接返回响应,不再执行原有请求处理函数
		} else {
	        // 增加访问计数器,并更新本次请求时间和已处理请求数量到映射中
	        mu.Lock()
	        defer mu.Unlock()

		    m.Store(countKey, currentCount.(int)+1)
		    m.Store(timeKey, nowTime)
	        m.Store(counterKey, counter.(int)+1)

	        fn(w, r) // 执行原有请求处理函数

            // 打印当前已处理请求数量和剩余请求数量(可选)
            fmt.Printf("今日已处理 %d 次,请求数量剩余 %d\n", currentCount.(int)+1, maxCount-currentCount.(int)-1)
		}
    }
}

func main() {
    // 创建一个 HTTP 服务器并注册 HTTP 请求处理函数(使用 LimitDailyRequest 封装后的新函数)
    http.HandleFunc("/", LimitDailyRequest(20, handler))

    // 启动 HTTP 服务器并监听在本地 8080 端口上
    http.ListenAndServe(":8080", nil)
}

使用 LimitDailyRequest 封装 HTTP 请求处理函数后,每个客户端每天最多只能访问该接口指定的次数。如果超出限制,则会直接返回响应,并不再执行原有请求处理函数。同时,该封装方法是线程安全的,可以保证在高并发情况下仍能正确地统计和限制请求次数。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=3131

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?