【问题标题】:What are the thing we need to configure to implement live notification module (using redis and socket.io) in https server?我们需要配置什么来在 https 服务器中实现实时通知模块(使用 redis 和 socket.io)?
【发布时间】:2018-04-01 11:43:11
【问题描述】:

我已经在我的本地机器上成功地完成了实时通知模块。我需要在实时服务器中实现这个模块。实时服务器是 https。我不知道我们需要为 https 更改哪些内容。请检查我的代码并帮助将其集成到 https 服务器上。谢谢。

ssl 文件

SSLCertificateFile /etc/letsencrypt/live/dev.test.de/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/dev.test.de/privkey.pem

socket.js

var app   = require('express')();
var http  = require('http').Server(app);
var io    = require('socket.io')(http);
var redis = require('redis');

io.on('connection', function(socket){
    console.log('a user connected');

    var redisClient = redis.createClient();

    /* Realtime message subscribe */
    redisClient.subscribe('message');
    redisClient.on('message', function(channel, message){
        /*console.log('new message in queue', channel, message);*/
        socket.emit(channel, message);
    });

    /* Realtime inquiry subscribe */
    redisClient.subscribe('inquiryCount');
    redisClient.on('inquiryCount', function(channel, message){
        /*console.log('new inquiry in queue', channel, message);*/
        socket.emit(channel, message);
    });

    socket.on('disconnect', function(){
        redisClient.quit();
        console.log('user disconnected');
    });
});


http.listen(3000, function(){
    console.log('listening on *:3000');
});

app.blade.php

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
    <script>
        var socket = io('{{env('APP_URL')}}:3000');
        /* Realtime message notification */
        socket.on('message', function(data){
           if(data){
               /* var res = $.parseJSON(data);*/
               $('.messages-menu').empty();
               $('.messages-menu').html(data);
           }
        });
        /* Realtime inquiry notification */
        socket.on('inquiryCount', function(data){
            if(data){
                $('.tasks-menu').empty();
                $('.tasks-menu').html(data);
            }
        });
    </script>

DashboardController.php

public function privateMessageAPICount($id)
{
      $message = 'taking count of data';
      if(count($message) > 0){
           $redis = Redis::connection();
                $redis->publish('message', $message);
                return response()->json(['status' => 'success'], 200);
        }
        else {
            return response()->json(['status' => 'No Result'], 404);
        }
 }

public function inquiryAPIUnreadCount($id)
{
   $inquiryCount .= 'taking count of data';
   if(count($inquiryCount ) > 0){
         $redis = Redis::connection();
          $redis->publish('inquiryCount', $inquiryCount);
          return response()->json(['status' => 'success'], 200);
        }
        else {
            return response()->json(['status' => 'No Result'], 404);
        }              
 }

