je cherche a faire fonctionner des websocket en cluster.
à l'heure actuelle mon programme nodejs a gagner énormément en performance grace à ça.
le problème maintenant est que je n'arrive pas à faire communiquer les différents processuse entre eux.
ceci ne pause aucuns problèmes apparents lorsque j'effectue qu'une seule requête.
Mais à chaque fois qu'il y a requète, il y a possibilitée de créer un nouveau socket sans que le socket du serveur ne se ferme.
je m'en remets à vos avis
fichier maître:
let cluster = require('cluster');
let os = require('os');
let cpu = os.cpus();
let cfg = require('./cfg.json');
let sqp = require('./lib/sql_profile');
function server_start() {
console.log('mcm: server is starting');
mysql_init();
function mysql_init(){
//mysql init
let sql = sqp.normal
let basic_sql = sqp.basic
let mysql = require('mysql')
var con = mysql.createConnection(sql)
con.connect((err, res) => {
if (err) {
con.destroy();
setTimeout(() => {
con.end()
create_db()
}, 200);
} else {
console.log('mcm: controling mysql table')
setTimeout(() => {
controle_tables()
}, 100);
}
})
function create_db() {
con = mysql.createConnection(basic_sql)
con.connect((err, res) => {
if (err) {
console.log("mcm: couldn't connect to mysql server (make sure that your mysql server is on or good configured)")
} else {
console.log("mcm: creating mysql database")
con.query('CREATE DATABASE '+cfg.mysql.database+' CHARACTER SET utf8 COLLATE utf8_bin', (err, res) => {
if (err) {
console.log("mcm: unable to create the database")
return process.exit(0);
} else {
console.log("mcm: database created !!")
console.log('mcm: installing mysql table')
con.destroy()
con = mysql.createConnection(sql)
controle_tables()
}
});
}
});
}
function controle_tables() {
let tb_list = ["mcm_user", "mcm_post", "mcm_post_answer", "mcm_forum", "mcm_forum_answer"];
let crt_set = {
mcm_user: "create table if not exists mcm_user(id INT(20) PRIMARY KEY AUTO_INCREMENT, "+
"account VARCHAR(20), password VARCHAR(255) NOT NULL, describ VARCHAR(255) NULL, group_list TEXT NULL, "+
"public_name VARCHAR(20) NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, last_login DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, "+
"power_level INT DEFAULT '0', suspend ENUM('0','1') NOT NULL DEFAULT '0', user_status ENUM('online','offline','away') NOT NULL DEFAULT 'offline',"+
"mail VARCHAR(36), is_admin ENUM('TRUE','FALSE') NOT NULL DEFAULT 'FALSE')",
mcm_post: "create table if not exists mcm_post(id INT(40)PRIMARY KEY AUTO_INCREMENT, "+
"autor VARCHAR(255) NOT NULL, reaction TEXT NULL, tag VARCHAR(255) NULL DEFAULT 'random',"+
"content TEXT, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"+
")",
mcm_post_answer: "create table if not exists mcm_post_comment(id INT(40)PRIMARY KEY AUTO_INCREMENT, "+
"post_id INT(40) NOT NULL, autor VARCHAR(255) NOT NULL, reaction TEXT NULL, "+
"content TEXT, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"+
")",
mcm_forum: "create table if not exists mcm_forum(id INT(40)PRIMARY KEY AUTO_INCREMENT, "+
"category VARCHAR(255) NOT NULL DEFAULT 'uncategorised', topic VARCHAR(255) NOT NULL DEFAULT 'default',"+
"autor VARCHAR(255) NOT NULL, reaction TEXT NULL, modified DATETIME NULL, "+
"subject VARCHAR(255) NULL, content TEXT, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"+
")",
mcm_forum_answer: "create table if not exists mcm_forum_comment(id INT(40)PRIMARY KEY AUTO_INCREMENT, "+
"subject_id INT(40) NOT NULL, autor VARCHAR(255) NOT NULL, reaction TEXT NULL, "+
"content TEXT, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, modified DATETIME NULL"+
")"
}
var i = 0;
tb_list.forEach(table => {
con.query(crt_set[table], (err, res) => {
if (err) {
console.log(err);
return process.exit(0);
} else {
console.log('mcm: '+table.replace('mcm_', '')+' ready !');
i++;
if (i == tb_list.length) {
console.log('mcm: mysql database are ready to be used! ');
find_user_admin();
}
}
});
});
function find_user_admin() {
var rows = []
con.query('SELECT * FROM mcm_user WHERE account = ? AND password = ?', [cfg.admin.account, cfg.admin.password])
.on('result', (row, any) => {
rows.push(row)
})
.on('end', () => {
if (rows.length === 0) {
con.query('INSERT INTO mcm_user (account, password, public_name, mail, is_admin)'+
' VALUES (?,?,?,?,?)', [cfg.admin.account, cfg.admin.password,
cfg.admin.public_name, cfg.admin.mail, 'TRUE'])
}
enable_threads();
})
}
}
}
}
function enable_threads() {
for (let i = 0; i < cpu.length; i++) {
cluster.fork()
}
cluster.on('exit', (worker, code, signal) => {
console.log('worker '+ worker.process.pid +' terminated');
});
}
if (cluster.isMaster) {
//single thread socket
let io = require('socket.io')()
io.on('connection', (socket)=>{
console.log('new');
})
//begin server
server_start()
} else {
require('./cluster.js');
}
cluster :
let http = require('http')
let https = require('https')
let url = require('url')
let fs = require('fs')
let cfg = require('./cfg.json')
let ext = require('path')
let app = require('express')()
let session = require('express-session')
let MySqlStore = require('express-mysql-session')(session);
let bodyParser = require('body-parser')
let cookieParser = require('cookie-parser')
// body-parser
var url_encoder = bodyParser.urlencoded({ extended: false })
var jsonParser = bodyParser.json()
// mysql-session-setup
var store_opt = {
host: cfg.mysql.server,
port: cfg.mysql.port,
user: cfg.mysql.user,
password: cfg.mysql.pass,
database: cfg.mysql.database,
clearExpired: true,
checkExpirationInterval: 1000 * 60 * 30,
endConnectionOnClose: true,
charset: 'utf8mb4_bin',
schema: {
tableName: 'mcm_session',
columnNames: {
session_id: 'session_id',
expires: 'expires',
data: 'data'
}
}
}
let store = new MySqlStore(store_opt)
//cookies
app.use(cookieParser('lorem_pixeview'))
//session
app.set('trust-proxy', 1)
app.use(session({
name: 'session',
secret: 'lorem_pixeview',
store: store,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 1000*60*60*24*30,
sameSite: 'Lax',
secure: true
}
}))
function session_update(req, res) {
var session = req.session;
session.cookie.expires = new Date(Date.now() + (1000*60*60*24*30));
}
function cookie_update(req, res) {
var session = req.session
var sessionparam = req.session.cookie
sessionparam.sameSite = 'Lax'
var cookie = req.cookies["user-param"]
if (!cookie) {
res.cookie('user-param', {account:"",password:"",connected:false}, sessionparam)
}
if (session.connected == true) {
res.cookie('user-param', {account:session.username ,password:session.password ,connected:true}, sessionparam)
}
}
// http redirect
http.createServer((req, res) => {
path = url.parse(req.url).pathname;
host = req.headers.host;
res.writeHead(301, {Location: 'https://'+host+path })
res.end()
}).listen(80)
//https
let ssl_opt = {
key: fs.readFileSync('./lib/ssl/key.pem'),
cert: fs.readFileSync('./lib/ssl/cert.pem')
}
let serv = https.createServer(ssl_opt, app)
var _404 = '<h1> FILE NOT FOUND</h1>'
var _403 = '<h1> FORBBIDEN ACCESS</h1>'
app.get('/', (req, res) => {
var cookie = req.cookies['user-param']
if (!req.session.connected && cookie) {
if (cookie.connected != false) {
require('./lib/pages/session').connect(req, res, data = {account:cookie.account, password:cookie.password})
return false;
}
} else {
session_update(req, res)
cookie_update(req, res)
}
//initial
fs.readFile('index.html', 'utf-8' ,(err, data) => {
if (err) {
res.writeHead(404)
res.send(_404)
} else {
if (req.session.connected == true) {
data = data.replace('<body class="s-showpage">', '<body class="s-left-navigation">')
} else if (req.session.badlogin) {
delete req.session.badlogin
data = data.replace('<body class="s-showpage">', '<body class="s-showpage wrong-password">')
}
res.end(data)
}
})
})
app.get('/*', (req, res) => {
var file = req.url.replace('/','')
if (file.match(/lib\/.+|cfg\.json|package.+|node_modules\/.+/g)) {
res.writeHead(403)
res.end(_403)
return false;
}
fs.readFile(file, (err, data) => {
if (err) {
res.writeHead(404)
res.end(_404)
} else {
var fmt = ext.extname(file);
switch (fmt) {
// exec files
case '.css':
res.writeHead(200, {'Content-Type':'text/css'})
break;
case '.js':
res.writeHead(200, {'Content-Type':'application/javascript'})
break;
case '.json':
res.writeHead(200, {'Content-Type':'application/json'})
break;
case '.html':
res.writeHead(200, {'Content-Type':'text/html; charset=utf-8'})
break;
case '.xml':
res.writeHead(200, {'Content-Type':'application/xml'})
break;
// archives
case '.zip':
res.writeHead(200, {'Content-Type':'application/zip'})
break;
case '.rar':
res.writeHead(200, {'Content-Type':'application/x-rar-compressed'})
break;
// image-icons
case '.ico':
res.writeHead(200, {'Content-Type':'image/x-icon'})
break;
case '.jpg' || '.jpeg':
res.writeHead(200, {'Content-Type':'image/jpeg'})
break;
case '.png':
res.writeHead(200, {'Content-Type':'image/png'})
break;
case '.gif':
res.writeHead(200, {'Content-Type':'image/gif'})
break;
case '.svg':
res.writeHead(200, {'Content-type':'image/svg+xml'})
break;
// media
case '.aac':
res.writeHead(200, {'Content-type':'audio/aac'})
break;
case '.mid' || '.midi':
res.writeHead(200, {'Content-type':'audio/midi'})
break;
case '.rtf':
res.writeHead(200, {'Content-type':'application/rtf'})
break;
case '.ttf':
res.writeHead(200, {'Content-type':'font/ttf'})
break;
case '.avi':
res.writeHead(200, {'Content-type':'video/x-msvideo'})
break;
case '.mpeg':
res.writeHead(200, {'Content-type':'video/mpeg'})
break;
default:
res.writeHead(200)
break;
}
res.end(data);
}
});
})
app.post('/', (req, res) => {
session_update(req, res)
cookie_update(req, res)
var pages = ['post']
var data = "";
req.on('data', chunk => {
data += chunk
})
req.on('end', () => {
var mpage = ""
var arr = pages.forEach(el => {
mpage += " |"+el+"| "
})
var filter = data.match('/'+mpage+'/')
if (filter) {
var getpage = pages.indexOf(filter[0])
}
if (getpage >= 0) {
require('./lib/pages/'+filter+'.js')(res, data.match(/{.+}/g)[0])
}
})
})
app.post('/login', url_encoder ,(req, res) => {
require('./lib/pages/session').connect(req, res, req.body)
})
app.post('/logout', (req, res) => {
req.session.destroy()
res.cookie('user-param', '', {maxAge:0})
res.writeHead(200, {
'Content-type':'text/plain'
})
res.end()
})
serv.listen(443);