限制每秒ping一个主机名的次数

时间:2016-09-30 20:34:21

标签: go

我正在编写一个网络爬虫来学习go

我目前的实现使用10个例程来获取网站,我想限制每秒命中主机名的次数。

执行此操作的最佳(线程安全)方法是什么。

1 个答案:

答案 0 :(得分:1)

channel提供了可用于协调的并发同步机制。您可以使用一个与time.Ticker协调来定期调度给定数量的函数调用。

// A PeriodicResource is a channel that is rebuffered periodically.
type PeriodicResource <-chan bool

// The NewPeriodicResourcePool provides a buffered channel that is filled after the
// given duration. The size of the channel is given as count. This provides
// a way of limiting an function to count times per duration.
func NewPeriodicResource(count int, reset time.Duration) PeriodicResource {
    ticker := time.NewTicker(reset)
    c := make(chan bool, count)

    go func() {
        for {
            // Await the periodic timer
            <-ticker.C

            // Fill the buffer
            for i := len(c); i < count; i++ {
                c <- true
            }
        }
    }()

    return c
}

单个go例程等待每个ticker事件并尝试将缓冲通道填充到最大容量。如果消费者没有耗尽缓冲区,任何连续的滴答只会重新填充它。您可以使用该频道以 n 次/ 持续时间同步执行操作。例如,我可能希望每秒呼叫doSomething()不超过五次。

r := NewPeriodicResource(5, time.Second)
for {
        // Attempt to deque from the PeriodicResource
        <-r

        // Each call is synchronously drawing from the periodic resource
        doSomething()
}

当然,可以使用相同的频道来呼叫go doSomething(),这会在每时散布出最多五个进程。