sql >> Base de Datos >  >> NoSQL >> Redis

Uso de Redis con Node.js y Socket.IO

En este artículo, le mostraremos cómo crear una aplicación de chat en tiempo real utilizando las siguientes tecnologías:

  • Redis
  • Node.js + Express.js
  • Socket.IO
  • Heroku

Redis

Redis es un almacén de estructura de datos en memoria de código abierto (licencia BSD), que se utiliza como base de datos, caché y agente de mensajes. Admite estructuras de datos como cadenas, hashes, listas, conjuntos, conjuntos ordenados con consultas de rango, mapas de bits, hiperloglogs e índices geoespaciales con consultas de radio.

En este tutorial de aplicación, nos conectaremos a uno de los clústeres mediante el alojamiento de ScaleGrid para Redis™*.

Nodo.js

Una plataforma basada en el tiempo de ejecución de JavaScript de Chrome para crear fácilmente aplicaciones de red rápidas y escalables. Node.js utiliza un modelo de E/S sin bloqueo y controlado por eventos que lo hace liviano y eficiente, por lo tanto, perfecto para aplicaciones en tiempo real con uso intensivo de datos que se ejecutan en dispositivos distribuidos.

Express.js

Un marco Node.js. Node.js es una plataforma que permite usar JavaScript fuera de los navegadores web para crear aplicaciones web y de red. Esto significa que puede crear el servidor y el código del lado del servidor para una aplicación como la mayoría de los otros lenguajes web, pero usando JavaScript.

Socket.IO

Una biblioteca de JavaScript para aplicaciones web en tiempo real que permite la comunicación bidireccional en tiempo real entre clientes y servidores web. Socket.IO tiene dos componentes:una biblioteca del lado del cliente que se ejecuta en el navegador y una biblioteca del lado del servidor para Node.js. Ambos componentes tienen API casi idénticas.

Héroe

Una plataforma en la nube que permite a las empresas crear, entregar, monitorear y escalar aplicaciones. La plataforma Heroku es la forma más rápida de pasar de la idea a la URL, evitando todos esos dolores de cabeza de infraestructura.

Este artículo asume que ya tiene Redis, Node.js y Heroku Toolbelt instalados en su máquina.

Configuración

Cree una carpeta y asígnele un nombre. Puede crearlo en cualquier parte de su máquina ya que Node.js no necesita un servidor especial como Apache/nginx.

Paso 1

Inicialice un archivo package.json ejecutando npm init .

{
  "name": "node-socket-redis-chat-scalegrid",
  "version": "0.0.1",
  "description": "A realtime chat application using Redis, Node.js and Socket.IO",
  "dependencies": {
    "body-parser": "^1.15.2",
    "express": "^4.10.2",
    "redis": "^2.6.3",
    "socket.io": "^1.7.1"
  },
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "engines": {
    "node": "4.1.1"
  }
}

Paso 2

Instalar las siguientes dependencias:

  • expressjs
  • socketio
  • redis

…y algunos otros métodos de utilidad:

  • analizador de cuerpo

ejecutando el siguiente comando:

npm install --save expressjs socket.io redis body-parser

Paso 3

Cree una carpeta pública para almacenar nuestros archivos CSS y JS:

/public/css/main.css
/public/js/main.js

Paso 4:

Cree una carpeta de vistas para almacenar nuestro archivo HTML principal:

/views/index.html

Paso 5:

Crear un creds.json archivo que contendrá las credenciales para conectarse a nuestro Redis™ Cluster. Debe seguir el siguiente formato:

{
    "user": "",
    "password": "",
    "host": "",
    "port": 6379
}

Paso 6:

Cree el index.js archivo que alojará nuestro código Node.js y servirá como punto de partida para Heroku.

Paso 7:

Agregue un .gitignore archivo para que la carpeta node_modules no se registre en Heroku:

node_modules

Después de completar el paso 7, deberías tener la siguiente estructura:

.
├── creds.json
├── index.js
├── package.json
├── public
│   ├── css
│   │   └── main.css
│   └── js
│       └── main.js
└── views
    └── index.html

Paso 8

Ahora que todo está configurado, podemos comenzar a escribir nuestro código de back-end. En primer lugar, debemos incorporar todos nuestros módulos. Por lo tanto, abra el archivo index.js y pegue lo siguiente:

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

var fs = require('fs');
var creds = '';

var redis = require('redis');
var client = '';
var port = process.env.PORT || 8080;

// Express Middleware for serving static
// files and parsing the request body
app.use(express.static('public'));
app.use(bodyParser.urlencoded({
    extended: true
}));

// Start the Server
http.listen(port, function() {
    console.log('Server Started. Listening on *:' + port);
});

// Store people in chatroom
var chatters = [];

// Store messages in chatroom
var chat_messages = [];

Antes de que podamos comenzar a escribir cualquier código, necesitamos un clúster que ejecute Redis. Afortunadamente, ScaleGrid for Redis™ proporciona una solución de alojamiento de alto rendimiento, con un solo clic y completamente administrada.

Si aún no es miembro, puede registrarse para una prueba gratuita de 30 días aquí.

De lo contrario, inicie sesión en su tablero y cree un nuevo clúster de Redis™ en la sección de Redis™:

Una vez que se complete la creación del clúster, tome nota de la información anterior y agréguela a los campos relevantes de creds.json archivo.

Ahora que tenemos configuradas nuestras credenciales, estamos listos para crear nuestro cliente Redis en Node que se conectará a nuestro clúster y comenzará a almacenar pares clave-valor.

Agregue el siguiente código al archivo index.js:

// Read credentials from JSON
fs.readFile('creds.json', 'utf-8', function(err, data) {
    if(err) throw err;
    creds = JSON.parse(data);
    client = redis.createClient('redis://' + creds.user + ':' + creds.password + '@' + creds.host + ':' + creds.port);

    // Redis Client Ready
    client.once('ready', function() {

        // Flush Redis DB
        // client.flushdb();

        // Initialize Chatters
        client.get('chat_users', function(err, reply) {
            if (reply) {
                chatters = JSON.parse(reply);
            }
        });

        // Initialize Messages
        client.get('chat_app_messages', function(err, reply) {
            if (reply) {
                chat_messages = JSON.parse(reply);
            }
        });
    });
});

El código anterior hace dos cosas:

  1. Lee las credenciales de creds.json y crea un cliente de Redis que se utiliza para realizar operaciones de clave-valor
  2. Una vez que el cliente está listo, completamos los chatters y los chat_messages por lo que cualquier miembro nuevo que se una podrá ver el historial de chat.

Ahora vamos a escribir un par de API para manejar la aplicación de chat. Necesitamos las siguientes API:

  • Unirse a la sala [POST]
  • Salir de la habitación [POST]
  • Enviar mensaje [POST]
  • Obtener mensajes [GET]
  • Obtener miembros [GET]

Empecemos con la API Join Room. Esto se llama cuando cualquier usuario nuevo inicia la aplicación por primera vez e intenta unirse a la sala de chat:

// API - Join Chat
app.post('/join', function(req, res) {
    var username = req.body.username;
    if (chatters.indexOf(username) === -1) {
        chatters.push(username);
        client.set('chat_users', JSON.stringify(chatters));
        res.send({
            'chatters': chatters,
            'status': 'OK'
        });
    } else {
        res.send({
            'status': 'FAILED'
        });
    }
});

Aquí tenemos la API para salir de la sala de chat:

// API - Leave Chat
app.post('/leave', function(req, res) {
    var username = req.body.username;
    chatters.splice(chatters.indexOf(username), 1);
    client.set('chat_users', JSON.stringify(chatters));
    res.send({
        'status': 'OK'
    });
});

Enviando y almacenando el mensaje:

// API - Send + Store Message
app.post('/send_message', function(req, res) {
    var username = req.body.username;
    var message = req.body.message;
    chat_messages.push({
        'sender': username,
        'message': message
    });
    client.set('chat_app_messages', JSON.stringify(chat_messages));
    res.send({
        'status': 'OK'
    });
});

Obtener todos los mensajes en la sala:

// API - Get Messages
app.get('/get_messages', function(req, res) {
    res.send(chat_messages);
});

Obtener todos los miembros:

// API - Get Chatters
app.get('/get_chatters', function(req, res) {
    res.send(chatters);
});

Una vez que tengamos todas las API configuradas, debemos escribir el código Socket.IO para emitir eventos cuando se actualicen ciertas propiedades como las siguientes:

  • Recuento de habitaciones
  • Mensajes
// Socket Connection
// UI Stuff
io.on('connection', function(socket) {

    // Fire 'send' event for updating Message list in UI
    socket.on('message', function(data) {
        io.emit('send', data);
    });

    // Fire 'count_chatters' for updating Chatter Count in UI
    socket.on('update_chatter_count', function(data) {
        io.emit('count_chatters', data);
    });

});

Estos eventos luego son recogidos en el front-end por la biblioteca Socket.IO, que a su vez actualiza la interfaz de usuario.

Paso 9

Ahora, necesitamos crear nuestra interfaz de usuario que permita a los usuarios iniciar sesión y chatear.

Abre el index.html archivo y agregue el siguiente código:

<!doctype html>
<html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Node.js + Socket.io + Redis Chat | ScaleGrid</title>
      <link rel="stylesheet" href="css/main.css">
    </head>
    <body>
        <div class="container">
            <h1>Node.js + Socket.io + Redis Chat | ScaleGrid</h1>
            <div class="join-chat">
                <label for="username">Username:</label>
                <input type="text" id="username" name="username" />
                <input type="button" id="join-chat" value="Join Chat" />
            </div><br />
            <div class="chat-info"></div><br />
            <div class="chat">
                <div class="messages"></div>
                <textarea name="message" id="message" cols="90" rows="5" placeholder="Enter your message..."></textarea><br /><br />
                <input type="button" id="send-message" data-username="" value="Send Message">&nbsp;
                <input type="button" id="leave-chat" data-username="" value="Leave Chat">
            </div>
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.6.0/socket.io.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
        <script src="js/main.js"></script>
    </body>
</html>

Paso 10

Para que nuestro HTML funcione, necesitamos agregar algunos eventos AJAX de JavaScript que manejarán las diversas operaciones, como unirse a una sala, salir, enviar un mensaje, etc.

El siguiente código obtiene la cantidad de personas que chatean para que podamos actualizar la interfaz de usuario sobre la cantidad total de personas en la sala:

$.get('/get_chatters', function(response) {
    $('.chat-info').text("There are currently " + response.length + " people in the chat room");
    chatter_count = response.length; //update chatter count
});

Este código permite a los usuarios unirse a la sala de chat. Recuerde, los nombres de usuario son únicos y no se pueden duplicar:

$('#join-chat').click(function() {
    var username = $.trim($('#username').val());
    $.ajax({
        url: '/join',
        type: 'POST',
        data: {
            username: username
        },
        success: function(response) {
            if (response.status == 'OK') { //username doesn't already exists
                socket.emit('update_chatter_count', {
                    'action': 'increase'
                });
                $('.chat').show();
                $('#leave-chat').data('username', username);
                $('#send-message').data('username', username);
                $.get('/get_messages', function(response) {
                    if (response.length > 0) {
                        var message_count = response.length;
                        var html = '';
                        for (var x = 0; x < message_count; x++) {
                            html += "<div class='msg'><div class='user'>" + response[x]['sender'] + "</div><div class='txt'>" + response[x]['message'] + "</div></div>";
                        }
                        $('.messages').html(html);
                    }
                });
                $('.join-chat').hide(); //hide the container for joining the chat room.
            } else if (response.status == 'FAILED') { //username already exists
                alert("Sorry but the username already exists, please choose another one");
                $('#username').val('').focus();
            }
        }
    });
});

Este es el código para permitir que los usuarios abandonen la sala de chat:

$('#leave-chat').click(function() {
    var username = $(this).data('username');
    $.ajax({
        url: '/leave',
        type: 'POST',
        dataType: 'json',
        data: {
            username: username
        },
        success: function(response) {
            if (response.status == 'OK') {
                socket.emit('message', {
                    'username': username,
                    'message': username + " has left the chat room.."
                });
                socket.emit('update_chatter_count', {
                    'action': 'decrease'
                });
                $('.chat').hide();
                $('.join-chat').show();
                $('#username').val('');
                alert('You have successfully left the chat room');
            }
        }
    });
});

Este es el código que se ejecuta cada vez que alguien envía un mensaje:

$('#send-message').click(function() {
    var username = $(this).data('username');
    var message = $.trim($('#message').val());
    $.ajax({
        url: '/send_message',
        type: 'POST',
        dataType: 'json',
        data: {
            'username': username,
            'message': message
        },
        success: function(response) {
            if (response.status == 'OK') {
                socket.emit('message', {
                    'username': username,
                    'message': message
                });
                $('#message').val('');
            }
        }
    });
});

El siguiente es el código de Socket.IO que escucha los eventos del backend y actualiza la interfaz de usuario. Por ejemplo, agregar nuevos mensajes al área de mensajes, actualizar el conteo de conversaciones, etc.:

socket.on('send', function(data) {
    var username = data.username;
    var message = data.message;
    var html = "<div class='msg'><div class='user'>" + username + "</div><div class='txt'>" + message + "</div></div>";
    $('.messages').append(html);
});
socket.on('count_chatters', function(data) {
    if (data.action == 'increase') {
        chatter_count++;
    } else {
        chatter_count--;
    }
    $('.chat-info').text("There are currently " + chatter_count + " people in the chat room");
});

¡Y listo! Inicie el servidor usando npm start y abra múltiples ventanas del navegador para simular múltiples usuarios.

Una demostración de la aplicación está disponible aquí: https://node-socket-redis-chat.herokuapp.com/

Para implementar esta aplicación en Heroku, consulte sus documentos: https://devcenter.heroku.com/categories/deployment

El código fuente completo también está disponible en GitHub para que lo bifurques y trabajes en:https://github.com/Scalegrid/code-samples/tree/sg-redis- node-socket-chat/redis-node-socket-chat

Como siempre, si construyes algo asombroso, envíanos un tweet al respecto @scalegridio.

Si necesita ayuda con la administración y el alojamiento de Redis™, permítanos simplificarle las cosas con nuestros servicios profesionales.