【问题讨论】:

    标签: php laravel sockets laravel-5 laravel-5.4


    【解决方案1】:

    当您的 apache 服务器已经使用 https 进行配置时,您只需在 ws-server 中实现 https。由于这是一个节点 http 服务器,因此修改后的代码应该可以工作(基于此 post):

    var app   = require('express')();
    var fs = require('fs');
    var privateKey  = fs.readFileSync('/etc/letsencrypt/live/dev.test.de/privkey.pem', 'utf8');
    var certificate = fs.readFileSync('/etc/letsencrypt/live/dev.test.de/fullchain.pem', 'utf8');
    var credentials = {key: privateKey, cert: certificate};
    var https  = require('https').createServer(credentials, app);
    var io    = require('socket.io')(https);
    var redis = require('redis');
    
    
    io.on('connection', function(socket){
        console.log('a user connected');
    
        var redisClient = redis.createClient();
    
        /* Realtime message subscribe */
        redisClient.subscribe('message');
        redisClient.on('message', function(channel, message){
            /*console.log('new message in queue', channel, message);*/
            socket.emit(channel, message);
        });
    
        /* Realtime inquiry subscribe */
        redisClient.subscribe('inquiryCount');
        redisClient.on('inquiryCount', function(channel, message){
            /*console.log('new inquiry in queue', channel, message);*/
            socket.emit(channel, message);
        });
    
        socket.on('disconnect', function(){
            redisClient.quit();
            console.log('user disconnected');
        });
    });
    
    
    https.listen(3000, function(){
        console.log('listening on *:3000');
    });
    

    您的APP_URL 必须以https:// 开头。

    我建议使用laravel-echo-server 来处理ws-connections,它更简单

    【讨论】:

    • 我试过这段代码,但我收到错误ReferenceError: fs is not defined
    • 现在我收到另一个错误ReferenceError: http is not defined
    • 已修复。很抱歉没有测试它。我在没有使用 ide 的情况下在 stackoverflow 中修改了您的代码。
    • 现在显示端口正在监听。但是a user connected 控制台消息没有显示。我使用redis-cli monitor 监控redis。通知计数显示在 redis 中。用户连接出现问题。
    • 当您尝试连接时,浏览器控制台中是否出现错误?您是否已将 https 添加到您的 URL 中?
    【解决方案2】:

    我不能把它写成命令@sam sam。

    只需要做的是

        http{
        server {
                listen       443 ssl;
                server_name  localhost;
                keepalive_timeout  5;
                proxy_connect_timeout 7d;
                proxy_send_timeout 7d;
                proxy_read_timeout 7d;
    
                # Self-signed certificate.
                ssl_certificate ../ssl/server.crt;
                ssl_certificate_key ../ssl/server.key;
                ssl_protocols         SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    
                location / {
                    proxy_pass http://apache_nodes/;
                    proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "upgrade";
                    proxy_redirect off;
    
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
        }
           upstream apache_nodes {
            server 192.168.1.155;
        }
    
    }
    

    这将保证您处理 443 并通过代理传递将客户端发送到 80。

    更多信息请查看 nginx ssl 代理服务器。使用相同的代理服务器,您还可以处理超过 443 的 socket.io 请求

    为此

     upstream socket_nodes_1 {
            server 192.168.1.155:1337;
        }
    location /sockets {
                proxy_pass http://socket_nodes_1/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_redirect off;
    
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }
    

    问候,

    【讨论】:

    • 但是这是基于nginx的吧?我正在使用 Apache 2。
    【解决方案3】:

    这是我的工作 socket_https.js :

    const fs = require('fs');
    
    const options = {
        key: fs.readFileSync('/etc/letsencrypt/live/dev.test.de/privkey.pem'),
        cert: fs.readFileSync('/etc/letsencrypt/live/dev.test.de/fullchain.pem'),
        NPNProtocols: ['http/2.0', 'spdy', 'http/1.1', 'http/1.0']
    };
    
    var server = require('https').Server(options);
    
    var io = require('socket.io')(server);
    
    
    var Redis = require('ioredis');
    var redis = new Redis();
    
    redis.subscribe('message-channel');
    
    redis.on('message', function (channel, message) {
        console.log('Message Receive');
        console.log(message);
        message = JSON.parse(message);
    
        io.emit(channel + ':' + message.event, message.data);
    });
    
    server.listen(4000);
    

    然后当我想发布到 redis 时:

    $data = [
          'event' => 'someEvent',
          'data'  => [
                          'id' => $id,
                          [...]
                      ]
    ];
    
    Redis::publish('my-channel', json_encode($data));
    

    【讨论】:

    • 我已经尝试过您的代码,但在运行 node socket.js 时遇到了一些错误。 SyntaxError: Unexpected token &lt; at Object.parse (native) at Redis.&lt;anonymous&gt; (/var/www/html/demo.laravel-api/ socket.js:22:20) at emitTwo (events.js:87:13) at Redis.emit (events.js:172:7) at Redis.exports.returnReply (/var/www/html/demo.laravel-api/node_modules/ioredis/lib/redis/parser.js:107:14)
    • 我已经添加了我用来发布到 redis 的代码
    【解决方案4】:

    不要改变任何事情。仅使用 nginx 处理 https 并在位置 / 上使用 proxypass 到 80 端口。顺便说一句,您的系统现在支持并使用 https

    【讨论】:

    • 我正在使用 Apache 2。你知道我们需要在 Apache 2 中配置哪些东西吗?
    • 山姆答案如下。你可以检查一下。有更多问题可以发邮件给我
    猜你喜欢
    • 2017-04-16
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    相关资源
    最近更新 更多