2017-01-10 1 views
0

Я новичок в Node JS, и я создаю небольшое приложение, основанное на файловой системе.Как убедиться, что два клиента не запрашивают в то же время повреждающее состояние

Допустим, что цель моего приложения, чтобы заполнить файл, как это:

1 
2 
3 
4 
.. 

И я хочу, чтобы при каждом запросе, новая строка записывается в файл, и в правильном порядке.

Могу ли я достичь этого?

Я знаю, что не могу задать свой вопрос здесь, не делая никакого кода, так вот. Я использую сервер Экспресс JS:

(представим себе, что файл содержит только 1 при первом запуске кода)

import express from 'express' 
import fs from 'fs' 

let app = express(); 

app.all('*', function (req, res, next) { 
    // At every request, I want to write my file 
    writeFile() 
    next() 
}) 

app.get('/', function(req,res) { 
    res.send('Hello World') 
}) 

app.listen(3000, function (req,res) { 
    console.log('listening on port 3000') 
}) 

function writeFile() { 
    // I get the file 
    let content = fs.readFileSync('myfile.txt','utf-8') 

    // I get an array of the numbers 
    let numbers = content.split('\n').map(item => { 
     return parseInt(item) 
    }) 

    // I compute the new number and push it to the list 
    let new_number = numbers[numbers.length - 1] + 1 
    numbers.push(new_number) 

    // I write back the file 
    fs.writeFileSync('myfile.txt',numbers.join('\n')) 
} 

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

Если я неясно, скажите, пожалуйста, в комментариях

+0

Является ли это проблемой XY или вы действительно просто пишете в файл число, увеличивающееся число экземпляров? – mscdex

+0

После прочтения определения, я думаю, это может быть. Но решение этой проблемы действительно поможет мне понять поведение узла, я думаю. – Hammerbot

ответ

2

Если я правильно вас понял, что вы боитесь является race condition, в этом случае, если два клиента одновременно достигают HTTP-сервера, файл сохраняется с тем же содержимым, где число увеличивается только один раз, а не дважды.

Простое исправление заключается в том, чтобы обеспечить совместный доступ или изменение общего ресурса один раз за раз. В этом случае, используя синхронные методы, исправьте проблему. Как и при выполнении всего узла, процесс блокируется и ничего не будет делать.

Если вы измените синхронные методы с их асинхронными счетчиками без каких-либо других мер контроля параллелизма, ваш код определенно будет уязвим для условий гонки или повреждения.

Теперь, если это только то, что делает ваше приложение, лучше всего сохранить этот способ, поскольку это очень просто, но предположим, что вы хотите добавить к нему другие функции, в этом случае вы, вероятно, захотите избежать любых синхронных методы, поскольку он блокирует процесс и не позволит вам иметь параллелизм.

Простым способом добавления контроля параллелизма является наличие счетчика, который отслеживает количество запросов в очереди. Если ничего не поставлено в очередь (counter === 0), тогда мы просто читаем и записываем файл, иначе добавляем счетчик. После записи в файл закончен, мы уменьшаем от прилавка и повторить:

app.all('*', function (req, res, next) { 
    // At every request, I want to write my file 
    writeFile(); 
    next(); 
}); 

let counter = 0; 

function writeFile() { 
    if (counter === 0) { 
    work(function onWriteFileDone() { 
     counter--; 
     if (counter > 0) { 
     work(); 
     } 
    }); 
    } else { 
    counter++; 
    } 

    function work(callback) { 
    // I get the file 
    let content = fs.readFile('myfile.txt','utf-8', function (err, content) { 
     // ignore the error because life is too short on stackoverflow questions... 

     // I get an array of the numbers 
     let numbers = content.split('\n').map(parseInt); 

     // I compute the new number and push it to the list 
     let new_number = numbers[numbers.length - 1] + 1; 
     numbers.push(new_number); 

     // I write back the file 
     fs.writeFile('myfile.txt',numbers.join('\n'), callback); 
    }); 
    } 
} 

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

Теперь не записывайте свои собственные механизмы параллелизма. В экосистеме узлов много. Например, вы можете использовать async module, which provide a queue.

Обратите внимание, что если у вас есть только один процесс за раз, вам не нужно беспокоиться о нескольких потоках с тех пор, как в узле.js, в одном процессе есть только один поток выполнения за раз, но предположим, что в файл записано несколько процессов, что может усложнить ситуацию, но давайте оставим это для другого вопроса, если он еще не охвачен. Операционные системы предоставляют несколько различных способов справиться с этим, также вы можете использовать свои собственные файлы блокировки или выделенный процесс для записи в файл или процесс очереди сообщений.

Смежные вопросы