Broadcasting With Redis and Laravel

Giới thiệu về cơ chế Pub/Sub
Trong hệ thống phân tán lớn, message broker là một thành phần vô cùng quan trọng. Lý do vì sao mình xin thứ lỗi không giải thích ở đây. Hiện nay, có 2 messaging model phổ biến là message queuing và pub/sub messaging.

Message queuing được thiết kế để thực hiện danh sách task một cách lần lượt. Khi một message đến, hàng đợi sẽ tiếp nhận. Nếu task trước đó đã thực thi xong, message đó sẽ bị xóa, message kế tiếp mới được gửi đi để xử lý task tương ứng. Vậy thì ở đây, với message queuing, nếu như một message bị lỗi gì đó, thì có thế các message sau sẽ không được xử lý theo tuần tự nữa.

Pub/Sub messaging cũng làm nhiệm vụ giống như message queuing. Tuy nhiên, cơ chế của pub/sub có khác biệt:

Pub – Publish: producer sẽ đẩy data vào một chanel.
Sub – Subscribe: consumer đăng ký nhận dữ liệu từ một chanel.

Cái này giống như bạn xem Youtube. Bạn subscribe một channel. Khi một producer làm một video đẩy lên Youtube. Bạn sẽ nhận dữ liệu, tức xem video đó tại channel mà bạn đã subscribe. Khi bạn bè của bạn cũng subscribe channel đó, thì khi producer đẩy video lên, bạn và bạn bè của bạn cùng nhận được video để xem. Và tất nhiên, bạn có thể đăng ký nhiều channel.

Và tất nhiên mỗi messaging model có một ưu điểm riêng và tùy vào bài toán mà sử dụng chúng.
Để cài redis server các bạn tham khảo các bài này của mình:http://www.gacoder.info/category/redis/
Phần 1:Tạo server nodejs subscribe client:
Tạo folder thong_bao_server.Sau đó chạy lệnh sau:

cd broadcasting_server
npm init

Các bạn cứ enter để mặc định.File package.json sẽ có nội dung sau:

{
  "name": "broadcasting_server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Tiếp theo setup webserver:

npm install express ejs ioredis socket.io --save

Tiếp theo tạo file index.js với nội dung như sau:

var server=require('http').Server();
var io = require('socket.io')(server);
var Redis=require('ioredis');
var redis = new Redis(6379, "192.168.174.128");//các bạn đổi địa chỉ ip tới server redis nhé.Mặc định là port 6379

redis.subscribe('test-channel');

redis.on('message',function(channel,message){
	console.log('Message Received');
	console.log(message);
})

server.listen(3000,function(){
	console.log('server run');
});

Publish với laravel:
Các bạn tạo route như sau:

use Illuminate\Support\Facades\Redis;
Route::get('/', function () {
	//Publish event with Redis
    $data=[
    	'event'=>'Message',
    	'data'=>[
    		'message'=>'Xin chào gacoder.info'
    	]
    ];
    Redis::publish('test-channel',json_encode($data));
    return 'done';
});

Tiếp theo ta chạy server nodejs:

node index.js

Chạy web laravel.Kết quả ở cmd là:

server run
Message Received
{"event":"Message","data":{"message":"Xin ch\u00e0o gacoder.info"}}

Chinh sửa server nodejs chỉ hiển thị tin nhắn.Các bạn thay thể code cũ thành code mới như:

redis.on('message',function(channel,message){
	message=JSON.parse(message);
	console.log(message.data.message);
})

Sau đó chạy lại server nodejs va laravel.Ở nodejs cmd sẽ hiẻn thị như sau:

D:\xampp\htdocs\broadcasting_server>node index.js
server run
Xin chào gacoder.info

Tiếp theo ta sẽ viết sự kiện cho phép gửi tin nhắn tới mọi client dùng socketio.
Ta sửa server nodejs lại như sau:

redis.on('message',function(channel,message){
	message=JSON.parse(message);
	io.emit(channel+':'+message.event,message.data);//test-channel:Message
})

Ta thêm route laravel tên message dùng để hiển thị thông báo:

Route::get('message', function () {
    return view('message');
});

File template message.blade.php laravel

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/mouse0270-bootstrap-notify/3.1.7/bootstrap-notify.min.js"></script>
    </head>
    <body>
    <h1>Thông báo</h1>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
    <script>
    var socket = io('http://localhost:3000');
    socket.on('test-channel:Message', function(data){
        $.notify({
                message:data.message 
            },{
                // settings
                delay: 0,
                type: 'danger'
            });
      });

    </script>
    </body>
</html>

Các bạn chú ý test-channel:Message có nghĩa là ta dùng channel là test-channel và event là Message
Tổng kết:
File index.js

var server=require('http').Server();
var io = require('socket.io')(server);
var Redis=require('ioredis');
var redis = new Redis(6379, "192.168.174.128"); 

redis.subscribe('test-channel');

redis.on('message',function(channel,message){
	message=JSON.parse(message);
	io.emit(channel+':'+message.event,message.data);//test-channel:Message
})

server.listen(3000,function(){
	console.log('server run');
});

Route laravel:

Route::get('/', function () {
	//Publish event with Redis
    $data=[
    	'event'=>'Message',
    	'data'=>[
    		'message'=>'Xin chào gacoder.info'
    	]
    ];
    Redis::publish('test-channel',json_encode($data));
    return 'done';
});

Route::get('message', function () {
    return view('message');
});

Test:
Chạy server nodejs

node index.js

Chạy link hiển thị message laravel http://your-domain/message
Mở cửa số mới truy cập link:http://your-domain/
Quay lại cửa số http://your-domain/message
Kết quả:

0 Shares

Leave a Reply

avatar
  Subscribe  
Notify of