首页 > 其他分享 >go实现白名单黑名单

go实现白名单黑名单

时间:2023-12-19 10:25:01浏览次数:27  
标签:ip 令牌 黑名单 bucket 白名单 限流 IP go Go

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

相关文章

  • go服务get请求中携带分号(;)时报错,获取不到参数的问题
    前言我们在写get方式的api请求时,有时候会用这样的一种方式携带参数:http://ip:port/a/b?query=key:1;value:2&other=xxx,这里我们注意到query一个字段其实是携带了等子字段的,一个是key,一个是value;这在go1.17版本之前是没有问题的。但是在1.17之后打印警告,在1.20之后,go服务......
  • Google Guava:EventBus
    EventBus是Guava中对于事件发布订阅功能的实现,是设计模式中的发布/订阅模式的一种实现方案。功能概括:通过eventBus.register注册订阅者,通过eventBus.post方法发布事件,然后根据发布事件的类型(classType),执行所有订阅者中被@Subcribe注解标记的且参数类型一致的方法,从而实现发布、......
  • 65道Go基础高频题整理(附答案背诵)
    说明一下Golang中make和new的区别?好的,关于make和new在Go语言中的区别,我来解释一下。new函数的作用:new(T)函数会为T类型的新项分配零值内存,并返回其地址,即一个*T类型的值(指针)。这种方法适用于各种类型,包括基本类型如int、float、bool等,以及数组、结构体等......
  • 数据结构与算法 第二章线性表(48课时课程笔记)Data Structure and Algorithms
    2.1线性表的类型定义一个线性表是n个数据元素的有限序列。 (1)结构初始化 InitList(&L) 构造一个空的线性表L。(2)销毁结构 DestroyList(&L)(3)引用型操作  (4)修改型操作  一个算法举例:假设有两个集合A和B分别用两个线性表LA和LB表示(即:线性表中的数据元素即为集......
  • RK3568 android12 动态替换开机logo
    前言:最近客户有个需要,通过adbpush来动态替换开机logo。通过网上查阅相关资料,现整理如下。参考:RK3568Android/Linux系统动态更换U-Boot/KernelLogo解决方法:通过自定义一个分区来存储开机logo,这样在恢复出厂时不会丢失开机logo。然后通过修改u-boot/drivers/video/drm/rock......
  • Django ORM 基本操作
    本次sql大部分习题出自知乎以为网友,对原sql感兴趣的各位朋友,可以去参考知乎上的这位朋友:https://www.zhihu.com/tardis/bd/art/38354000?source_id=1001我们在他的基础上,进行sql改造,成为我们DjangoORM机制下的ORM语法。本次教程的面向人群:我们默认你会使用Django,至少能够自己......
  • Django报错UnorderedObjectListWarning: Pagination may yield inconsistent results
    Django报错UnorderedObjectListWarning:Paginationmayyieldinconsistentresults withanunorderedobject_list报错报错信息如下:Django报错Django报错UnorderedObjectListWarning:Paginationmayyieldinconsistentresults withanunorderedobject_list:<class......
  • go gorm 软删除和查询
    软删除如果您的模型包含了一个gorm.deletedat字段(gorm.Model已经包含了该字段),它将自动获得软删除的能力!拥有软删除能力的模型调用Delete时,记录不会从数据库中被真正删除。但GORM会将DeletedAt置为当前时间,并且你不能再通过普通的查询方法找到该记录。//user的ID......
  • MongoDB mongoshake 迁移分片到复制集合
    Mongoshake是阿里云自研的开源工具,实现Mongodb数据库之间的数据同步,数据灾备,数据多活,分库分表,版本升级无间断。其中需要注意的一些事项1 Mongoshake尽量使用较高的版本,低版本的产品有一些Bug 2 Mongoshake在使用中需要源库的用户权限为readAnyDatabase  同时Mongoshake......
  • Linux服务器快速安装MongoDB-5.0
    最近开始体验FastGPT开源知识库问答系统,用他们试着开发调试一些小助手。这中间需要使用到MongoDB,就在自己服务器上进行了安装,特此记录下。环境说明:阿里云ECS,2核8G,X86架构,CentOS7.9操作系统。选择版本1.打开MongoDB社区版下载页面,选择我们想要安装的版本、操作系统、和包类型,......