npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cluster-dispatch

v2.2.1

Published

解决Node.js在Cluster模式下的连接/资源复用问题

Downloads

8

Readme

cluster-dispatch

解决Node.js在Cluster模式下的连接/资源复用问题

NPM version build status Test coverage David deps node version npm download npm license

你会不会有这么一种场景, 比如创建一个TCP连接并且监听一个configserver的配置变动, 当变动的时候同时调整配置, 当你的应用运行在cluster模式下这个TCP连接就会是N个, 但是你并不需要N个因为浪费系统和你的服务方资源, 你只需要有一个TCP连接就够了.

这个模块就是解决这个问题诞生的.

他用了这样一个进程模型

        Master  -> fork Library
          |           |       
          |         Agent
       Cluster        |
  Wokrer, Wokrer, Woker....

你可以把需要复用的资源放在Library进程中, Agent来负责跨进程的调用

Installation

$ npm i cluster-dispatch --save

Example

$ git clone

$ npm i

$ npm run example

API

Master

master作为守护进程也是应用的入口, 负责启动appWokrer和libraryWorker

const Master = require('cluster-dispatch').Master;

/*
  * @param {Object} options
  *   - {String} baseDir - 工程根路径
  *   - {String} appPath - app进程入口文件, 可以是一个相对路径
  *   - {String} libraryPath - 第三方库入口文件, 具体参照exmaple/lib/index.js, 可以是一个相对路径
  *   - {Number} appWorkerCount - 需要启动的app进程数
  *   - {Funcion} logging - log
  *   - {Boolean} needLibrary - 是否需要启动library进程
  *   - {Boolean} needAgent - 是否需要自动启动代理
 */
const master = new Master({
  baseDir: __dirname,
  logging: debug,
  appWorkerCount,
});

(async function initMaster() {
  await master.init(); // 初始化

  master.on('error', error => debug(error));
})().catch(debug)

Agent

agent负责跨进程的调度, 这个agent实例每个appWorker都有, 默认会在appWorker初始化时创建好

在appWorker中通过Agent.getAgent()就可以拿到agent实例

// agent/index.js
'use strict';

const Agent = require('cluster-dispatch').Agent;

module.exports = Agent.getAgent();

通过agent调用和正常调用是一样的, 只是得通过agent对象调用

eg

// agent/lib/demo.js
module.exports = {
  getName() {
    return new Promise((resolve) => {
      resolve('get name')
    });
  }
}

// index.js
const agent = require('./agent')

(async function eg() {
  const name = await agent.demo.getName()
  console.log(name) // "get name"
})().catch(console.error)

不过因为是跨进程的所以任何调用都是异步的, 即使你调用的原本是个同步方法

启动流程

  1. 启动master进程
  2. master fork 出 library worker
  3. library worker 根据实例化master传递的libraryPath参数拿到下面对象签名, 然后触发ready事件给master
  4. master接到ready事件后开始已cluster模式启动app worker
  5. app worker初始化完成后会向library worker请求对象签名, 拿到对象签名后开始初始化agent
  6. agent遍历对象签名, 并且把对象的每个key重写, 类似这样的逻辑
agent.invoke = function(objName, methodName, ...rest) {
  return client.setTo('Library').send({
    objName,
    methodName,
    args: rest,
  })
}

等于拿到你的调用方法后, 把参数原样返回回去, 实际执行还是在library worker中

  1. done