Home Web Front-end JS Tutorial How to implement port reuse function in Node.Js

How to implement port reuse function in Node.Js

Jun 01, 2018 am 11:32 AM
javascript node.js Reuse

This time I will bring you how to implement the port reuse function in Node.Js, what are the precautions for implementing the port reuse function in Node.Js, the following is a practical case, Let’s take a look.

Origin, from the official example, multi-process shared port

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
 console.log(`Master ${process.pid} is running`);
 for (let i = 0; i < numCPUs; i++) {
  cluster.fork();
 }
 cluster.on(&#39;exit&#39;, (worker, code, signal) => {
  console.log(`worker ${worker.process.pid} died`);
 });
} else {
 http.createServer((req, res) => {
  res.writeHead(200);
  res.end('hello world\n');
 }).listen(8000);
 console.log(`Worker ${process.pid} started`);
}
Copy after login

Execution result:

$ node server.js
Master 3596 is running
Worker 4324 started
Worker 4520 started
Worker 6056 started
Worker 5644 started

Understand the http.js module:

We all only need to create an http Service mustreferencehttp module. The http module will eventually call net.js to implement network services

// lib/net.js
'use strict';
 ...
Server.prototype.listen = function(...args) {
  ...
 if (options instanceof TCP) {
   this._handle = options;
   this[async_id_symbol] = this._handle.getAsyncId();
   listenInCluster(this, null, -1, -1, backlogFromArgs); // 注意这个方法调用了cluster模式下的处理办法
   return this;
  }
  ...
};
function listenInCluster(server, address, port, addressType,backlog, fd, exclusive) {
// 如果是master 进程或者没有开启cluster模式直接启动listen
if (cluster.isMaster || exclusive) {
  //_listen2,细心的人一定会发现为什么是listen2而不直接使用listen
 // _listen2 包裹了listen方法,如果是Worker进程,会调用被hack后的listen方法,从而避免出错端口被占用的错误
  server._listen2(address, port, addressType, backlog, fd);
  return;
 }
 const serverQuery = {
  address: address,
  port: port,
  addressType: addressType,
  fd: fd,
  flags: 0
 };
// 是fork 出来的进程,获取master上的handel,并且监听,
// 现在是不是很好奇_getServer方法做了什么
 cluster._getServer(server, serverQuery, listenOnMasterHandle);
}
 ...
Copy after login

The answer can be found soon through the cluster._getServer function

  1. Proxy server._listen2 This method performs operations in the work process

  2. Sends a queryServer message to the master and registers an internal TCP server with the master

// lib/internal/cluster/child.js
cluster._getServer = function(obj, options, cb) {
 // ...
 const message = util._extend({
  act: 'queryServer',  // 关键点:构建一个queryServer的消息
  index: indexes[indexesKey],
  data: null
 }, options);
 message.address = address;
// 发送queryServer消息给master进程,master 在收到这个消息后,会创建一个开始一个server,并且listen
 send(message, (reply, handle) => {
   rr(reply, indexesKey, cb);       // Round-robin.
 });
 obj.once('listening', () => {
  cluster.worker.state = 'listening';
  const address = obj.address();
  message.act = 'listening';
  message.port = address && address.port || options.port;
  send(message);
 });
};
 //...
 // Round-robin. Master distributes handles across workers.
function rr(message, indexesKey, cb) {
  if (message.errno) return cb(message.errno, null);
  var key = message.key;
  // 这里hack 了listen方法
  // 子进程调用的listen方法,就是这个,直接返回0,所以不会报端口被占用的错误
  function listen(backlog) {
    return 0;
  }
  // ...
  const handle = { close, listen, ref: noop, unref: noop };
  handles[key] = handle;
  // 这个cb 函数是net.js 中的listenOnMasterHandle 方法
  cb(0, handle);
}
// lib/net.js
/*
function listenOnMasterHandle(err, handle) {
  err = checkBindError(err, port, handle);
  server._handle = handle;
  // _listen2 函数中,调用的handle.listen方法,也就是上面被hack的listen
  server._listen2(address, port, addressType, backlog, fd);
 }
*/
Copy after login

