socket.io如何进行分布式部署

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket.io如何进行分布式部署相关的知识,希望对你有一定的参考价值。

参考技术A 结构不是问题,现在的问题是 效率的问题。 现在大部分的例子都是在单机的情况下,当有用户上线时,直接io.sockets.broadcast群发一个消息,但这是个广播消息,效率太低,特别是 在使用 socket.io + redis pub/sub的情况下,一个用户的上下线,就给整个系统是群发一个消息,真是个悲剧. 我自己的想法是 用redis或memerycache 缓存用户的好友列表和全系统的在线用户信息(在线用户信息中包含当前所在server的信息,如IP地址),如果用户的好友列表中有用户在线,则可以找到该在线好友所在的socket.io server的IP地址,将上线消息emit到好友所在的server,好友所在的server收到消息之后,根据该台server中缓存的socket列表,最终可以找到该好友对应的socket连接,并将消息发送出去。

如何将 socket.io 部署到 Google App Engine?

【中文标题】如何将 socket.io 部署到 Google App Engine?【英文标题】:How do I deploy socket.io to Google App Engine? 【发布时间】:2016-09-20 22:33:03 【问题描述】:

我使用 socket.io 创建了我的第一个 node.js 应用程序。具体来说,我实现了socket.io发布的chat example。它在本地完美运行。然后我尝试将其部署到 Google App Engine(对节点进行一些代码调整以使其正常工作)。

一切都表明节点部分运行良好。但是聊天不起作用,表明 socket.io 部分不起作用。您可以看到已部署的应用程序(和页面源)here。

我是否需要做任何额外的事情? yaml 或 json 文件中的内容?

yaml 内容:

runtime: nodejs
vm: true

skip_files:
  - ^(.*/)?.*/node_modules/.*$

json 内容:


  "name": "Chaty",
  "description": "chatrooms app",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "McChatface",
  "engines": 
    "node": "~4.2"
  ,
  "scripts": 
    "start": "node app.js",
    "monitor": "nodemon app.js",
    "deploy": "gcloud preview app deploy"
  ,
  "dependencies": 
    "express": "^4.13.4",
    "socket.io": "^1.4.6"
  

【问题讨论】:

【参考方案1】:

简而言之,这不能在生产中完成,它似乎是work in process。正确的架构是在谷歌计算引擎上拥有一个聊天服务器,如here 所述。

但作为概念证明,在谷歌应用引擎上使用 socket.io 与google appengine samples for websockets 中显示的非常相似。

如果是 socket.io,请在服务器端执行以下步骤。下面是代码 sn-p。

    创建第二个 express 中间件和服务器。 在新服务器上附加/使用 socket.io。 监听端口 (65080)。 为谷歌计算引擎上的端口 (65080) 打开防火墙。 链接到working repository。

socket.io 在服务器端发生变化

    var app_chat = require('express')();
    var server1 = require('http').Server(app_chat);
    var io = require('socket.io')(server1);
    server1.listen(65080);

    io.on('connection', function (socket) 
      console.log('user connected');
      socket.on('chat_message', function (data) 
        console.log('client sent:',data);
        socket.emit('chat_message', 'Server is echoing your message: ' + data);
      );
    );

通过命令打开防火墙

gcloud compute firewall-rules create default-allow-websockets \
    --allow tcp:65080 \
    --target-tags websocket \
    --description "Allow websocket traffic on port 65080"

我希望 Google 能尽快推出可用于生产的解决方案,因为这将成为任何 PaaS 武器库的关键装甲。

【讨论】:

Google 示例应用的链接已损坏;这个似乎很接近:github.com/GoogleCloudPlatform/appengine-websocketchat-java 在控制台中收到此错误无法加载资源:net::ERR_CONNECTION_TIMED_OUT staging-dot-wellnite-web-app.appspot.com:65080/socket.io/…【参考方案2】:

February 2019 中的 GAE 支持持续套接字连接!

要完成这项工作,您需要使用flex 环境并修改您的app.yaml 以包含session_affinity

network:
  session_affinity: true

请注意,我仍然需要打开端口 65080 才能使其正常工作,但我不需要进行其他更改。

阅读详情:

https://cloud.google.com/appengine/docs/flexible/nodejs/using-websockets-and-session-affinity

【讨论】:

您在移动设备上有什么问题吗?在桌面上一切正常,但在我的 iPhone(safari 和 chrome)上却无法连接。此外,我还没有打开任何其他端口......一切都通过8080。最后,我的应用程序正在使用我准备好的https可能会导致问题......我在这里难住了。 我在移动设备上仍然遇到问题。我尝试让它与 https 一起工作,但似乎 chrome 只是不接受证书。甚至 Safari 也可以工作,同样的引擎! @tommyc38:你有想过吗?我将尝试将我的后端移至 AWS。【参考方案3】:

Google 有一个使用 WebSockets here 的示例应用程序,您需要执行以下操作才能使其正常工作:

为服务器打开防火墙端口,以便客户端可以访问您的服务器 在 Google App Engine 中获取您的内部 IP,以便客户端知道要连接到哪个 IP 通过诸如 REST API 或 HTML 页面之类的方式从服务器中回显您的 IP

应该就是这样(不过不要相信我的话,这是我在对文档进行一些研究后能够找到的),希望对您有所帮助!

从 Google App Engine 中获取您的外部 IP

var METADATA_NETWORK_INTERFACE_URL = 'http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip';

function getExternalIp (cb) 
    var options = 
        url: METADATA_NETWORK_INTERFACE_URL,
        headers: 
            'Metadata-Flavor': 'Google'
        
    ;

    request(options, function (err, resp, body) 
        if (err || resp.statusCode !== 200) 
            console.log('Error while talking to metadata server, assuming localhost');
            return cb('localhost');
        

        return cb(body);
    );

打开防火墙端口

gcloud compute firewall-rules create default-allow-websockets \
    --allow tcp:65080 \
    --target-tags websocket \
    --description "Allow websocket traffic on port 65080"

【讨论】:

我觉得我已经很接近了,但还没有开始工作。我打开了防火墙端口并部署了 google websocket 项目。那行得通。但我还不知道如何使它与 socket.io 一起工作。因为socket.io使用的是使用8080监听的服务器并使用express。 // 启动服务器 var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() console.log('Press Ctrl+C to quit.'); ) ; var io = require('socket.io')(server); 示例应用的链接已损坏;这个似乎很接近:github.com/GoogleCloudPlatform/appengine-websocketchat-java【参考方案4】:

这个 app.yaml 配置对我有用:

runtime: nodejs
env: flex
manual_scaling:
instances: 1
network:
 session_affinity: true

我通过这个命令启用了防火墙规则:

gcloud compute firewall-rules create default-allow-websockets     --allow 
tcp:65080     --target-tags websocket     --description "Allow websocket 
traffic on port 65080"

【讨论】:

这对我有用。对于我的应用引擎实例,只有 yaml 配置就足够了,不需要更改防火墙设置

以上是关于socket.io如何进行分布式部署的主要内容,如果未能解决你的问题,请参考以下文章

socket.io分布式

分布式部署

MinIO分布式专题(第二章MinIO分布式部署)

在多个节点上部署 socket.io 应用程序

Django 项目分布式部署【UWSGI + NGINX】

基于docker 如何部署surging分布式微服务引擎