Go语言实现接口IP限流,黑名单&白名单的实例,都可用!
原创 学习与分享 Go语言圈 2023-07-18 08:30 发表于广东 MySQL大牛 带你全面剖析与系统梳理数据库(mysql等)知识分享,总结数据库技巧和方法,提升你的技术技能。 45篇原创内容 公众号Goland 激活码&个人账号开通授权,支持版本升级
https://www.mano100.cn/thread-1942-1-1.html
学习与交流:Go语言技术微信群
商务合作加微信:LetsFeng
现在就开始你的Go语言学习之旅吧!人生苦短,let’s Go.
在Go语言中,可以使用令牌桶算法(Token Bucket Algorithm)来实现接口IP限流。令牌桶算法基于令牌桶的概念,每个令牌代表一个请求,令牌桶限制了请求的速率。
以下是一个简单的示例代码,演示如何使用令牌桶算法实现接口IP限流:
package main
import (
"fmt"
"net"
"sync"
"time"
)
type RateLimiter struct {
bucket map[string]*TokenBucket
mutex sync.Mutex
}
type TokenBucket struct {
rate float64 // 速率,单位:令牌/秒
capacity float64 // 令牌桶容量
tokens float64 // 当前令牌数量
lastUpdate time.Time // 上次更新时间
}
func NewRateLimiter() *RateLimiter {
return &RateLimiter{
bucket: make(map[string]*TokenBucket),
}
}
func (rl *RateLimiter) AllowIP(ip string) bool {
rl.mutex.Lock()
defer rl.mutex.Unlock()
bucket, exists := rl.bucket[ip]
if !exists {
// 初始化令牌桶
bucket = &TokenBucket{
rate: 10, // 每秒生成10个令牌
capacity: 10, // 令牌桶容量为10个
tokens: 10, // 初始时令牌桶为满的状态
lastUpdate: time.Now(),
}
rl.bucket[ip] = bucket
}
// 计算时间间隔,并根据速率生成令牌
now := time.Now()
elapsed := now.Sub(bucket.lastUpdate).Seconds()
tokensToAdd := elapsed * bucket.rate
// 更新令牌桶状态
if tokensToAdd > 0 {
bucket.tokens = bucket.tokens + tokensToAdd
if bucket.tokens > bucket.capacity {
bucket.tokens = bucket.capacity
}
bucket.lastUpdate = now
}
// 检查令牌数量是否足够
if bucket.tokens >= 1 {
bucket.tokens--
return true
}
return false
}
func main() {
limiter := NewRateLimiter()
// 模拟并发请求
for i := 0; i < 20; i++ {
go func() {
ip := GetClientIP() // 获取客户端IP
if limiter.AllowIP(ip) {
fmt.Printf("Request from IP %s is allowed\n", ip)
} else {
fmt.Printf("Request from IP %s is rate limited\n", ip)
}
}()
}
// 等待所有请求完成
time.Sleep(2 * time.Second)
}
func GetClientIP() string {
conn, _ := net.Dial("udp", "8.8.8.8:80")
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String()
}
在上述示例中,我们定义了 RateLimiter
结构体和 TokenBucket
结构体,用于表示IP限流的令牌桶和限流器。RateLimiter
使用 sync.Mutex
来保证并发安全。
通过 AllowIP
方法实现IP限流逻辑。该方法首先从 RateLimiter
中获取对应IP的令牌桶,如果令牌桶不存在,则创建一个新的令牌桶。然后根据速率计算时间间隔,并生成相应数量的令牌。最后,检查令牌桶中的令牌数量是否足够,如果足够则返回 true
,表示允许访问;否则返回 false
,表示限制访问。
在 main
函数中,我们创建了一个 RateLimiter
对象,并模拟并发请求。每个请求获取客户端IP,并通过 AllowIP
方法判断是否允许访问。根据令牌桶的速率和容量,前 10 个请求会被允许,后续的请求会被限流。
注意,以上示例代码仅演示了基本的令牌桶算法实现IP限流的方法。实际应用中,可能需要考虑更复杂的限流策略,如平滑突发限流、动态调整速率等,以满足具体的需求。
黑名单&白名单的实现
在Go语言中,可以使用map数据结构来实现IP黑名单和IP白名单的功能。以下是一个示例代码,演示如何实现IP黑名单和IP白名单:
package main
import (
"fmt"
"net"
)
type IPList struct {
list map[string]bool
}
func NewIPList() *IPList {
return &IPList{
list: make(map[string]bool),
}
}
func (l *IPList) AddIP(ip string) {
l.list[ip] = true
}
func (l *IPList) RemoveIP(ip string) {
delete(l.list, ip)
}
func (l *IPList) ContainsIP(ip string) bool {
_, exists := l.list[ip]
return exists
}
func main() {
// 创建IP黑名单
blacklist := NewIPList()
// 添加IP到黑名单
blacklist.AddIP("127.0.0.1")
blacklist.AddIP("192.168.0.1")
// 模拟请求,判断IP是否在黑名单中
ips := []string{"127.0.0.1", "192.168.0.1", "10.0.0.1"}
for _, ip := range ips {
if blacklist.ContainsIP(ip) {
fmt.Printf("IP %s is in the blacklist\n", ip)
} else {
fmt.Printf("IP %s is not in the blacklist\n", ip)
}
}
}
在上述示例中,我们定义了一个名为 IPList
的结构体,用于表示IP名单列表。该结构体内部使用map来存储IP,并提供了添加IP、移除IP和判断IP是否存在的方法。
在 main
函数中,我们创建了一个 IPList
对象,并添加一些IP到黑名单中。然后,我们模拟请求并判断每个IP是否在黑名单中,根据结果输出相应的消息。
如果需要实现IP白名单,可以类似地创建一个 IPList
结构体,但将逻辑调整为判断IP是否在白名单中。然后使用 AddIP
方法添加白名单IP,使用 ContainsIP
方法判断IP是否在白名单中。
在实际应用中,可以根据需求扩展 IPList
结构体的功能,如支持批量添加IP、从文件中加载名单等。此外,还可以结合网络请求的IP获取方法,获取客户端IP并进行名单判断。
文章首发:
更多相关Go语言的技术文章或视频教程,请关注本公众号获取并查看,感谢你的支持与信任!
学Go语言哪些事儿247 学Go语言哪些事儿 · 目录 上一篇TIOBE7月份榜单,要稳坐前十太难了??下一篇Go语言是 如何解决与实现跨域 问题的? 阅读 2225 Go语言圈 精选留言 写留言
- KuMo 上海7月18日 2 golang 的time包下面有个rate 实现了令牌桶
人划线
标签:ip,令牌,黑名单,bucket,白名单,限流,IP,go,Go From: https://www.cnblogs.com/cheyunhua/p/17912992.html