Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:add sticky cluster mode #14

Merged
merged 5 commits into from
Feb 13, 2017
Merged

feat:add sticky cluster mode #14

merged 5 commits into from
Feb 13, 2017

Conversation

ngot
Copy link
Member

@ngot ngot commented Feb 9, 2017

Checklist
  • npm test passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)
Description of change

增加sticky模式,用于websocket服务模式

@mention-bot
Copy link

@ngot, thanks for your PR! By analyzing the history of the files in this pull request, we identified @dead-horse, @popomore and @atian25 to be potential reviewers.

@ngot ngot mentioned this pull request Feb 9, 2017
@codecov
Copy link

codecov bot commented Feb 9, 2017

Codecov Report

Merging #14 into master will increase coverage by 0.33%.

@@            Coverage Diff             @@
##           master      #14      +/-   ##
==========================================
+ Coverage   96.25%   96.58%   +0.33%     
==========================================
  Files           7        7              
  Lines         267      293      +26     
==========================================
+ Hits          257      283      +26     
  Misses         10       10
Impacted Files Coverage Δ
lib/app_worker.js 96.66% <100%> (+1.01%)
lib/master.js 95.58% <100%> (+0.51%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d988b42...828280a. Read the comment docs.

@fengmk2
Copy link
Member

fengmk2 commented Feb 9, 2017

参考来源?

@ngot
Copy link
Member Author

ngot commented Feb 9, 2017

主要参考这个做的 https://github.com/elad/node-cluster-socket.io

@ngot
Copy link
Member Author

ngot commented Feb 9, 2017

@ngot
Copy link
Member Author

ngot commented Feb 10, 2017

@popomore @fengmk2 @dead-horse 同志们帮忙review下

@fengmk2
Copy link
Member

fengmk2 commented Feb 10, 2017

改动有点大,需要点时间去消耗一下什么是 sticky

@@ -34,7 +34,22 @@ function startServer() {
// emit `server` event in app
app.emit('server', server);

server.listen(options.port);
if (options.sticky) {
server.listen(0, '127.0.0.1');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这一步 listen 有什么作用?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原来的cluster模式完全没有改变。每个worker内的http的hander,依然需要存在,用来接受master转发过来的socket对象,来进行下一步的处理。这里listen 0只是为了启动http handler,而不暴露出去。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

去掉这个 listen 应该也是可以的。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要listen,不然逻辑走不下去

lib/master.js Outdated
}).listen(this.options.port);
}

stickyWorker(ip) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

要写一个测试,看看 stickyWorker 这个算法是否分配均匀

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个算法,是根据用户的IP和进程数量做的一个hash匹配。能够保证,某个固定ip映射到某个固定Worker。但是其实,并不能完全保证平均分配。如果,实际访问的样本IP是平均分布的,那么问题不大,如果是集中某几个固定IP,那么就会导致非常不均衡。昨天,想到公司内部做过代理,导致来源IP被篡改为公司固定的出口IP,是有问题的。

lib/master.js Outdated
@@ -309,6 +343,11 @@ class Master extends EventEmitter {
}

this.isAllAppWorkerStarted = true;

if (this.options.sticky) {
this.startMasterSocketServer();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startMasterSocketServer 也是一个异步过程,它成功了才能 ready 成功

return this.startMasterSocketServer(err => {
  if (err) return this.ready(err);
  this.ready(true);
});

app.ready(done);
});

after(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app.close() 返回的是 promise,需要 return 才会生效,写成 after(() => app.close())

describe('--sticky', () => {
before(done => {
app = utils.cluster('apps/cluster_mod_sticky', { sticky: true });
app.ready(done);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return app.ready() 即可,不需要 done 了

Copy link
Member

@fengmk2 fengmk2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

if (options.sticky) {
server.listen(0, '127.0.0.1');
// Listen to messages sent from the master. Ignore everything else.
process.on('message', (message, connection) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

忽略其他消息这个会不会影响到 messeger 那边?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该不会,这个只是新增一个listenser,只限定在这个逻辑,不会影响其他的。

lib/master.js Outdated
@@ -58,8 +58,12 @@ class Master extends EventEmitter {

this.ready(() => {
this.isStarted = true;
this.logger.info('[master] %s started on %s://127.0.0.1:%s (%sms)',
frameworkPkg.name, this.options.https ? 'https' : 'http', this.options.port, Date.now() - startTime);
let stickyMsg = '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const stickMsg = this.options.sticky ? ' with STICKY MODE!' : '';

lib/master.js Outdated
const wsd = ws.map(w => w % workerNumbers);

let s = '';
for (let i = 0, _len = ip.length; i < _len; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i < ip.length 就可以了

lib/master.js Outdated
s += ip[i];
}
}
s = +s;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s = Number(s)

lib/master.js Outdated

let s = '';
for (let i = 0, _len = ip.length; i < _len; i++) {
if (!isNaN(ip[i])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是不是用一些 hash 算法会比较好一点?不然很容易就造出一系列 ip 地址全部都连接到一个 worker 上了。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗯,是的,我也有这个担忧

@codecov
Copy link

codecov bot commented Feb 10, 2017

Codecov Report

Merging #14 into master will increase coverage by 0.33%.

@@            Coverage Diff             @@
##           master      #14      +/-   ##
==========================================
+ Coverage   96.25%   96.58%   +0.33%     
==========================================
  Files           7        7              
  Lines         267      293      +26     
==========================================
+ Hits          257      283      +26     
  Misses         10       10
Impacted Files Coverage Δ
lib/master.js 95.58% <100%> (+0.51%)
lib/app_worker.js 96.66% <100%> (+1.01%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d988b42...9deb273. Read the comment docs.

s += ip[i];
}
}
s = Number(s);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那直接改成 hash(ip) % workerNumbers ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我研究看看,有没有更好些的算法

Copy link
Member Author

@ngot ngot Feb 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

框架本身的话,没有找到很好的算法。大多数做法,还是在集群前面架设负载设备来做。目前,就这样其实就已经够了。

@fengmk2
Copy link
Member

fengmk2 commented Feb 13, 2017

LGTM, need @dead-horse one more +1

@dead-horse
Copy link
Member

+1, 先这样,到时候文档里面说清楚这个模式下的一些弊端和怎样配合反向代理使用好了。cluster 的文档里面都可以不介绍这个功能,只在 socket.io 的文档里面说明好了?

@dead-horse dead-horse merged commit 4a51254 into master Feb 13, 2017
@dead-horse dead-horse deleted the add-sticky-mod branch February 13, 2017 10:51
@dead-horse
Copy link
Member

1.4.0

@ngot
Copy link
Member Author

ngot commented Feb 14, 2017

就只在socket.io说明就好了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants