2016-05-24 10 views
1

いくつかのajaxスクリプトから1つのファイルにリクエストを書きたいと思っています。問題は、2番目に多くのファイルが存在し、ファイルへの書き込みに要求間のブレークよりも時間がかかる場合と、同時に2つの要求がある場合に発生します。ajaxリクエストからのファイルへの同時書き込み

どうすればこの問題を解決できますか?

私は次のように、ミューテックスを使用して来ました:

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

しかし、それは全体のことは同期になり、私は本当に、同時に2つの要求があったときに何が起こるか分かりません。それでもファイル自体はロックされません。

これを行うには適切な方法はありますか?

+0

'ミューテックス.Lockは、ゴルーチン内からのリソースへの排他的なアクセスを保証するために使用されます。グローバルリソースを読み書きしようとするいくつかのゴルーチンがある場合に便利です。ファイルへの書き込みはブロックI/Oであり、そのゴルーチンを自然にブロックする必要があります。 – PieOhPah

答えて

4

"sequential"というファイルに書き込む必要があるのは、2つの並行するゴルーチンがファイルに書き込むことができないということです。はい、writeToFile()関数でロックを使用すると、あなたのAjaxリクエストの処理が(部分的に)順次になることもあります。

私が提案するのは、アプリケーションを起動するときにファイルを一度開くことです。ファイルへの書き込みを担当する単一のゴルーチンを指定します。他のgoroutinesはそれを行うべきではありません。

バッファされたチャネルを使用して、ファイルに書き込まれるデータを送信します。これにより、ajaxリクエストは非ブロッキングになりますが、ファイルは同時に並行/並行して書き込まれません。

このように、データが実際にファイルに書き込まれている間(応答時間が速い)、Ajaxリクエストは待つ必要がないことに注意してください。これは問題である場合とそうでない場合があります。たとえば、後で書き込みが失敗した場合、Ajaxレスポンスはすでにコミットされている可能性があります。>クライアントに失敗を通知する機会はありません。

それを行う方法の例:(それが閉じていたときに、writeToFile()のループが終了すると、ファイルが閉じられます。

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チャネルを閉じる必要がありますキャッシュされたデータをフラッシュし、OSリソースを解放する)。

ファイルにテキストを書き込みたい場合は、あなたがこのようなdataチャンネル宣言してもよい:

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

をし、ファイルに書き込みFile.WriteString()を使用することがあります。

if _, err := f.WriteString(data); err != nil { 
    // handle error! 
} 
関連する問題