我想从某个 ajax 脚本向一个文件写入请求。当一秒钟内会有很多这样的请求并且写入文件比请求之间的中断花费更多的时间,并且同时有两个请求时,就会出现问题。
我该如何解决这个问题?
我想到了使用互斥量,例如:
var mu sync.Mutex
func writeToFile() {
mu.Lock()
defer mu.Unlock()
// write to file
}
但它使整个事情同步,我真的不知道当同时有两个请求时会发生什么。而且它仍然不会锁定文件本身。
呃,正确的做法是什么?
最佳答案
你只需要让写入文件成为“顺序的”,这意味着不允许 2 个并发的 goroutines 写入文件。是的,如果您在 writeToFile()
函数中使用锁定,则服务您的 ajax 请求也可能会(部分)顺序化。
我的建议是在您的应用程序启动时打开文件一次。并指定一个 goroutine 负责写入文件,其他 goroutine 不应该这样做。
并使用缓冲 channel 发送应写入文件的数据。这将使服务 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
channel :当它关闭时,writeToFile()
中的循环将终止,文件将被关闭(刷新任何缓存数据,释放操作系统资源)。
如果你想向文件写入文本,你可以像这样声明data
channel :
var datach = make(chan string, 100) // Buffered channel
你可以使用 File.WriteString()
将其写入文件:
if _, err := f.WriteString(data); err != nil {
// handle error!
}
关于ajax - 从ajax请求并发写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37411114/