The master process starts the service after receiving the queryServer message

  1. If the address has not been monitored, start the service through RoundRobinHandle monitoring

  2. If the address has been monitored, directly bind the handle to the service that has been monitored to consume the request

// lib/internal/cluster/master.js
function queryServer(worker, message) {
  const args = [
    message.address,
    message.port,
    message.addressType,
    message.fd,
    message.index
  ];
  const key = args.join(':');
  var handle = handles[key];
  // 如果地址没被监听过,通过RoundRobinHandle监听开启服务
  if (handle === undefined) {
    var constructor = RoundRobinHandle;
    if (schedulingPolicy !== SCHED_RR ||
      message.addressType === 'udp4' ||
      message.addressType === 'udp6') {
      constructor = SharedHandle;
    }
    handles[key] = handle = new constructor(key,
      address,
      message.port,
      message.addressType,
      message.fd,
      message.flags);
  }
  // 如果地址已经被监听,直接绑定handel到已经监听到服务上,去消费请求
  // Set custom server data
  handle.add(worker, (errno, reply, handle) => {
    reply = util._extend({
      errno: errno,
      key: key,
      ack: message.seq,
      data: handles[key].data
    }, reply);
    if (errno)
      delete handles[key]; // Gives other workers a chance to retry.
    send(worker, reply, handle);
  });
}
Copy after login

Seeing this step, it is already obvious that we know how to carry out more ports Sharing implementation principle

  1. In fact, the port is only monitored once by the internal TCP server in the master process

  2. Because the net.js module will determine Is the current process a master or a Worker process?

  3. If it is a Worker process, call cluster._getServer to hack the native listen method.

  4. So call it in the child The listen method is an empty method that returns 0, so it will not report a port occupation error

Now the question comes, since how does the Worker process get the master process listening service received What about the connect?

  1. Listen to the connection of the TCP server started by the master processEvent

  2. Select a worker through polling

  3. Send newconn internal message to it, the message body contains the client handle

  4. ##With the handle, everyone knows how to deal with it haha

  5. // lib/internal/cluster/round_robin_handle.js
    function RoundRobinHandle(key, address, port, addressType, fd) {
      this.server = net.createServer(assert.fail);
      if (fd >= 0)
        this.server.listen({ fd });
      else if (port >= 0)
        this.server.listen(port, address);
      else
        this.server.listen(address); // UNIX socket path.
      this.server.once('listening', () => {
        this.handle = this.server._handle;
        // 监听onconnection方法
        this.handle.onconnection = (err, handle) => this.distribute(err, handle);
        this.server._handle = null;
        this.server = null;
      });
    }
    RoundRobinHandle.prototype.add = function (worker, send) {
      // ...
    };
    RoundRobinHandle.prototype.remove = function (worker) {
      // ...
    };
    RoundRobinHandle.prototype.distribute = function (err, handle) {
      // 负载均衡地挑选出一个worker
      this.handles.push(handle);
      const worker = this.free.shift();
      if (worker) this.handoff(worker);
    };
    RoundRobinHandle.prototype.handoff = function (worker) {
      const handle = this.handles.shift();
      const message = { act: 'newconn', key: this.key };
      // 向work进程其发送newconn内部消息和客户端的句柄handle
      sendHelper(worker.process, message, handle, (reply) => {
      // ...
        this.handoff(worker);
      });
    };
    Copy after login
Let us see what operations the Worker process performed after receiving the newconn message

// lib/child.js
function onmessage(message, handle) {
  if (message.act === 'newconn')
   onconnection(message, handle);
  else if (message.act === 'disconnect')
   _disconnect.call(worker, true);
 }
// Round-robin connection.
// 接收连接,并且处理
function onconnection(message, handle) {
 const key = message.key;
 const server = handles[key];
 const accepted = server !== undefined;
 send({ ack: message.seq, accepted });
 if (accepted) server.onconnection(0, handle);
}
Copy after login

Summary

  1. The net module will judge the process, whether it is a worker or a master. If it is a worker, hack it. The listen method of the net.Server instance

  2. listen called by the worker The method is hacked and returns 0 directly, but a connection event will be registered with the master.

  3. After the master receives the client connection event, it will poll and send the connection to the worker. Client handle

  4. The worker receives the client handle sent by the master, and then it can process the client request

I believe I read this article You have mastered the case method. For more exciting information, please pay attention to other related articles on the PHP Chinese website!

Recommended reading:

Vue.js two-way binding project practical analysis

How jquery determines that the element content is empty

The above is the detailed content of How to implement port reuse function in Node.Js. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to implement an online speech recognition system using WebSocket and JavaScript How to implement an online speech recognition system using WebSocket and JavaScript Dec 17, 2023 pm 02:54 PM

How to use WebSocket and JavaScript to implement an online speech recognition system Introduction: With the continuous development of technology, speech recognition technology has become an important part of the field of artificial intelligence. The online speech recognition system based on WebSocket and JavaScript has the characteristics of low latency, real-time and cross-platform, and has become a widely used solution. This article will introduce how to use WebSocket and JavaScript to implement an online speech recognition system.

WebSocket and JavaScript: key technologies for implementing real-time monitoring systems WebSocket and JavaScript: key technologies for implementing real-time monitoring systems Dec 17, 2023 pm 05:30 PM

WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

How to use JavaScript and WebSocket to implement a real-time online ordering system How to use JavaScript and WebSocket to implement a real-time online ordering system Dec 17, 2023 pm 12:09 PM

Introduction to how to use JavaScript and WebSocket to implement a real-time online ordering system: With the popularity of the Internet and the advancement of technology, more and more restaurants have begun to provide online ordering services. In order to implement a real-time online ordering system, we can use JavaScript and WebSocket technology. WebSocket is a full-duplex communication protocol based on the TCP protocol, which can realize real-time two-way communication between the client and the server. In the real-time online ordering system, when the user selects dishes and places an order

How to implement an online reservation system using WebSocket and JavaScript How to implement an online reservation system using WebSocket and JavaScript Dec 17, 2023 am 09:39 AM

How to use WebSocket and JavaScript to implement an online reservation system. In today's digital era, more and more businesses and services need to provide online reservation functions. It is crucial to implement an efficient and real-time online reservation system. This article will introduce how to use WebSocket and JavaScript to implement an online reservation system, and provide specific code examples. 1. What is WebSocket? WebSocket is a full-duplex method on a single TCP connection.

JavaScript and WebSocket: Building an efficient real-time weather forecasting system JavaScript and WebSocket: Building an efficient real-time weather forecasting system Dec 17, 2023 pm 05:13 PM

JavaScript and WebSocket: Building an efficient real-time weather forecast system Introduction: Today, the accuracy of weather forecasts is of great significance to daily life and decision-making. As technology develops, we can provide more accurate and reliable weather forecasts by obtaining weather data in real time. In this article, we will learn how to use JavaScript and WebSocket technology to build an efficient real-time weather forecast system. This article will demonstrate the implementation process through specific code examples. We

Simple JavaScript Tutorial: How to Get HTTP Status Code Simple JavaScript Tutorial: How to Get HTTP Status Code Jan 05, 2024 pm 06:08 PM

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

How to use insertBefore in javascript How to use insertBefore in javascript Nov 24, 2023 am 11:56 AM

Usage: In JavaScript, the insertBefore() method is used to insert a new node in the DOM tree. This method requires two parameters: the new node to be inserted and the reference node (that is, the node where the new node will be inserted).

JavaScript and WebSocket: Building an efficient real-time image processing system JavaScript and WebSocket: Building an efficient real-time image processing system Dec 17, 2023 am 08:41 AM

JavaScript is a programming language widely used in web development, while WebSocket is a network protocol used for real-time communication. Combining the powerful functions of the two, we can create an efficient real-time image processing system. This article will introduce how to implement this system using JavaScript and WebSocket, and provide specific code examples. First, we need to clarify the requirements and goals of the real-time image processing system. Suppose we have a camera device that can collect real-time image data

See all articles