Як користуватися redis PUBLISH / SUBSCRIBE з nodejs для сповіщення клієнтів про зміну значень даних?


99

Я пишу заявку на публікацію / підписку, керовану подією, з NodeJS та Redis. Мені потрібен приклад, як повідомляти веб-клієнтів, коли значення даних у Redis змінюються.

Відповіді:


123

OLD використовуйте лише посилання

Залежності

використовує express , socket.io , node_redis і не в останню чергу зразок коду від медіа-пожежі.

Встановити node.js + npm (як не root)

Спочатку слід (якщо ви цього ще не зробили) встановити node.js + npm за 30 секунд (правильний шлях, оскільки НЕ слід запускати npm як root ):

echo 'export PATH=$HOME/local/bin:$PATH' >> ~/.bashrc
. ~/.bashrc
mkdir ~/local
mkdir ~/node-latest-install
cd ~/node-latest-install
curl http://nodejs.org/dist/node-latest.tar.gz | tar xz --strip-components=1
./configure --prefix=~/local
make install # ok, fine, this step probably takes more than 30 seconds...
curl http://npmjs.org/install.sh | sh

Встановити залежності

Після встановлення вузла + npm слід встановити залежності, видавши:

npm install express
npm install socket.io
npm install hiredis redis # hiredis to use c binding for redis => FAST :)

Завантажити зразок

Ви можете завантажити повний зразок з mediafire .

Розпакуйте пакет

unzip pbsb.zip # can also do via graphical interface if you prefer.

Що всередині zip

./app.js

const PORT = 3000;
const HOST = 'localhost';

var express = require('express');

var app = module.exports = express.createServer();

app.use(express.staticProvider(__dirname + '/public'));

const redis = require('redis');
const client = redis.createClient();

const io = require('socket.io');

if (!module.parent) {
    app.listen(PORT, HOST);
    console.log("Express server listening on port %d", app.address().port)

    const socket  = io.listen(app);

    socket.on('connection', function(client) {
        const subscribe = redis.createClient();
        subscribe.subscribe('pubsub'); //    listen to messages from channel pubsub

        subscribe.on("message", function(channel, message) {
            client.send(message);
        });

        client.on('message', function(msg) {
        });

        client.on('disconnect', function() {
            subscribe.quit();
        });
    });
}

./public/index.html

<html>
<head>
    <title>PubSub</title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="/javascripts/jquery-1.4.3.min.js"></script>
</head>
<body>
    <div id="content"></div>
    <script>    
        $(document).ready(function() {
            var socket = new io.Socket('localhost', {port: 3000, rememberTransport: false/*, transports: ['xhr-polling']*/});
            var content = $('#content');

            socket.on('connect', function() {
            });

            socket.on('message', function(message){
                content.prepend(message + '<br />');
            }) ;

            socket.on('disconnect', function() {
                console.log('disconnected');
                content.html("<b>Disconnected!</b>");
            });

            socket.connect();
        });
    </script>
</body>
</html>

Запуск сервера

cd pbsb    
node app.js

Запустити браузер

