Golang 高并发限流操作 ping/telnet 的完整攻略
在分布式系统中,高并发请求是不可避免的问题,如何防止恶意攻击和拒绝服务攻击是一个必须解决的问题。Golang 作为一种高性能的编程语言,提供了良好的支持来解决这些问题。本文介绍如何使用 Golang 实现高并发的 ping / telnet 限流操作。
原理简介
在 Golang 中,我们可以使用 os/exec
模块的 Command
函数来执行系统命令。同时,time.Ticker
可以用于定时器触发。在定时器触发调用命令之前,可以将相关信息保存到一个临时 Map 中。在执行命令之后将 Map 中对应的信息删除。如果在一秒钟内有超过设定的阈值数量的请求,我们就认为这是一个恶意攻击或拒绝服务攻击,直接将其拒绝。
具体实现
我们首先需要定义一个结构体,用于保存每个请求的信息,如下所示:
type request struct {
ip string
cmd *exec.Cmd // 用于保存正在执行的命令
}
// 用于保存需要触发的命令和请求对象的 Map
var reqs = make(map[string]*request)
然后我们需要实现一个函数,用于触发 ping / telnet 命令,并记录请求信息:
func processRequest(ip string) error {
ipKey := strings.ReplaceAll(ip, ".", "_") // 将点分格式的 IP 转换为 Map 中的 Key
if _, ok := reqs[ipKey]; ok {
return errors.New("request already exists")
}
cmd := exec.Command("ping", "-c", fmt.Sprintf("%d", COUNT), "-w", fmt.Sprintf("%d", TIMEOUT), ip)
if err := cmd.Start(); err != nil {
return err
}
reqs[ipKey] = &request{ip: ip, cmd: cmd}
return nil
}
我们在 processRequest
函数中触发一个 ping 命令,同时将请求信息保存到 Map 中。
接下来,我们需要使用定时器循环读取 Map 中的信息,判断是否超过了限流阈值。如果超过了阈值,则终止正在执行的命令,否则继续等待。
func checkLimit() {
t := time.NewTicker(time.Second)
for range t.C {
for key, req := range reqs {
if req.cmd.ProcessState == nil {
// 如果命令没有执行完成,则继续等待
continue
}
delete(reqs, key) // 从 Map 中删除请求信息
if req.cmd.ProcessState.ExitCode() == 0 {
continue
}
counter[req.ip] += 1 // 记录请求次数
if counter[req.ip] > MAX_COUNT {
req.cmd.Process.Kill() // 终止进程
fmt.Printf("access from %s is blocked\n", req.ip)
}
}
}
}
在 checkLimit
函数中,我们循环读取 Map 中的信息,判断是否超过了限流阈值。如果超过了阈值,则终止正在执行的命令并输出警告信息。
我们还需要定义一个全局变量,用于记录每个 IP 地址的请求次数:
var counter = make(map[string]int)
最后,我们需要调用 processRequest
函数来触发请求,并启动定时器。
func main() {
for i := 0; i < MAX_COUNT*2; i++ {
processRequest("1.1.1.1")
processRequest("2.2.2.2")
processRequest("3.3.3.3")
}
go checkLimit() // 启动定时器
}
示例说明
在上面的示例中,我们使用 processRequest
函数来触发 6 个 IP 地址的请求,并使用 checkLimit
函数来限流和阻止恶意请求。在一秒钟内,如果有超过 10 个的请求,则会被判断为恶意请求,并被直接拒绝。这样就可以有效地防止恶意攻击和拒绝服务攻击。
另外一个示例,我们可以针对 telnet 进行限流,具体可以参考上面的示例代码进行调整。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:golang高并发限流操作 ping / telnet - Python技术站