手拉手開發nodejs電影cms系統②:定時任務,視頻源數據,初始化數據

nodejs定時任務一直是個讓人頭疼的問題,我在作以前就已經看到過不少人發問題問到pm2部署項目之後,多線程的問題下,
如何關閉定時任務,
或者任務被多個線程同時執行
這類問題。前端

第一章手拉手開發nodejs電影cms系統①:內容規劃,導航分類,視頻數據,用戶,留言
第二章手拉手開發nodejs電影cms系統②:定時任務,視頻源數據,初始化數據
第三章手拉手開發nodejs電影cms系統③:寶塔面板懶人部署node

pm2部署沒法關閉任務(後臺)

pm2部署沒法關閉任務是由於,用戶(管理員)開啓定時任務的時候,可能被pm2分發到了B線程(假設電腦6核心12線程),你:我電腦就雙核哪來的六核心?mongodb

image.png

很差意思,個人12線程。數據庫

扯遠了,扯回來。
當用戶(管理員)想關閉的時候pm2可能把任務分發到了G線程上了,可是G線程上並無執行這個任務,就會報錯。npm

定時任務被多個線程同時執行?

那是由於這個定時任務是項目部署開啓服務的時候就設置好了,到了時間,pm2複製多份任務執行(一毛同樣),固然就會重複跑任務。json

怎麼避免合適?

試想一下,若是咱們項目用pm2部署,複製了12份node項目。可是咱們可使用別的進程守護工具,例如forever(單份,單線程)守護定時任務。
說人話:就是分兩個項目部署,定時任務使用一個單線程守護工具,守護。這樣,定時任務到時間之後就是單線程跑了,不會多線程同時調用。隨之而來的一個問題,怎麼通信??pm2那邊的服務怎麼通知forever這邊守護的的進程開啓關閉任務。(http服務啊)segmentfault

假設pm2守護的項目監聽的是8888端口,咱們forever這邊的js開啓的http服務能夠監聽9999。二者之間通信就發post請求。(由於本機的緣由。因此很快,秒收到)這樣,通信的問題解決,就能夠隨時動態的建立/刪除 定時任務了。也不會出現多線程同時執行的問題。session

視頻源錄入(後臺)

上一章說了,視頻數據錄入格式。播放源如何錄入,長啥樣?
和留言關聯視頻表,關聯用戶表同樣。視頻源的數據也須要單獨出來,由於若是不單獨出來,咱們只是查詢一下電影列表,不須要展現播放源列表的時候,沒有必要無故帶出來那麼多的數據
image.png多線程

一樣使用mongodb管道聯表操做就能夠很容易關聯出源的數據。async

初始化數據(後臺)

可能剛入坑nodejs的cxk沒懂,簡稱就是項目初始化默認就必須有的數據,好比博客總得有個默認的後臺系統的root用戶吧,默認的頂級分類,一些默認的配置,從哪來??確定不會天上掉下來。

nodejs pakcage。json的script字段用於定義一些命令。前端的確定知道,npm run dev,npm run build這些你確定經常使用

你徹底能夠再script定義你的初始化數據命令。好比我

"scripts": {
    "build": "node ./build/initDataBase.js",
    "restore": "mongorestore -d movie ./backup/movie",
    "backup": "mongodump -d movie -o ./backup/movie"
}

build用於鏈接數據庫,刪除原有的數據庫,建立全新的數據庫,建立字段索引,並向數據庫中插入默認的數據,好比電影cms系統的默認管理員信息。初始化的數據

const mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient,
config = require('../utils/config.js'),
dbConfig = config.project;

let connectURL = 'mongodb://127.0.0.1:27017';

let client = MongoClient.connect(connectURL, { useNewUrlParser: true, useUnifiedTopology: true });

client.then(async (db) => {

    let DB = db.db(dbConfig.dbName);

    await new Promise(async (resolve, reject) => {

        console.log('正在清除原始數據表');
        await DB.dropCollection('session1').catch(err => {});
        await DB.dropCollection('session2').catch(err => {});
        await DB.dropCollection('config').catch(err => {});
        await DB.dropCollection('logs').catch(err => {});
        await DB.dropCollection('message').catch(err => {});
        await DB.dropCollection('other').catch(err => {});
        await DB.dropCollection('user').catch(err => {});
        await DB.dropCollection('video_info').catch(err => {});
        await DB.dropCollection('video_list').catch(err => {});
        resolve()
    })
    .then(() => {
        console.log('原始數據表清除完成');
    })
    .catch(err => {
        console.log('+++', err);
    })
    
    await new Promise(async (resolve, reject) => {
        console.log('開始重建數據表');
        await DB.createCollection('session1');
        await DB.createCollection('session2');
        await DB.createCollection('config');
        await DB.createCollection('logs');
        await DB.createCollection('message');
        await DB.createCollection('other');
        await DB.createCollection('user');
        await DB.createCollection('video_info');
        await DB.createCollection('video_list');
        resolve()
    })
    .then(() => {
        console.log('數據表重建完成');
    })
    await new Promise(async (resolve, reject) => {
        console.log('開始建立用戶數據');
        // 用戶字段索引
        let userColl =  DB.collection('user');
        // 索引字段
        await userColl.createIndexes([
            {key:{userName: 1}},
            {key:{passWord: 1}},
            {key:{display: 1}},
            {key:{admin: 1}},
            {key:{grade_id: 1}},
            {key:{default: 1}}
        ]);
        await userColl.insertOne({
            userName: 'root',
            passWord: 'e10adc3949ba59abbe56e057f20f883e',  // 123456 md5
            nickName: '網站全部者',
            admin: true,
            display: true,
            default: true,
            grade_id: 2,                                   // 0用戶 1管理員 2root用戶
        });
        resolve();
    })
    .then(res=>{
        console.log('用戶數據建立成功');
    })
});
相關文章
相關標籤/搜索