Найкраще, якщо ви запустите Google Chrome (через підтримку веб-сокетів, але це не обов'язково). Відвідайте, http://localhost:3000щоб побачити зразок (на початку ви бачите не що інше, PubSubяк заголовок).

Але на publishканалі pubsubви повинні побачити повідомлення. Нижче ми публікуємо "Hello world!"в браузері.

Від ./redis-cli

publish pubsub "Hello world!"

навіщо вам потрібно const client = redis.createClient()в корені app.js?
Акаша

вам зовсім не потрібно використовувати const. var може бути використаний також, і, можливо, я мав би це зробити, тому що const доступний лише в нових механізмах javascript. Крім того, ця лінія гарантує, що ми підключені до сервера redis, який ми використовуємо в цьому прикладі.
Альфред

5
Зразок дуже старий, тому не в курсі останніх модулів socket.io/express і, можливо, навіть node.js. Я б спробував оновити код. Існує ще одна величезна проблема з цим кодом, що він відкриває чергове з'єднання redis для кожного підключеного користувача. Це повинно бути замість цього. Я повинен працювати спочатку, але після цього намагаюся оновити код.
Альфред

1
Дуже добре. Я все ще думаю, що є місце для деяких вдосконалень, які, коли встигну, викладу в Інтернет. Але зараз я дуже багато працюю: $.
Альфред

1
Я думаю, що Subscri.on має бути поза блоком socket.on ('connection'), щоб уникнути декількох підписок /
zubinmehta

26

ось спрощений приклад без такої кількості залежностей. Вам все одно потрібноnpm install hiredis redis

Вузол JavaScript:

var redis = require("redis"),
    client = redis.createClient();

client.subscribe("pubsub");
client.on("message", function(channel, message){
  console.log(channel + ": " + message);
});

... помістіть це у файл pubsub.js і запустіть node pubsub.js

в Redis-cli:

redis> publish pubsub "Hello Wonky!"
(integer) 1

який повинен відображатися: pubsub: Hello Wonky!у термінальному запущеному вузлі! Вітаю!

Додатково 23.04.2013: Я також хочу зауважити, що коли клієнт підписується на паб / підканал, він переходить у режим передплатників і обмежується командами передплатників. Вам просто потрібно буде створити додаткові екземпляри клієнтів Redis. client1 = redis.createClient(), client2 = redis.createClient()тому один може перебувати в режимі передплатників, а інший може видавати звичайні команди БД.


Якщо ми додаємо дані до редакції, чи потрібно запустити публікувати pubsub, щоб отримати повідомлення про вставку?
IshaS

1
@IshaS якщо це потрібно зробити, так. Ви також повинні дивитися на угоди , якщо вам потрібно виконати кілька команд атомарному: redis.io/commands/exec
NAK

@nak Це працювало як шарм в одному GO :) Деякі користувачі можуть встановити "подвійну чергу", якщо її ще не встановлено.
Алекс

1
Варто також зазначити, що якщо ви хочете використовувати підстановку, наприклад, підпишіться, щоб pubsub/*просто додати pв приклад: замінити subscibeна psubscribeі messageна pmessage.
Ліоша Бакушина

7

Повний приклад Redis Pub / Sub ( Чат у режимі реального часу за допомогою Hapi.js & Socket.io)

Ми намагалися зрозуміти Redis Publish / Subscribe (" Pub / Sub "), і всі існуючі приклади були або застарілими, занадто простими, або не мали тестів. Отже, ми написали Повний чат у режимі реального часу, використовуючи Hapi.js + Socket.io + Redis Pub / Sub Приклад із тестами в кінці !

https://github.com/dwyl/hapi-socketio- redis-chat-example

Компонент Pub / Sub - це лише кілька рядків коду node.js: https://github.com/dwyl/hapi-socketio-redis-chat-example/blob/master/lib/chat.js#L33-L40

Замість того, щоб вставляти його тут ( без будь-якого контексту ), ми рекомендуємо вам оформити замовлення / спробувати приклад .

Ми побудували його з допомогою Hapi.js , але chat.jsфайл від'єднано від Хапи і може легко використовуватися з базовим node.js HTTP - сервером або висловити ( і т.д.)


у вас є такий приклад з експресом?
Gixty

@Gixty ми написали приклад, використовуючи Hapi.js, тому що всі інші приклади там використовують Express.js ..., як згадується у публікації, його тривіальне значення для того, щоб перенести його в будь-яку іншу рамку Node.js (просто передайте в експрес-програму / слухач коду init chat.js), і він працює точно так само. ps: якщо ви новачок у Hapi.js дивіться: github.com/nelsonic/learn-hapi
nelsonic

4

Обробіть помилки redis, щоб зупинити вихід вузлів. Це можна зробити, написавши;

subcribe.on("error", function(){
  //Deal with error
})

Я думаю, ви отримуєте виняток, оскільки ви використовуєте того самого клієнта, який підписаний для публікації повідомлень. Створіть окремий клієнт для публікації повідомлень, який може вирішити вашу проблему.



2

Якщо ви хочете, щоб це працювало з socket.io 0.7 І зовнішнім веб-сервером, вам потрібно змінити (окрім staticProvider -> статична проблема):

а) введіть доменне ім’я замість localhost (тобто var socket = io.connect ('http://my.domain.com:3000');) у index.html

b) зміни HOST у app.js (тобто const HOST = 'my.domain.com';)

в) і додайте сокети в рядок 37 програми app.js (тобто 'socket.sockets.on (' з'єднання ', функція (клієнт) {…')



0

згідно з рішенням @alex . якщо у вас є така помилка, як зазначено у @tyler :

node.js:134
        throw e; // process.nextTick error, or 'error'

event on first tick ^ Error: Redis connection to 127.0.0.1:6379 failed - ECONNREFUSED, Connection refused at Socket.

тоді вам потрібно спочатку встановити Redis . заціни:

http://redis.io/download

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.