Làm thế nào để sử dụng redis PUBLISH / SUBSCRIBE với nodejs để thông báo cho khách hàng khi giá trị dữ liệu thay đổi?


99

Tôi đang viết một ứng dụng đăng ký / xuất bản theo hướng sự kiện với NodeJS và Redis. Tôi cần một ví dụ về cách thông báo cho khách hàng web khi giá trị dữ liệu trong Redis thay đổi.

Câu trả lời:


123

CŨ chỉ sử dụng tham chiếu

Sự phụ thuộc

sử dụng express , socket.io , node_redismã mẫu cuối cùng nhưng không kém phần quan trọng từ media fire.

Cài đặt node.js + npm (không phải root)

Trước tiên, bạn nên (nếu bạn chưa làm điều này) cài đặt node.js + npm trong 30 giây (đúng cách vì bạn KHÔNG nên chạy npm dưới dạng 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

Cài đặt phần phụ thuộc

Sau khi bạn cài đặt node + npm, bạn nên cài đặt các phụ thuộc bằng cách phát hành:

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

Tải xuống mẫu

Bạn có thể tải xuống mẫu hoàn chỉnh từ mediafire .

Giải nén gói

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

Có gì bên trong 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>

Khởi động máy chủ

cd pbsb    
node app.js

Khởi động trình duyệt

Tốt nhất nếu bạn khởi động google chrome (vì hỗ trợ websockets, nhưng không cần thiết). Truy cập http://localhost:3000để xem mẫu (ban đầu bạn không thấy gì ngoàiPubSub tiêu đề).

Nhưng trên publishkênh, pubsubbạn sẽ thấy một thông báo. Dưới đây chúng tôi xuất bản "Hello world!"lên trình duyệt.

Từ ./redis-cli

publish pubsub "Hello world!"

tại sao bạn cần const client = redis.createClient()trong thư mục gốc của app.js?
Akasha

bạn không cần phải sử dụng const. var cũng có thể được sử dụng và có lẽ tôi nên có thay thế vì const chỉ có sẵn trong các công cụ javascript mới hơn. Hơn nữa, dòng này đảm bảo chúng tôi được kết nối với máy chủ redis mà chúng tôi sử dụng trong ví dụ này.
Alfred

5
Mẫu này rất cũ nên không được cập nhật với các mô-đun socket.io/express mới nhất và thậm chí có thể là node.js. Tôi sẽ cố gắng cập nhật mã. Cũng có một vấn đề lớn khác với mã này là nó mở một kết nối redis khác cho mỗi người dùng được kết nối. Điều đó chỉ nên được thay thế. Tôi phải làm việc trước, nhưng sau đó tôi cố gắng cập nhật mã.
Alfred

1
Rất tốt. Tôi vẫn nghĩ rằng vẫn còn chỗ cho một số cải tiến mà khi có thời gian tôi sẽ đưa lên mạng. Nhưng hiện tại tôi đang thực sự làm việc chăm chỉ: $.
Alfred

1
Tôi nghĩ subscribe.on nên ngoài socket.on ( 'kết nối') khối để tránh nhiều lượt đăng ký /
zubinmehta

26

đây là một ví dụ đơn giản mà không có nhiều phụ thuộc. Bạn vẫn cầnnpm install hiredis redis

JavaScript nút:

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

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

... đặt nó vào tệp pubsub.js và chạy node pubsub.js

trong redis-cli:

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

sẽ hiển thị: pubsub: Hello Wonky!trong nút đang chạy của thiết bị đầu cuối! Chúc mừng!

Bổ sung 23/4/2013: Tôi cũng muốn lưu ý rằng khi khách hàng đăng ký kênh pub / sub, nó sẽ chuyển sang chế độ người đăng ký và bị giới hạn ở lệnh đăng ký. Bạn chỉ cần tạo thêm các phiên bản redis client. client1 = redis.createClient(), client2 = redis.createClient()vì vậy một người có thể ở chế độ thuê bao và người kia có thể đưa ra các lệnh DB thông thường.


Ở đây khi chúng tôi thêm dữ liệu vào redis, tôi có nên chạy Pubsub xuất bản để nhận thông báo chèn không?
IshaS

1
@IshaS nếu đó là điều bạn cần làm, vâng. Bạn cũng nên xem xét các giao dịch nếu bạn cần chạy nhiều lệnh nguyên tử: redis.io/commands/exec
nak

@nak Điều này hoạt động giống như sự quyến rũ trong một lần GO :) Một số người dùng có thể cần cài đặt 'hàng đợi kết thúc kép' nếu chưa được cài đặt.
Alex

