堆叠来自go例程的数据

问题描述 投票:0回答:1

我正在学习go lang,我想创建一个go app来实现以下功能。

  1. 从远程日志接收数据
  2. 析误
  3. 周期性地发送一个HTTP请求到一个URL,告知一切正常或者发送警告和错误。

我一直在阅读关于并发、并行和通道的文章,但我不知道应该如何将我的日志记录goroutine中的数据传递给另一个带有定时器的例程来进行请求。 我是否应该在另一个例程中声明一个分片来接收所有的消息,并在最后fo定时器对其进行迭代?

目前,我的代码是这样的。

package main

import (
    "fmt"
    "log"
    "strings"

    "gopkg.in/mcuadros/go-syslog.v2"
)

func strigAnalyze(str string){
/*analyse the contents of the log message and do something*/
}

func main() {

    channel := make(syslog.LogPartsChannel)
    handler := syslog.NewChannelHandler(channel)
    server := syslog.NewServer()
    server.SetFormat(syslog.RFC3164)
    server.SetHandler(handler)
    server.ListenUDP("0.0.0.0:8888")
    server.ListenTCP("0.0.0.0:8888")

    server.Boot()

    go func(channel syslog.LogPartsChannel) { 

        for logParts := range channel {
            content := logParts["content"]
            fmt.Println("logparts", logParts)
            string := fmt.Sprintf("%v", content)
            strigAnalyze(str) 
        }
    }(channel)
    server.Wait()
}
go concurrency goroutine
1个回答
1
投票

我是否应该在另一个例程中声明一个分片来接收所有的消息,并在最后fo定时器迭代它?

这是一个非常常见的模式在去。你所描述的例子有时被称为"例行监查". 它守护着日志的缓冲区,因为它 "拥有 "日志,所以你知道它们是安全的,不会被并发访问。

数据是通过通道共享的,日志数据的生产者将与发送者如何使用日志数据完全解耦,它所需要做的就是在通道上发送。如果通道是无缓冲的,那么你的生产者会阻塞,直到接收器可以处理。如果你需要保持生产者的高吞吐量,你可以对通道进行缓冲或 遣送,它看起来像。

select {
   case logChan <- log:
      ...
   default:
     // chan is full shedding data.
}

这种模式也很适合用于 "接收 "循环,即: for...selects 在输入通道、定时器和某种donecontext上进行选择。以下不是一个工作的例子,它缺少取消和逻辑,但它显示了你如何为...选择多个通道(其中一个是你的定时器心跳)。

logChan := make(chan string)

go func() {
   var logBuf []string
   t := time.NewTimer(time.Second * 5)
   for {
      select {
         log, ok := <-logChan:
            if !ok { return }
            logBuf = append(logBuf, log)
         <-t.C:
            // timer up
            // flush logs
            // reset slice
      }
   }
}()

另外,根据你如何使用数据, 在这里使用一个实际的缓冲区而不是切片可能更有意义。

© www.soinside.com 2019 - 2024. All rights reserved.