从ajax请求并发写入文件

时间:2016-05-24 10:36:33

标签: ajax file go concurrency

我想从一些ajax脚本向一个文件写入请求。问题出现在一秒钟内会有很多这样的问题,写入文件将比请求之间的中断花费更多的时间,并且同时会有两个请求。

我怎么解决这个问题?

我使用互斥量,比如:

var mu sync.Mutex
func writeToFile() {
    mu.Lock()
    defer mu.Unlock()
    // write to file
}

但它使整个事情同步,我真的不知道当同时有两个请求时会发生什么。它仍然不会锁定文件本身。

呃,这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

您只需要将文件写入“顺序”,这意味着不允许2个并发的goroutine写入文件。是的,如果您在writeToFile()函数中使用锁定,那么提供ajax请求也可能(部分)顺序。

我建议您在应用程序启动时打开文件一次。并指定一个单独的goroutine,负责写入文件,没有其他goroutines应该这样做。

使用缓冲通道发送应写入文件的数据。这将使服务ajax请求无阻塞,并且仍然不会同时/并行地写入文件。

请注意,这样ajax请求甚至不必在数据实际写入文件时等待(响应时间更快)。这可能是也可能不是问题。例如,如果稍后写入失败,则您的ajax响应可能已经提交=>没有机会向客户发出失败信号。

示例如何操作:

var (
    f      *os.File
    datach = make(chan []byte, 100) // Buffered channel
)

func init() {
    // Open file for appending (create if doesn't exist)
    var err error
    f, err = os.OpenFile("data.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
    if err != nil {
        panic(err)
    }

    // Start goroutine which writes to the file
    go writeToFile()
}

func writeToFile() {
    // Loop through any data that needs to be written:
    for data := range datach {
        if _, err := f.Write(data); err != nil {
            // handle error!
        }
    }
    // We get here if datach is closed: shutdown
    f.Close()
}

func ajaxHandler(w http.ResponseWriter, r *http.Request) {
    // Assmeble data that needs to be written (appended) to the file
    data := []byte{1, 2, 3}
    // And send it:
    datach <- data
}

要正常退出应用程序,您应该关闭datach频道:当它关闭时,writeToFile()中的循环将终止,文件将被关闭(刷新任何缓存的数据,释放OS资源)。

如果您想在文件中写入文字,可以像这样声明data频道:

var datach = make(chan string, 100) // Buffered channel

您可以使用File.WriteString()将其写入文件:

if _, err := f.WriteString(data); err != nil {
    // handle error!
}