1
Cũng cần đề cập rằng nếu bạn muốn sử dụng các ký tự đại diện, chẳng hạn, hãy đăng ký để pubsub/*chỉ thêm pvào ví dụ: thay thế subscibebằng psubscribemessagebằng pmessage.
Liosha Bakoushin

7

Hoàn thành ví dụ về Redis Pub / Sub ( Trò chuyện thời gian thực bằng Hapi.js & Socket.io)

Chúng tôi đang cố gắng hiểu Redis Publish / Subscribe (" Pub / Sub ") và tất cả các ví dụ hiện có đều đã lỗi thời, quá đơn giản hoặc không có thử nghiệm. Vì vậy, chúng tôi đã viết một cuộc trò chuyện hoàn chỉnh trong thời gian thực bằng Hapi.js + Socket.io + Redis Pub / Sub Ví dụ với các bài kiểm tra từ đầu đến cuối !

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

Thành phần Pub / Sub chỉ là một vài dòng mã node.js: https://github.com/dwyl/hapi-socketio-redis-chat-example/blob/master/lib/chat.js#L33-L40

Thay vì dán nó ở đây ( không có bất kỳ ngữ cảnh nào ), chúng tôi khuyến khích bạn kiểm tra / thử ví dụ .

Chúng tôi đã xây dựng nó bằng cách sử dụng Hapi.js nhưng chat.jstệp được loại bỏ khỏi Hapi và có thể dễ dàng được sử dụng với máy chủ http node.js cơ bản hoặc express (v.v.)


bạn có ví dụ này với express không?
Gixty

@Gixty, chúng tôi đã viết ví dụ bằng cách sử dụng Hapi.js bởi vì tất cả các ví dụ khác đều sử dụng Express.js ... như đã đề cập trong bài đăng, việc chuyển nó sang bất kỳ khung Node.js nào khác (chỉ cần chuyển vào ứng dụng express / nghe mã init chat.js) và nó hoạt động giống hệt nhau. ps: nếu bạn chưa quen với Hapi.js, hãy xem: github.com/nelsonic/learn-hapi
nelsonic

4

Xử lý lỗi redis để ngăn nodejs thoát. Bạn có thể làm điều này bằng cách viết;

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

Tôi nghĩ rằng bạn nhận được ngoại lệ vì bạn đang sử dụng cùng một ứng dụng được đăng ký để xuất bản tin nhắn. Tạo một khách hàng riêng để xuất bản tin nhắn và điều đó có thể giải quyết vấn đề của bạn.



2

Nếu bạn muốn điều này hoạt động với socket.io 0.7 một máy chủ web bên ngoài, bạn cần thay đổi (ngoài staticProvider -> sự cố tĩnh):

a) cung cấp tên miền thay vì localhost (tức là var socket = io.connect ('http://my.domain.com:3000');) trong index.html

b) thay đổi HOST trong app.js (tức là const HOST = 'my.domain.com';)

c) và thêm các ổ cắm vào dòng 37 của app.js (tức là 'socket.sockets.on (' kết nối ', hàm (máy khách) {…')



0

theo giải pháp @alex . nếu bạn gặp lỗi như thế này theo @tyler đề cập:

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.

thì bạn cần cài đặt Redis trước. kiểm tra cái này:

http://redis.io/download

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.