Closed atian25 closed 7 years ago
基于cluster-client
,实现client
没问题,但是server
还是不可以的。 一旦启动 cluster 模式,websocket就会握手失败。我感觉,要和egg有机结合起来,并利用多核能力,需要设计一番。
嗯, websocket / socket.io 算是比较重要的一个 showcase 的插件.
cc @fengmk2 @popomore @dead-horse
主要是集群的不好做
得 egg-cluster
有支持 sticky session 的开关,并且插件可以有办法在框架启动之前改变 cluster 的配置,有办法吗
依赖 socket.io ,基于标准的 redis 来做 cluster server。跟 cluster-client 没有半毛关系的。
@fengmk2 现在的 cluster 逻辑会导致 websocket 握手失败
没明白为啥要用 cluster-client 实现?
当我没说 cluster-client ~
反正就是需要一个完善的 websocket 插件~
@denghongcai 所以要基于 redis 来维持 websocket 的 session,走 socket.io 标准的模式。
目前最快的是 https://github.com/uWebSockets/uWebSockets
但是最通用和最易用的是 socket.io https://www.npmjs.com/package/socket.io
https://www.npmjs.com/package/socket.io-redis
By running socket.io with the socket.io-redis adapter you can run multiple socket.io instances in different processes or servers that can all broadcast and emit events to and from each other.
@fengmk2 socket.io可以直接使用uWebsockets
websocket和socket.io都是非常重要的一个模块,使用的人太多了,所以egg得在这个上面封装一套支持集群模式的方案。
将会在 https://github.com/eggjs/egg-websocket 做.
@fouber
@atian25 会有 socket.io 吗?
@arden 这个库有可能内部实现用 socket.io 吧, 看具体写的时候.
@gxcsoccer @ngot 你们谁上?
我来搞
@ngot 👍 ,可以在正文 issue 写一下方案
@fengmk2 @ngot @atian25 目前我们也使用了socket.io,使用uWebsockets做为engine。本来想用pm2来做集群方案,可是在pm2的cluster运行模式下,socket.io有总有问题,只能使用pm2的fork运行模式,直接在代码里通过socket.io-redis实现socket.io的cluster模式。但光socket.io-redis还不够,session这块还需要处理。所以整个项目依赖了以下几个模块: 集群和session处理模块 https://github.com/uqee/sticky-cluster https://github.com/socketio/socket.io-redis 高效率websocket引擎 https://github.com/uWebSockets/uWebSockets https://github.com/Unitech/pm2
另外据说socket.io 2.0默认用uWebsockets做为ws引擎。
我觉得如果基于socket.io做的话,就叫 egg-socket.io 吧,egg-websocket 要做的话,就只对uWebSockets封装
要不要把某领域的解决方案放这里 https://github.com/eggjs/egg/issues/287
@ngot 改名了
npm 也占个 0.0.1吧
发自我的 iPhone
在 2017年2月10日,19:29,Hengfei Zhuang notifications@github.com 写道:
https://github.com/eggjs/egg-socket.io 先占坑
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
很好啊。 可以在所有的npm包里都打上egg-前缀,多么美妙的事情啊。哈哈。
同意楼上的意见!@calidion
@ngot egg-socket.io 什么时候可用?
好多插件正在进行中,能否有个页面可以让满怀期待的吃瓜群众看到计划或详细进展
@jinMaoHuiHui 主要还是关注各个插件对应的 issue 即可, 这些插件并不属于 egg 的核心代码, 所以不会纳入到 egg 1.0 的规划里面.
另外, 我们更期望社区这边能参与进来一起共建.
讨论一下集成到egg的设计思路:
对于这种长连接应用,比基于 请求 - 响应
的 http
服务,要更复杂,类型更多。
socket.io 库本身,类似于koa,只提供了最基本的API,如使用中间件使用 use
,并没有类似 egg
这样的约定开发规范。
我思考,既然 socket.io
集成 egg
就应该按照约定的思路,设计一套开发规范出来。
http
服务和 socket
服务混布。主要考虑到,目前的 sticky
负载不是适合于 http
服务,同时,两套约定规范融合于同一个项目也是非常的复杂和痛苦。从应用维护角度看来,也是长连接服务单独部署比较合理。app
下所有现有的目录,并稍加改进。app
├── bgtask # 后台任务
│ └── adPush.js # 比如广告推送
├── cmidware # tcp连接级别中间件
│ └── auth.js # 授权验证
├── controller # 消息处理
│ └── chat.js # 聊天消息处理
├── pmidware # tcp包级别中间件
│ └── filter.js # 一些过滤
└── tcp-router.js # 一些配置,比如消息事件绑定
大家看看如何?
如果不混部,为什么要强行在 egg 里面支持 socket.io,我们设计的这一套 web 开发相关的规范本来就美为 socket.io 考虑,等于是要再造一个基于 socket.io 的上层框架,我们本身也没有类似的强需求,不应该做到 egg 里面。
我的看法是我们主要解决的第二类问题。
赞同,第二点需求。 那么,关于开发规范,问题呢?
在没有最佳实践的前提下,我们主要解决几个问题:
先做轻量级,后面再去规划,以前做过一个试验性质的 koa.io,不过因为没有使用场景无法深入使用而停止开发了。
赞同 @dead-horse , 如果第一点, egg-socket.io 就不是插件了,而是基于 egg-core 的一个框架封装了,跟 egg 是同一层的了
tcp-router.js
还是可以服用 app/router.js
的,只是里面通过 app.io.xxx
api 来实现路由。
这样确保路由都在同一个地方配置吧。
同样,cmidware和pmidware也可以放到 middleware 目录,然后增加 socket 子目录区分? bgtask 就是 schedule 吧?
需要跟 http 请求复用 service 等通用代码,就需要造一个基于 websocket 的 ctx 了
websocket 是否也能抽象为 请求 - 响应
模式?
@fengmk2 我们先不去强行抽象为请求响应模式吧,复用 service 代码不需要完整的造 ctx,其实只是复用业务逻辑,本来我们也不推荐在 service 上直接使用 ctx 的方法。
目录的话如果到处都要拆两个的话,不如统一放到app/sio
下面?
middleware 没必要拆分目录吧, 那个目录只是加载用的, 挂载是在 config.middleware 的
middleware因为ctx其实是不同的,放在一起,感觉会混
我倾向于这样的 app/sio
单独目录,比较好组织和解析,看起来也不容易混。
那这里是否也需要考虑到和 websocket 插件的统一规范不?
先不用考虑这么多,实践中摸索吧,egg-socketio 也只是我们提供的一个插件和一个扩展的解决方案,先不侵入到 egg 的核心中。
@ngot 首先,不支持 http 服务和 socket 服务混布。主要考虑到,目前的 sticky 负载不是适合于 http 服务,同时,两套约定规范融合于同一个项目也是非常的复杂和痛苦。从应用维护角度看来,也是长连接服务单独部署比较合理。 其实我还是比较认可这种方案,现在有很多http/socket混合在一起的方案,但实际上都很少使用,感觉实用价值并不大,并且容易复杂化。
@arden 上面说了,如果混部,那根本不需要考虑 egg 集成的事情了。
├── app
│ ├── io
│ │ ├── controller
│ │ │ └── chat.js
│ │ └── middleware
│ │ ├── auth.js
│ │ └── filter.js
│ └── router.js
├── config
│ ├── config.default.js
│ └── plugin.js
└── package.json
module.exports = app => {
app.get('/', 'home'); // http router
app.io.on('connection', socket => {
socket.on('chat', app.io.controller.chat);
});
};
exports.io = {
cmiddleware: [ 'auth' ], // connection middleware
pmiddleware: [ 'filter' ], // packet middleware
};
module.exports = app => {
return (socket, next) => {
console.log('auth middleware!');
next();
};
};
module.exports = app => {
return (packet, next) => {
console.log('filter middleware!');
next();
};
};
module.exports = app => {
return msg => {
console.log('chat :', msg + process.pid);
setTimeout(function () {
socket.emit('res', 'Hello World !');
}, 500);
}
};
最终就这样吧
midware
typo ?
@atian25 fixed
Directory Structure
Configuration
Middleware
middleware are functions which every connection or packet will be processed by.
Connection Middleware
app/io/middleware/auth.js
config/config.default.js
pay attention to the namespace, the config will only work for a specific namespace.
Packet Middleware
app/io/middleware/filter.js
config/config.default.js
pay attention to the namespace, the config will only work for a specific namespace.
Controller
controller is designed to handle the
emit
event from the client.example:
app/io/controller/chat.js
next, config the router at
app/router.js