수색…


노드를 사용하여 장기 실행 쿼리 처리

Node는 단일 스레드이므로 장기 실행 계산의 경우 해결 방법이 필요합니다.

참고 : 이것은 "실행할 준비가되었습니다"예제입니다. jQuery를 가져와 필요한 모듈을 설치하는 것을 잊지 마십시오.

이 예제의 주요 논리는 다음과 같습니다.

  1. 클라이언트가 서버에 요청을 보냅니다.
  2. 서버는 별도의 노드 인스턴스에서 루틴을 시작하고 관련 태스크 ID와 함께 즉시 응답을 보냅니다.
  3. 클라이언트는 주어진 태스크 ID의 상태 업데이트를 위해 서버에 점검을 지속적으로 보냅니다.

프로젝트 구조 :

    project
    │   package.json
    │   index.html    
    │
    ├───js
    │      main.js
    │      jquery-1.12.0.min.js
    │   
    └───srv
        │    app.js
        ├─── models
        │      task.js
        └─── tasks
               data-processor.js

app.js :

var express     = require('express');
var app         = express();
var http        = require('http').Server(app);
var mongoose    = require('mongoose');
var bodyParser  = require('body-parser');

var childProcess= require('child_process');

var Task        = require('./models/task');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(express.static(__dirname + '/../'));

app.get('/', function(request, response){
    response.render('index.html');
});

//route for the request itself
app.post('/long-running-request', function(request, response){
    //create new task item for status tracking
    var t = new Task({ status: 'Starting ...' });
    
    t.save(function(err, task){
        //create new instance of node for running separate task in another thread
        taskProcessor = childProcess.fork('./srv/tasks/data-processor.js');

        //process the messages comming from the task processor
        taskProcessor.on('message', function(msg){
            task.status = msg.status;
            task.save();
        }.bind(this));

        //remove previously openned node instance when we finished
        taskProcessor.on('close', function(msg){
            this.kill();
        });

        //send some params to our separate task
        var params = {
            message: 'Hello from main thread'
        };

        taskProcessor.send(params);
        response.status(200).json(task);
    });
});

//route to check is the request is finished the calculations
app.post('/is-ready', function(request, response){
    Task
        .findById(request.body.id)
        .exec(function(err, task){
            response.status(200).json(task);
        });
});

mongoose.connect('mongodb://localhost/test');
http.listen('1234');

task.js :

var mongoose    = require('mongoose');

var taskSchema = mongoose.Schema({
    status: {
        type: String
    }
});

mongoose.model('Task', taskSchema);

module.exports  = mongoose.model('Task');

data-processor.js :

process.on('message', function(msg){
    init = function(){
        processData(msg.message);
    }.bind(this)();
    
    function processData(message){
        //send status update to the main app
        process.send({ status: 'We have started processing your data.' });

        //long calculations ..
        setTimeout(function(){
            process.send({ status: 'Done!' });
            
            //notify node, that we are done with this task
            process.disconnect();
        }, 5000);
    }
});

process.on('uncaughtException',function(err){
    console.log("Error happened: " + err.message + "\n" + err.stack + ".\n");
    console.log("Gracefully finish the routine.");
});

index.html :

<!DOCTYPE html>
<html>
    <head>
        <script src="./js/jquery-1.12.0.min.js"></script>
        <script src="./js/main.js"></script>
    </head>
    <body>
        <p>Example of processing long-running node requests.</p>
        <button id="go" type="button">Run</button>
        
        <br />
        
        <p>Log:</p>
        <textarea id="log" rows="20" cols="50"></textarea>    
    </body>
</html>

main.js :

$(document).on('ready', function(){
    
    $('#go').on('click', function(e){
        //clear log
        $("#log").val('');
        
        $.post("/long-running-request", {some_params: 'params' })
            .done(function(task){
                $("#log").val( $("#log").val() + '\n' + task.status);
                
                //function for tracking the status of the task
                function updateStatus(){
                    $.post("/is-ready", {id: task._id })
                        .done(function(response){
                            $("#log").val( $("#log").val() + '\n' + response.status);
                            
                            if(response.status != 'Done!'){
                                checkTaskTimeout = setTimeout(updateStatus, 500);
                            }
                        });
                }
                
                //start checking the task
                var checkTaskTimeout = setTimeout(updateStatus, 100);
            });
    });
});

package.json :

{
  "name": "nodeProcessor",
  "dependencies": {
    "body-parser": "^1.15.2",
    "express": "^4.14.0",
    "html": "0.0.10",
    "mongoose": "^4.5.5"
  }
}

면책 조항 : 이 예제는 기본적인 아이디어를 제공하기위한 것입니다. 프로덕션 환경에서 사용하려면 개선이 필요합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow