Redis
 sql >> Baza danych >  >> NoSQL >> Redis

Używanie Redis z Node.js i Socket.IO

W tym artykule pokażemy, jak zbudować aplikację do czatu w czasie rzeczywistym przy użyciu następujących technologii:

  • Ponownie
  • Node.js + Express.js
  • Gniazdo.IO
  • Heroku

Ponownie

Redis to magazyn struktury danych typu open source (na licencji BSD), używany jako baza danych, pamięć podręczna i broker komunikatów. Obsługuje struktury danych, takie jak ciągi, skróty, listy, zestawy, posortowane zestawy z zapytaniami o zakres, mapy bitowe, hiperloglogi i indeksy geoprzestrzenne z zapytaniami o promień.

W tym samouczku dotyczącym aplikacji będziemy łączyć się z jednym z klastrów za pomocą hostingu ScaleGrid dla Redis™*.

Node.js

Platforma oparta na środowisku wykonawczym JavaScript Chrome do łatwego tworzenia szybkich i skalowalnych aplikacji sieciowych. Node.js wykorzystuje sterowany zdarzeniami, nieblokujący model we/wy, który czyni go lekkim i wydajnym, dzięki czemu idealnie nadaje się do aplikacji czasu rzeczywistego intensywnie korzystających z danych, które działają na urządzeniach rozproszonych.

Express.js

Struktura Node.js. Node.js to platforma, która pozwala na używanie JavaScript poza przeglądarkami internetowymi do tworzenia aplikacji internetowych i sieciowych. Oznacza to, że możesz utworzyć serwer i kod po stronie serwera dla aplikacji, podobnie jak większość innych języków internetowych, ale przy użyciu JavaScript.

Gniazdo.IO

Biblioteka JavaScript dla aplikacji internetowych działających w czasie rzeczywistym, która umożliwia dwukierunkową komunikację w czasie rzeczywistym między klientami sieciowymi a serwerami. Socket.IO ma dwa komponenty:bibliotekę po stronie klienta, która działa w przeglądarce oraz bibliotekę po stronie serwera dla Node.js. Oba komponenty mają prawie identyczne interfejsy API.

Heroku

Platforma w chmurze, która umożliwia firmom tworzenie, dostarczanie, monitorowanie i skalowanie aplikacji. Platforma Heroku to najszybszy sposób na przejście od pomysłu do adresu URL, z pominięciem wszystkich problemów związanych z infrastrukturą.

W tym artykule założono, że masz już zainstalowane Redis, Node.js i Heroku Toolbelt na swoim komputerze.

Konfiguracja

Utwórz folder i nadaj mu nazwę. Możesz go utworzyć w dowolnym miejscu na swoim komputerze, ponieważ Node.js nie wymaga specjalnego serwera, takiego jak Apache/nginx.

Krok 1

Zainicjuj plik package.json, uruchamiając 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"
  }
}

Krok 2

Zainstaluj następujące zależności:

  • ekspresowe
  • gniazdo
  • ponowne

…i kilka innych metod użytkowych:

  • parser ciała

przez uruchomienie następującego polecenia:

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

Krok 3

Utwórz folder publiczny do przechowywania naszych plików CSS i JS:

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

Krok 4:

Utwórz folder widoków do przechowywania naszego głównego pliku HTML:

/views/index.html

Krok 5:

Utwórz plik creds.json plik, który będzie zawierał dane uwierzytelniające do połączenia z naszym klastrem Redis™. Powinien mieć następujący format:

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

Krok 6:

Utwórz index.js plik, który będzie hostował nasz kod Node.js i będzie służył jako punkt wyjścia dla Heroku.

Krok 7:

Dodaj .gitignore więc folder node_modules nie jest zaewidencjonowany w Heroku:

node_modules

Po wykonaniu siódmego kroku powinieneś mieć następującą strukturę:

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

Krok 8

Teraz, gdy wszystko jest już skonfigurowane, możemy zacząć pisać nasz kod backendu. Przede wszystkim musimy wprowadzić wszystkie nasze moduły. Otwórz więc plik index.js i wklej:

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 = [];

Zanim zaczniemy pisać jakikolwiek kod, potrzebujemy klastra z systemem Redis. Na szczęście ScaleGrid dla Redis™ zapewnia wysoką wydajność, jedno kliknięcie i w pełni zarządzane rozwiązanie hostingowe.

Jeśli nie jesteś jeszcze członkiem, możesz zarejestrować się na bezpłatny 30-dniowy okres próbny tutaj.

W przeciwnym razie zaloguj się do pulpitu nawigacyjnego i utwórz nowy klaster Redis™ w sekcji Redis™:

Po zakończeniu tworzenia klastra zanotuj powyższe informacje i dodaj je do odpowiednich pól creds.json plik.

Teraz, gdy mamy już skonfigurowane dane uwierzytelniające, jesteśmy gotowi do utworzenia naszego klienta Redis w węźle, który połączy się z naszym klastrem i zacznie przechowywać pary klucz-wartość.

Dodaj następujący kod do pliku 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);
            }
        });
    });
});

Powyższy kod robi dwie rzeczy:

  1. Odczytuje poświadczenia z creds.json i tworzy klienta Redis, który jest używany do wykonywania operacji klucz-wartość
  2. Gdy klient jest gotowy, wypełniamy chatters i chat_messages więc wszyscy nowi członkowie, którzy dołączą, będą mogli zobaczyć historię czatu.

Teraz napiszemy kilka interfejsów API do obsługi aplikacji czatu. Potrzebujemy następujących interfejsów API:

  • Dołącz do pokoju [POST]
  • Opuść pokój [POST]
  • Wyślij wiadomość [POST]
  • Pobierz wiadomości [GET]
  • Pozyskaj członków [GET]

Zacznijmy od interfejsu Join Room API. Ta funkcja jest wywoływana, gdy nowy użytkownik po raz pierwszy uruchamia aplikację i próbuje dołączyć do pokoju rozmów:

// 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'
        });
    }
});

Oto mamy API do opuszczenia pokoju rozmów:

// 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'
    });
});

Wysyłanie i przechowywanie wiadomości:

// 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'
    });
});

Pobierz wszystkie wiadomości w pokoju:

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

Pobierz wszystkich członków:

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

Po skonfigurowaniu wszystkich interfejsów API, musimy napisać kod Socket.IO, aby emitować zdarzenia, gdy określone właściwości, takie jak następujące, zostaną zaktualizowane:

  • Liczba pokoi
  • Wiadomości
// 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);
    });

});

Te zdarzenia są następnie pobierane na interfejsie użytkownika przez bibliotekę Socket.IO, która z kolei aktualizuje interfejs użytkownika.

Krok 9

Teraz musimy zbudować nasz interfejs użytkownika, który umożliwi użytkownikom logowanie się i czatowanie.

Otwórz index.html plik i dodaj następujący kod:

<!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>

Krok 10

Aby nasz HTML działał, musimy dodać kilka zdarzeń JavaScript AJAX, które obsłużą różne operacje, takie jak dołączenie do pokoju, wyjście, wysłanie wiadomości itp.

Poniższy kod pobiera liczbę rozmówców, dzięki czemu możemy zaktualizować interfejs użytkownika o całkowitą liczbę osób w pokoju:

$.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
});

Ten kod umożliwia użytkownikom dołączenie do pokoju rozmów. Pamiętaj, że nazwy użytkowników są niepowtarzalne i nie można ich duplikować:

$('#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();
            }
        }
    });
});

Oto kod umożliwiający użytkownikom opuszczenie pokoju rozmów:

$('#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');
            }
        }
    });
});

Oto kod, który uruchamia się za każdym razem, gdy ktoś wysyła wiadomość:

$('#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('');
            }
        }
    });
});

Poniżej znajduje się kod Socket.IO, który nasłuchuje zdarzeń z zaplecza i aktualizuje interfejs użytkownika. Na przykład dodawanie nowych wiadomości do obszaru wiadomości, aktualizowanie licznika rozmów itp.:

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");
});

I gotowe! Uruchom serwer za pomocą npm start i otwórz wiele okien przeglądarki, aby zasymulować wielu użytkowników.

Demo aplikacji jest dostępne tutaj: https://node-socket-redis-chat.herokuapp.com/

Aby wdrożyć tę aplikację w Heroku, zapoznaj się z ich dokumentacją:https://devcenter.heroku.com/categories/deployment

Cały kod źródłowy jest również dostępny na GitHub, na którym możesz się rozwidlić i popracować:https://github.com/Scalegrid/code-samples/tree/sg-redis- node-socket-chat/redis-node-socket-chat

Jak zawsze, jeśli zbudujesz coś niesamowitego, napisz do nas o tym na Twitterze @scalegridio.

Jeśli potrzebujesz pomocy w zarządzaniu i hostingu dla Redis™, pozwól nam uprościć sprawy dzięki naszym profesjonalnym usługom.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Najczęstsze przypadki użycia Redis według typów podstawowych struktur danych

  2. skonfiguruj autoryzację redis na sidekiq

  3. Co robi parametr bind w Redis?

  4. Różnica między logami Redis AOF i Tarantool WAL

  5. django:redis:CommandError:Nie ustawiłeś ASGI_APPLICATION, który jest potrzebny do uruchomienia serwera