每隔几秒就有一次数据更新的http监听器

时间:2018-01-28 05:40:24

标签: go

我试图在Go中构建一个包含基于从Web服务收集的数据的报告的小网站。它使用API​​来查询服务以获取数据。该服务只能每隔几秒查询一次。

但是,我必须多次查询才能获得完整的报告数据。现在,每次调用http处理程序(http.HandleFunc)时,我都会使用API​​来更新我的整个数据结构。当然,这很糟糕,因为它会触发对受限制的外部API的大量查询。所以,我的报告非常,非常,非常缓慢地出现。

我想要做的是以非阻塞方式使用updateReportData函数并将该数据存储在http.HandleFunc()可以直接摄取的某个变量中而不调用外部API。

但是,我对Go(以及闭包,信号量,并发等等)很新,所以我不确定如何构建它。我应该使用频道吗?我应该使用计时器吗?如何让updateReportData不阻止http.HandleFunc,但仍然以固定的间隔运行?

总而言之,我希望有一个后台例程以固定的间隔更新数据结构,我希望能够使用http.HandleFunc在我发出http请求的任何时候提供数据结构中的任何数据。该程序。我根本不知道如何开始。任何建议将不胜感激。

1 个答案:

答案 0 :(得分:3)

您需要做一些事情:

  1. 创建一个轮询数据的后台服务。此服务可以作为goroutine运行,定期检查新数据。
  2. 创建后台服务用于将新数据发送到集中位置以存储值的通道。后台服务应该在发现新内容时将数据写入此通道。另一种选择是使用互斥锁保护集中式数据存储。根据数据的写入和读取方式,一个选项将是更好的选择。
  3. 创建一个HTTP处理程序,返回集中数据存储的当前内容。
  4. 这是一个简化示例,展示了如何使用goroutine和sync.RWMutext来实现您的目标:

    package main
    
    import (
        "fmt"
        "net/http"
        "sync"
        "time"
    )
    
    var (
        timeSumsMu sync.RWMutex
        timeSums   int64
    )
    
    func main() {
        // Start the goroutine that will sum the current time
        // once per second.
        go runDataLoop()
        // Create a handler that will read-lock the mutext and
        // write the summed time to the client
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            timeSumsMu.RLock()
            defer timeSumsMu.RUnlock()
            fmt.Fprint(w, timeSums)
        })
        http.ListenAndServe(":8080", nil)
    }
    
    func runDataLoop() {
        for {
            // Within an infinite loop, lock the mutex and
            // increment our value, then sleep for 1 second until
            // the next time we need to get a value.
            timeSumsMu.Lock()
            timeSums += time.Now().Unix()
            timeSumsMu.Unlock()
            time.Sleep(1 * time.Second)
        }
    }