go实现白名单黑名单

发布时间 2023-12-19 10:13:23作者: 技术颜良

Go语言实现接口IP限流,黑名单&白名单的实例,都可用!

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语言哪些事儿 · 目录
上一篇TIOBE7月份榜单,要稳坐前十太难了??下一篇Go语言是 如何解决与实现跨域 问题的?
阅读 2225
 
精选留言
写留言
  •  
    golang 的time包下面有个rate 实现了令牌桶
     
     
已无更多数据