Какой самый быстрый и безопасный способ добавить записи в файл на диске в высоконагруженном обработчике http .ashx? - PullRequest
3 голосов
/ 09 декабря 2011

Каков наилучший вариант для записи (добавления) записей в файл в высокопараллельной веб-среде в .net4 IIS7? Я использую ashx http handler для получения небольших порций данных, которые должны быть быстро записаны в файл. Сначала я использовал:

    using (var stream = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 8192))
    {
        stream.Write(buffer, 0, buffer.Length);
    } 

Но я заметил, что некоторые записи были битыми или неполными, возможно, из-за FileShare.ReadWrite. Затем я попытался переместить его в FileShare.Read. Там, где нет поврежденных записей, но время от времени я получал это исключение: System.IO.IOException: процесс не может получить доступ к файлу ... потому что он используется другим процессом.

В идеале я бы хотел, чтобы операционная система ставила в очередь параллельные запросы на запись, чтобы в конечном итоге были записаны все записи. Какой API доступа к файлам я должен использовать?

Ответы [ 2 ]

3 голосов
/ 09 декабря 2011

есть два варианта, в зависимости от размера.Если размер небольшой, , вероятно, , лучший вариант - просто синхронизировать доступ к файлу с помощью какой-либо общей блокировки.Если возможно, было бы также хорошей идеей, чтобы файл оставался открытым (иногда сбрасывался), а не постоянно открывался / закрывался.Например:

class MeaningfulName : IDisposable {
    FileStream file;
    readonly object syncLock = new object();
    public MeaningfulName(string path) {
        file =  new FileStream(fileName, FileMode.Append, FileAccess.Write,
           FileShare.ReadWrite, 8192);
    }
    public void Dispose() {
        if(file != null) {
           file.Dispose();
           file = null;
        }
    }
    public void Append(byte[] buffer) {
        if(file == null) throw new ObjectDisposedException(GetType().Name);
        lock(syncLock) { // only 1 thread can be appending at a time
            file.Write(buffer, 0, buffer.Length);
            file.Flush();
        }
    }
}

Это потокобезопасно и может быть доступно всем ashx без проблем.

Однако для больших данных вы можете захотеть взглянуть на синхронизированныйочередь чтения-записи - т. е. все авторы (обращения Ashx) могут перебрасывать данные в очередь, причем один выделенный поток записи снимает их с очереди и добавляет.Это удаляет время ввода-вывода из ashx, однако вы можете ограничить размер очереди на тот случай, если писатель не успевает за ней.Здесь приведен пример закрытой синхронизированной очереди чтения / записи .

0 голосов
/ 09 декабря 2011

Если вы не используете веб-сад или веб-ферму, я бы рекомендовал использовать локальную блокировку процесса (lock () {}) и выполнять как можно больше обработки за пределами блокировки.

Если у вас есть несколько файлов для записи, см. Лучшее решение для многопоточной загадки? для хорошего решения.

...