Router.js
Материал из support.qbpro.ru
Версия от 15:38, 4 августа 2013; imported>Supportadmin (Новая страница: « <nowiki>////////////////////////// ////////router.js///////// ////////////////////////// ///////А.В. Климов//////// ////////////////////////// ////////01…»)
////////////////////////// ////////router.js///////// ////////////////////////// ///////А.В. Климов//////// ////////////////////////// ////////01.11.2012//////// //Используются модули fifo.js, net, socket.io ////////////////////////// //Предназначен для перенаправления входящего через WebSocket (далее ws) потока //в поток с использованием NetSocket (далее ns) для передачи заданий на исполнение. //Наличие исполнителей (их адреса локальные (127.х.х.х) или в перспективе сетевые) //конфигурируется через параметр (массив) workers=[]. //Выбор маршрута определяется исходя из текущей (моментальной) нагрузки workerов. //Имеет отдельный управляющий канал ns для связи с ядром ////////////////////////// //Принцип работы: //При поступлении сообщения от клиента по протоколу ws генерируется стандартное //событие 'data' в функции ws.on(). По этому событию из буфера сокета сообщение //помещается в очередь ws_fifo_ns. Функция ns каждый цикл EventLoop проверяет //наличие заданий в очереди (длину массива ws_fifo_ns) и в случае ненулевого //значения, первое сообщение отправляется в ns конкретному исполнителю. Выбор //исполнителя осуществляется по критерию нагрузки {надо сделать расчет на //основе средневзвешенного коэффициента нагрузки, когда каждое задание имеет //вес - а)число определяющее степеть предполагаемой (временной) загрузки процесса EventLoop //по времени исполнения [математическая, чтение/запись в файл, чтение/запись БД] //б) собирать статистику времени вылонения, используемой памяти и на её основе выставлять вес задания, //что позволит избежать неправильного веса при увеличении данных в запросе к БД //(т.н. автокорретировка)}. http://th-algoritmov.narod.ru/4.htm http://th-algoritmov.narod.ru/5.htm //Книга Идеальный код. http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BA%D0%BE%D0%BD_%D0%90%D0%BC%D0%B4%D0%B0%D0%BB%D0%B0 // ////////////////////////// //Управляющий ns поток //ns используется для мгновенного обмена информацией с ядром системы. Ядро может //собирать статистику и устанавливать конфигурационные пераметры: //-добавлять/убирать worker путем var fifo= require("fifo"), //Модуль, организующий очередь FIFO websocket = require('socket.io'), //Модуль, организующий WebSocket netsocket = require('net'), //Модуль, организующий NetSocket json_rpc= require('json_rpc'); //Модуль, организующий анализ и синтез формата json-rpc var ws_fifo = new fifo(), //очередь WebSocket->fifo для входящих (от клиента) сообщений перед маршрутизацией fifo_ws = new fifo(), //очередь для исходящих (к клиенту) сообщений fifo->WebSocket fifo_ns = new fifo(), //очередь fifo->NetSocket для исходящих сообщений после маршрутизации ns_fifo = new fifo(), //очередь для входящих сообщений NetSocket->fifo->WebSocket ws = new websocket(), //создаем новый экземпляр WebSocket ns = new netsocket(), //создаем новый экземпляр NetSocket ns_direct = new netsocket(); //создаем новый экземпляр NetSocket (управляющий канал) //WebSocket ws.listen(8080); // Cтавим на прослушивание 8080-порта ws.set('log level', 1); // Отключаем вывод полного лога - пригодится в production'е ws.sockets.on('connection', function (socket) { // Навешиваем обработчик на подключение нового клиента // Т.к. чат простой - в качестве ников пока используем первые 5 символов от ID сокета //var ID = (socket.id).toString().substr(0, 5); var ID = (socket.id).toString(); //В качестве ников пока используем ID сокета var time = (new Date).toLocaleTimeString(); socket.json.send({'event': 'connected', 'name': ID, 'time': time});// Посылаем клиенту сообщение о том, что он успешно подключился и его имя socket.broadcast.json.send({'event': 'userJoined', 'name': ID, 'time': time}); // Посылаем всем остальным пользователям, что подключился новый клиент и его имя socket.on('message', function (msg) { // Навешиваем обработчик на входящее сообщение var time = (new Date).toLocaleTimeString(); socket.json.send({'event': 'messageSent', 'name': ID, 'text': msg, 'time': time}); // Уведомляем клиента, что его сообщение успешно дошло до сервера //socket.broadcast.json.send({'event': 'messageReceived', // 'name': ID, // 'text': msg, // 'time': time}) // Отсылаем сообщение остальным участникам чата ///////////////////////// //Здесь обработать авторизацию, занести в БД сессию //Если ошибка уведомить клиента (вернуть error в fifo_ws в формате JSON-RPC) ///////////////////////// ///////////////////////// //Здесь проверить валидность JSON-RPC //Если ошибка уведомить клиента (вернуть error в fifo_ws в формате JSON-RPC) ///////////////////////// ///////////////////////// //Проверить наличие и соответствие команды на выполнение //Если ошибка уведомить клиента (вернуть error в fifo_ws в формате JSON-RPC) ///////////////////////// ///////////////////////// //Здесь записать id задания(из JSON-RPC), id сокета, id клиента, id функции(для статистики), время начала в буфер. //Из номера этой строки, id функции, параметры функции, сформировать в формате JSON-RPC задание для woker ///////////////////////// ///////////////////////// //Здесь предать JSON-RPC запрос в fifo_ns ///////////////////////// }); socket.on('disconnect', function() { // При отключении клиента - уведомляем остальных var time = (new Date).toLocaleTimeString(); io.sockets.json.send({'event': 'userSplit', 'name': ID, 'time': time}); }); });