nodejs 构建高性能服务器的关键技术

nodejs 构建高性能服务器的关键技术

  1. 演示地址 演示地址
  2. 源码地址 源码地址
  3. 获取更多 获取更多
  • 在现代 Web 开发中,Node.js 已成为构建高性能、可扩展网络应用的首选平台之一。它的非阻塞 I/O 模型与事件驱动架构使其能够在处理大量并发请求时表现出色,尤其适合构建实时应用,如聊天系统、数据流处理等。这篇博客将介绍 Node.js 的核心特性、常用模块以及如何利用其优势来开发高效的服务器端应用。

什么是 Node.js?

  • Node.js 是一个基于 Chrome V8 JavaScript 引擎 的 JavaScript 运行时。它允许开发者使用 JavaScript 编写服务器端代码,而不仅仅是前端代码。与传统的多线程 Web 服务器(如 Apache、Tomcat)不同,Node.js 采用 单线程、事件驱动 的架构,这使它能够有效处理高并发请求。

Node.js 的核心特点

  1. 事件驱动、非阻塞 I/O
    Node.js 最大的特点是 非阻塞 I/O,也就是在进行 I/O 操作时(如读取文件、数据库查询或 HTTP 请求),它不会阻塞主线程,而是通过 事件循环 和 回调函数 来处理。这使得即使在 I/O 密集型场景下,Node.js 也能保持高效的响应。
const fs = require('fs');fs.readFile('example.txt', 'utf8', (err, data) => {if (err) throw err;console.log(data);
});console.log('This will print first!');
  1. 单线程,但高并发
  • 虽然 Node.js 是单线程的,但它通过 libuv 库将一些复杂的操作交给底层线程池处理,如文件读写、网络请求等。这种模型使 Node.js 在处理大量并发请求时拥有极高的性能,避免了传统多线程 Web 服务器因上下文切换而导致的性能损耗。

nodejs 架构图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • Node.js 架构的核心是 事件驱动、非阻塞 I/O,它利用了 事件循环(Event Loop) 来处理 I/O 操作,实现高效的并发处理。主要组件包括:
  1. V8 引擎:这是 Google 的 JavaScript 引擎,负责解析和执行 JavaScript 代码。
  2. libuv:Node.js 使用的库,支持事件驱动、异步 I/O 操作,主要处理文件系统、网络、DNS、以及定时器等。
  3. 事件循环(Event Loop):Node.js 的心脏,管理和调度 I/O 事件,使其可以通过单线程处理多任务。
  4. 回调队列(Callback Queue):事件循环将完成的异步任务的回调函数放入回调队列中,逐一执行。
  5. 线程池:尽管 Node.js 是单线程的,但底层通过 libuv 维护一个线程池,用来处理 CPU 密集型任务。

常见全局变量

  1. __dirname
  • 表示当前执行的脚本所在目录的绝对路径。
console.log(__dirname);
  1. __filename
  • 表示当前执行的脚本文件的绝对路径。
console.log(__filename);
  1. global
  • global 是 Node.js 的全局对象,类似于浏览器中的 window 对象。
  • 任何挂载到 global 的属性或方法都可以在整个应用中访问。
global.myVar = 'Hello, World!';
console.log(global.myVar); // 输出: Hello, World!
  1. process
  • process 对象提供有关当前 Node.js 进程的信息以及控制进程的方法。它包含关于环境、命令行参数、标准输入输出流等信息。
console.log(process.version); // Node.js 的版本
console.log(process.env); // 环境变量
console.log(process.argv); // 命令行参数
  1. Buffer
  • Buffer 对象用于处理二进制数据流,特别是在处理文件或网络数据时非常有用。
const buf = Buffer.from('Hello, World!');
console.log(buf.toString()); // 输出: Hello, World!
  1. setTimeout()
  • 用于延迟执行代码。与浏览器中的 setTimeout 一样,但在 Node.js 中,这是全局函数,不需要引入任何模块。
setTimeout(() => {console.log('Executed after 1 second');
}, 1000);
  1. setInterval
  • 用于定时执行代码。与 setTimeout() 类似,但它会以固定的时间间隔重复执行。
setInterval(() => {console.log('Repeated every 2 seconds');
}, 2000);
  1. clearTimeout
  • 用于取消由 setTimeout() 创建的定时器。
const timer = setTimeout(() => {console.log('This will not be logged');
}, 5000);clearTimeout(timer);
  1. clearInterval
  • 用于取消由 setInterval() 创建的定时器。
const interval = setInterval(() => {console.log('This will not repeat');
}, 2000);clearInterval(interval);
  1. require()
  • require() 函数用于引入模块。它是 CommonJS 模块系统的一部分。
const fs = require('fs');
  1. module
  • module 对象表示当前模块本身。它包含关于模块的信息,比如 module.exports 属性,它用于导出模块的内容。
console.log(module.exports); // 打印导出的内容
  1. exports
  • exports 是 module.exports 的快捷方式,用于导出模块的属性或方法。
exports.myFunction = function () {return 'Hello!';
};
  1. console
  • 提供与控制台输出相关的方法,如 console.log()、console.error()、console.warn() 等。
console.log('This is a log message');
console.error('This is an error message');

path 常用方法

  • path 模块是 Node.js 的核心模块之一,提供了处理和转换文件路径的实用方法。它能够帮助开发者跨平台地处理文件路径问题,因为不同操作系统的路径分隔符不同(Windows 使用 \,而 POSIX 系统(如 Linux 和 macOS)使用 /)。
  1. path.basename(p[, ext])
  • 作用:返回路径的最后一部分,也就是文件名。如果提供了 ext 参数,会从结果中移除这个扩展名。
  • 参数:
  1. p: 文件路径。
  2. ext: 可选,文件扩展名(若提供此参数,会从返回值中移除它)。
const path = require('path');
const filePath = '/user/local/bin/file.txt';
console.log(path.basename(filePath)); // 输出: file.txt
console.log(path.basename(filePath, '.txt')); // 输出: file
  1. path.dirname§
  • 作用:返回路径的目录部分。

  • 参数:

  • p: 文件路径。

const path = require('path');
const filePath = '/user/local/bin/file.txt';
console.log(path.dirname(filePath)); // 输出: /user/local/bin
  1. path.extname§
  • 作用:返回路径中文件的扩展名。
  • 参数:
  • p: 文件路径。
const path = require('path');
const filePath = '/user/local/bin/file.txt';
console.log(path.extname(filePath)); // 输出: .txt
  1. path.join([…paths])
  • 作用:使用平台特定的分隔符将所有给定的路径片段连接在一起,并规范化生成的路径。
const path = require('path');
const joinedPath = path.join('/user', 'local', 'bin/file.txt');
console.log(joinedPath); // 输出: /user/local/bin/file.txt
  1. path.resolve([…paths])
  • 作用:将路径或路径片段解析为绝对路径。如果没有给定路径片段,则使用当前工作目录。
const path = require('path');const absolutePath = path.resolve('file.txt');
console.log(absolutePath);const resolvedPath = path.resolve('/user', 'local', 'bin/file.txt');
console.log(resolvedPath);
  1. path.normalize§
  • 作用:规范化给定的路径,解析 … 和 . 片段,并移除多余的斜杠。
  • 参数:
  • p: 需要规范化的路径。
const path = require('path');
const normalizedPath = path.normalize('/user//local/../bin/file.txt');
console.log(normalizedPath);
  1. path.isAbsolute§
  • 作用:判断给定路径是否为绝对路径。
  • 参数:
  • p: 文件路径。
  • 返回:布尔值,表示路径是否是绝对路径。
const path = require('path');
console.log(path.isAbsolute('/user/local/bin')); // 输出: true
console.log(path.isAbsolute('file.txt')); // 输出: false
  1. path.relative(from, to)
  • 作用:根据两个给定的路径,返回相对路径。
  • 参数:
  • from: 起始路径。
  • to: 目标路径。
const path = require('path');
const fromPath = '/user/local/bin';
const toPath = '/user/local/lib/file.txt';
console.log(path.relative(fromPath, toPath)); // 输出: ../lib/file.txt
  1. path.parse§
  • 作用:将路径解析为一个对象,包含 root、dir、base、ext 和 name 属性。
  • 参数:
  • p: 文件路径。
  • 返回:一个对象,包含路径的各个部分。
const path = require('path');
const filePath = '/user/local/bin/file.txt';
const parsedPath = path.parse(filePath);
console.log(parsedPath);
//-------------------------------------
{root: '/',dir: '/user/local/bin',base: 'file.txt',ext: '.txt',name: 'file'
}
  1. path.format(pathObject)
  • 作用:将 path.parse() 返回的对象重新组合为路径。
  • 参数:
  • pathObject: 包含路径信息的对象,类似 path.parse() 的输出。
const path = require('path');
const pathObject = {root: '/',dir: '/user/local/bin',base: 'file.txt',ext: '.txt',name: 'file',
};
const formattedPath = path.format(pathObject);
console.log(formattedPath); // 输出: /user/local/bin/file.txt

Buffer 模块

  • 在 Node.js 中,Buffer 是处理二进制数据的核心模块。它在网络通信、文件读写等场景中非常常用,特别是在处理像 TCP 数据流、文件 I/O 以及其他没有明确编码的原始数据时。
  • 与浏览器 JavaScript 不同,Node.js 中的 Buffer 类可以直接处理和存储二进制数据,且在引入了 TypedArray 之前,这是 Node.js 中唯一可用的处理原始字节的方式。
  1. Buffer.alloc(size[, fill[, encoding]])
  • 作用:分配一个大小为 size 的缓冲区,并用 fill 填充该缓冲区。encoding 是填充时的编码,默认为 ‘utf8’。
const buf = Buffer.alloc(10);
const bufFilled = Buffer.alloc(10, 'a');
console.log(bufFilled.toString());
  1. Buffer.from(array)
  • 作用:将数组、字符串或其他对象转换为 Buffer。
const bufFromArray = Buffer.from([1, 2, 3]);
console.log(bufFromArray); // 输出: <Buffer 01 02 03>const bufFromString = Buffer.from('Hello, World!', 'utf8');
console.log(bufFromString); // 输出: <Buffer
  • 作用:将 Buffer 中的数据解码为字符串。默认使用 utf8 编码,可以指定起始和结束位置。
const buf = Buffer.from('Hello, World!', 'utf8');
console.log(buf.toString()); // 输出: Hello, World!
console.log(buf.toString('utf8', 0, 5)); // 输出: Hello
  1. buf.write(string[, offset[, length]][, encoding])
  • 作用:将 string 写入 Buffer。offset 是从 Buffer 的哪个位置开始写入,length 是写入的字节数,encoding 是编码格式,默认是 ‘utf8’。
const buf = Buffer.alloc(10);
buf.write('Hello', 0, 'utf8');
console.log(buf.toString()); // 输出: Hello
  1. Buffer.concat(list[, totalLength])
  • 作用:合并多个 Buffer 为一个 Buffer。list 是要合并的 Buffer 数组,totalLength 是合并后 Buffer 的总长度。
const buf1 = Buffer.from('Hello,');
const buf2 = Buffer.from('World!');const combinedBuf = Buffer.concat([buf1, buf2]);
console.log(combinedBuf.toString());
  1. Buffer.byteLength(string[, encoding])
  • 作用:返回给定字符串的字节长度。
const str = 'hello world';
console.log(Buffer.byteLength(str));
  1. buf.slice([start[, end]])
  • 作用:返回 Buffer 的一个片段,类似于数组的 slice() 方法。
const buf = Buffer.from('Hello, World!', 'utf8');
const sliceBuf = buf.slice(0, 5);
console.log(sliceBuf.toString()); // 输出: Hello
  1. buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
  • 作用:将当前 Buffer 的内容复制到目标 Buffer。
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.alloc(5);
buf1.copy(buf2);
console.log(buf2.toString()); // 输出: Hello
  1. buf.equals(otherBuffer)
  • 作用:比较两个 Buffer 的内容是否相同。
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('ABC');
const buf3 = Buffer.from('DEF');console.log(buf1.equals(buf2)); // 输出: true
console.log(buf1.equals(buf3)); // 输出: false
  1. buf.indexOf(value[, byteOffset][, encoding])
  • 作用:查找 Buffer 中的某个值,返回其首次出现的位置,如果没有找到则返回 -1。
const buf = Buffer.from('Hello, World!', 'utf8');
console.log(buf.indexOf('World')); // 输出: 7
console.log(buf.indexOf('XYZ')); // 输出: -1
  1. buf.fill(value[, offset[, end]][, encoding])
  • 作用:用指定值填充 Buffer 的内容。
const buf = Buffer.alloc(10);
buf.fill('a');
console.log(buf.toString()); // 输出: aaaaaaaaaa

fs 常用方法

  • fs 模块是 Node.js 提供的核心模块之一,用于处理文件系统相关操作。它提供了同步和异步方法,支持文件的读写、文件夹操作、文件权限修改等功能
  1. fs.readFile(path, [options], callback)
  • 作用:异步读取文件的全部内容。
  • 参数:
  1. path: 文件路径。
  2. options: 可选,指定编码或返回格式(默认为 Buffer)。
  3. callback: 回调函数,传递 (err, data)
const fs = require('fs');fs.readFile('data.txt', 'utf-8', (err, data) => {if (err) throw err;console.log(data);
});
  1. fs.readFileSync(path, [options])
  • 作用:同步读取文件的全部内容。返回读取到的数据。
  • 参数:
  • path: 文件路径。
  • options: 可选,指定编码或返回格式。
const fs = require('fs');
const data = fs.readFileSync('data.txt', 'utf-8');
console.log('data', data);
  1. fs.writeFile(file, data, [options], callback)
  • 作用:异步写入数据到文件,如果文件不存在会创建文件。
  • 参数:
  1. file: 文件路径。
  2. data: 要写入的数据。
  3. options: 可选,指定编码。
  4. callback: 回调函数,传递 (err)。
const fs = require('fs');
fs.writeFile('data.txt', 'change info', (err) => {if (err) throw err;console.log('file hash been write');
});
  1. fs.writeFileSync(file, data, [options])
  • 作用:同步写入数据到文件。
const fs = require('fs');
fs.writeFileSync('data.txt', 'change info', 'utf-8');
console.log('file has been written');
  1. fs.appendFile(file, data, [options], callback)
  • 作用:异步向文件追加数据。如果文件不存在则创建文件。
const fs = require('fs');
fs.appendFile('data.txt', 'this is appended txt.\n', (err) => {if (err) throw err;console.log('Data append to file');
});
  1. fs.appendFileSync(file, data, [options])
  • 作用:同步向文件追加数据。
const fs = require('fs');
fs.appendFileSync('data.txt', 'This is appended text.\n');
console.log('Data appended to file.');
  1. fs.rename(oldPath, newPath, callback)
  • 作用:异步重命名文件或文件夹。
  • 参数:
  • oldPath: 旧路径。
  • newPath: 新路径。
  • callback: 回调函数,传递 (err)。
const fs = require('fs');fs.rename('file.txt', 'file1.txt', (err) => {if (err) throw err;console.log('Rename complete.');
});
  1. fs.renameSync(oldPath, newPath)
  • 作用:同步重命名文件或文件夹。
const fs = require('fs');fs.renameSync('file1.txt', 'file.txt');
console.log('Rename complete.');
  1. fs.unlink(path, callback)
  • 作用:异步删除文件。
  • 参数:
  1. path: 文件路径。
  2. callback: 回调函数,传递 (err)。
const fs = require('fs');
fs.unlink('file.txt', (err) => {if (err) throw err;console.log('file delete');
});
  1. fs.unlinkSync(path)
  • 作用:同步删除文件
const fs = require('fs');
fs.unlinkSync('file.txt');
console.log('file delete');
  1. fs.readdir(path, [options], callback)
  • 作用:异步读取指定目录的内容,返回文件和子目录的数组。
  • 参数:
  1. path: 目录路径。
  2. options: 可选,encoding 或 withFileTypes(是否返回 Dirent 对象)。
  3. callback: 回调函数,传递 (err, files)。
const fs = require('fs');fs.readdir('./', (err, files) => {if (err) throw err;console.log(files); // 输出文件和目录的列表
});
  1. fs.readdirSync(path, [options])
  • 作用:同步读取目录内容。
const fs = require('fs');
const files = fs.readdirSync('./');
console.log(files);
  1. fs.mkdir(path[, options], callback)
  • 作用:异步创建目录。
  • 参数:
  1. path: 要创建的目录路径。
  2. options: 可选,是否递归创建,或设置权限模式。
  3. callback: 回调函数,传递 (err)。
const fs = require('fs');fs.mkdir('test', (err) => {if (err) throw err;console.log('Directory created.');
});
  1. fs.mkdirSync(path[, options])
  • 作用:同步创建目录。
const fs = require('fs');
fs.mkdirSync('test');
console.log('Directory created.');
  1. fs.rmdir(path[, options], callback)
  • 作用:异步删除目录。该目录必须为空。
  • 参数:
  1. path: 目录路径。
  2. options: 可选,recursive: true 表示递归删除非空目录(实验性功能)。
  3. callback: 回调函数,传递 (err)。
const fs = require('fs');
fs.rmdir('test', (err) => {if (err) throw err;console.log('directory deleted.');
});
  1. fs.rmdirSync(path[, options])
  • 作用:同步删除目录。
const fs = require('fs');
fs.rmdirSync('new_directory');
console.log('Directory deleted.');
  1. fs.stat(path, callback)
  • 作用:异步获取文件或目录的状态信息,返回 fs.Stats 对象。
  • 参数:
  1. path: 文件或目录路径。
  2. callback: 回调函数,传递 (err, stats)。
const fs = require('fs');
fs.stat('file.txt', (err, stats) => {if (err) throw err;console.log(stats);
});
  1. fs.statSync(path)
  • 作用:同步获取文件或目录的状态信息。
const fs = require('fs');
const stats = fs.statSync('example.txt');
console.log(stats);
  1. fs.existsSync(path)
  • 作用:同步检查文件或目录是否存在(注意:该方法已废弃,推荐使用 fs.access())。
const fs = require('fs');if (fs.existsSync('file.txt')) {console.log('File exists.');
}
  1. fs.access(path[, mode], callback)
  • 作用:检查文件或目录的权限。mode 可以用来检查读、写或执行权限。
  • 参数:
  1. path: 文件路径。
  2. mode: 可选,文件权限检查。
  3. callback: 回调函数,传递 (err)。
const fs = require('fs');fs.access('example.txt', fs.constants.R_OK | fs.constants.W_OK, (err) => {console.log(err ? 'No access!' : 'File can be read and written.');
});

vm 模块

  • Node.js 提供了许多强大的内置模块,其中的 vm 模块(Virtual Machine,虚拟机)特别值得关注。它允许我们在独立的上下文中执行 JavaScript 代码,这在某些场景中非常有用,比如执行不信任的代码、沙箱化运行环境等。
  1. 什么是 vm 模块
  • vm 模块允许在 Node.js 中创建沙箱化的虚拟机上下文,运行的 JavaScript 代码可以隔离在单独的上下文中,避免对主应用环境产生副作用。使用 vm 模块,可以执行动态代码,而无需担心代码直接影响主线程或全局环境。
  1. vm.runInThisContext()
  • vm.runInThisContext() 方法类似于 eval(),但执行的代码是在与当前上下文分离的环境中执行的,且无法访问主上下文的变量。
const vm = require('vm');
const code = `var x=10;x += 5`;
const result = vm.runInThisContext(code);
console.log('result', result);
  1. vm.runInNewContext()
  • vm.runInNewContext() 可以在全新的上下文中执行代码,可以指定上下文的对象,用作代码执行时的全局对象。
const vm = require('vm');const context = { x: 1 };
vm.runInNewContext('x += 40;', context);
console.log(context.x); // 输出 41
  • 在这里,代码是在新的上下文中执行的,并且 context 对象被当作全局对象传入执行环境中。
  1. vm.createContext()
  • vm.createContext() 用于创建一个新的上下文对象。在这个上下文中,可以安全地执行代码。
const vm = require('vm');const sandbox = { animal: 'cat', count: 2 };
const context = vm.createContext(sandbox);
vm.runInContext('count += 1; name = "Tom";', context);console.log(sandbox);
  • 此方法适用于在创建的上下文中运行复杂的代码,同时可以对上下文对象进行控制。
  1. vm.Script()
  • vm.Script() 可以将代码编译为一个可执行的脚本对象,并且可以多次执行该脚本。
const vm = require('vm');const script = new vm.Script(`count += 1;name="tom"`);
const sandbox = { count: 0 };
const context = vm.createContext(sandbox);script.runInContext(context);
console.log(sandbox);// 输出 { count: 2, name: 'Jerry' }
  • vm.Script() 的优势在于,可以多次执行同一个编译后的代码,避免重复编译带来的性能开销

事件模块 (events) 详解

  • 在 Node.js 中,事件驱动架构是其核心之一。events 模块是用于管理和触发事件的内置模块,提供了一种实现 观察者模式 的机制。通过事件模块,开发者可以定义事件、绑定事件处理函数,并在合适的时候触发这些事件。
  1. 事件驱动模型简介
  • Node.js 的核心架构基于事件驱动模型。与传统的多线程模型不同,Node.js 使用 单线程、异步 I/O 和 事件循环 来处理并发。所有的 I/O 操作(如网络请求、文件读写等)都是异步的,完成后会通过事件通知回调函数,从而使代码可以继续执行其他任务,而不会被阻塞。
  1. 监听事件
  • 可以使用 on() 方法为事件绑定监听器。监听器函数会在事件触发时执行。
const EventEmitter = require('events');
const emitter = new EventEmitter();emitter.on('greet', () => {console.log('Hello world');
});emitter.emit('greet');
  • 在这个例子中,我们使用 on() 方法监听了 greet 事件,当使用 emit() 方法触发该事件时,绑定的处理函数会执行。
  1. 移除监听器
    可以使用 removeListener() 或 off() 方法移除某个特定事件的监听器。
const EventEmitter = require('events');
const emitter = new EventEmitter();emitter.on('greet', () => {console.log('Hello, World!');
});const callback = () => console.log('This will not run');
emitter.on('removeEvent', callback);emitter.removeListener('removeEvent', callback);
emitter.emit('removeEvent'); // 无输出

http 模块详解

  • Node.js 的核心特性之一是其内置的 HTTP 模块。通过 http 模块,开发者可以轻松创建 HTTP 服务器和客户端,从而实现 Web 应用、API 服务或其他网络应用。http 模块是 Node.js 中处理网络请求的基础,它是基于事件驱动的,支持异步处理。
  1. HTTP 模块简介
  • Node.js 内置的 http 模块提供了创建 HTTP 服务器和客户端的功能。与浏览器端的 HTTP 请求不同,Node.js 的 http 模块允许服务器端代码主动监听并处理请求。
  1. 创建 HTTP 服务器
const http = require('http');const server = http.createServer((req, res) => {res.statusCode = 200;res.setHeader('Content-Type', 'text/plain');res.end('Hello World\n');
});server.listen(3000, () => {console.log('Server running at http://127.0.0.1:3000/');
});
  1. http.createServer([requestListener])
  • http.createServer() 方法用于创建 HTTP 服务器。requestListener 是一个回调函数,每当服务器接收到 HTTP 请求时,都会调用该回调函数。回调函数的两个参数是:
    req:代表 HTTP 请求的对象。
    res:代表 HTTP 响应的对象。
  1. 监听请求
  • 通过 server.listen() 方法,服务器可以开始监听指定的端口(如 3000),当有 HTTP 请求到达时,requestListener 会被触发。
  1. 发送响应
  • 在回调函数中,我们可以通过 res.writeHead() 设置响应状态码和响应头,使用 res.end() 结束响应并返回数据。
  1. 处理查询参数
  • 在处理 URL 时,可能需要解析 URL 中的查询参数(如 ?name=John&age=30)。Node.js 内置了 url 模块来帮助解析 URL 和查询参数。
const url = require('url');const server = http.createServer((req, res) => {const parsedUrl = url.parse(req.url, true);const query = parsedUrl.query;res.statusCode = 200;res.setHeader('Content-Type', 'application/json');res.end(JSON.stringify(query)); // 返回解析后的查询参数
});server.listen(3000);
  1. 使用 HTTP 客户端
  • 除了创建 HTTP 服务器,Node.js 的 http 模块还可以用作 HTTP 客户端,发送 HTTP 请求。
const http = require('http');const options = {hostname: 'example.com',port: 80,path: '/',method: 'GET',
};const req = http.request(options, (res) => {let data = '';res.on('data', (chunk) => {data += chunk;});res.on('end', () => {console.log('Response:', data);});
});req.on('error', (error) => {console.error('Error:', error);
});req.end();
  • 在这个例子中,http.request() 用于发起 HTTP 请求,设置请求选项(如 hostname、port、path 等),并处理服务器返回的响应。
  1. 支持
  • 对于安全通信,Node.js 提供了 https 模块。它的用法与 http 模块类似,但支持 SSL/TLS 加密。需要将 http 替换为 https。
const https = require('https');https.get('https://example.com', (res) => {let data = '';res.on('data', (chunk) => {data += chunk;});res.on('end', () => {console.log('Response:', data);});
});

联系作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1556095.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【C++11】新特性

前言&#xff1a; C11 是C编程语言的一个重要版本&#xff0c;于2011年发布。它带来了数量可观的变化&#xff0c;包含约 140 个新特性&#xff0c;以及对 C03 标准中约600个缺陷的修正&#xff0c;更像是从 C98/03 中孕育出的新语言 列表初始化 C11 中的列表初始化&#xff0…

【自用】王道文件管理强化笔记

文章目录 操作系统引导:磁盘初始化文件打开过程角度1文件的打开过程角度2 内存映射的文件访问 操作系统引导: ①CPU从一个特定主存地址开始&#xff0c;取指令&#xff0c;执行ROM中的引导程序(先进行硬件自检&#xff0c;再开机) ②)将磁盘的第一块–主引导记录读入内存&…

谷粒商城のRabbitMQ基础篇

文章目录 前言一、Rabbit MQ简介1、基本概念2、组件架构 二、使用步骤1.引入依赖2.application.properties3、docker 安装Rabbit MQ3、使用案例3.1、定义队列3.2、定义交换机3.3、绑定3.4、发送消息3.5、接受消息3.5、自定义消息序列化方式3.6、演示Fanout 交换机模式3.7、演示…

Vue基础(二)

计算属性与监视姓名案例 插值语法实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>姓名案例&l…

用人工智能写作:专业作家利用 ChatGPT 的五种方式 ✍️

用人工智能写作&#xff1a;专业作家利用 ChatGPT 的五种方式 &#x1f3a8;✍️ 在写作领域&#xff0c;人工智能工具如 ChatGPT 正逐渐成为作家们的得力助手。它不仅帮助优化文本&#xff0c;还能激发灵感、完善叙事结构&#xff0c;甚至推动创新。本文将通过五个具体案例&a…

【微服务】服务注册与发现 - Eureka(day3)

CAP理论 P是分区容错性。简单来说&#xff0c;分区容错性表示分布式服务中一个节点挂掉了&#xff0c;并不影响其他节点对外提供服务。也就是一台服务器出错了&#xff0c;仍然可以对外进行响应&#xff0c;不会因为某一台服务器出错而导致所有的请求都无法响应。综上所述&…

实验4 循环结构

1、判断素数 【问题描述】从键盘输入一个大于1的正整数&#xff0c;判断是否为素数 【输入形式】输入一个正整数 【输出形式】输出该数是否为素数 【样例输入】10 【样例输出】10 is not a prime number 【样例说明】样例2 输入&#xff1a;-10 输出&#xff1a;error! #de…

jmeter学习(7)beanshell

beanshell preprocessor 发送请求前执行 beanshell postprocessor 发送请求前执行 获取请求相关信息 String body sampler.getArguments().getArgument(0).getValue(); String url sampler.getPath(); 获取响应报文 String responseprev.getResponseDataAsString(); 获…

北京自闭症寄宿学校大盘点:优质教育资源汇总

北京自闭症寄宿学校大盘点&#xff1a;优质教育资源中的璀璨明珠——兼谈广州星贝育园 在北京&#xff0c;随着社会对自闭症儿童教育的日益重视&#xff0c;越来越多的优质寄宿学校应运而生&#xff0c;为这些特殊的孩子提供了专业的康复与教育环境。然而&#xff0c;当我们把…

【数据结构】【链表代码】随机链表的复制

/*** Definition for a Node.* struct Node {* int val;* struct Node *next;* struct Node *random;* };*/typedef struct Node Node; struct Node* copyRandomList(struct Node* head) {if(headNULL)return NULL;//1.拷贝结点&#xff0c;连接到原结点的后面Node…

猫头虎深度解读:过去2周,AI领域的十大突破事件与未来展望

猫头虎深度解读&#xff1a;过去2周&#xff0c;AI领域的十大突破事件与未来展望 &#x1f680;&#x1f916; 大家好&#xff0c;我是猫头虎技术团队的代表&#xff01;这两周&#xff0c;人工智能领域再次掀起了技术与应用的新浪潮。从立法到技术进展&#xff0c;再到前沿应…

初始爬虫12(反爬与反反爬)

学到这里&#xff0c;已经可以开始实战项目了&#xff0c;多去爬虫&#xff0c;了解熟悉反爬&#xff0c;然后自己总结出一套方法怎么做。 1.服务器反爬的原因 服务器反爬的原因 总结&#xff1a; 1.爬虫占总PV较高&#xff0c;浪费资源 2.资源被批量抓走&#xff0c;丧失竞争力…

交叉熵的数学推导和手撕代码

交叉熵的数学推导和手撕代码 数学推导手撕代码 数学推导 手撕代码 import torch import torch.nn.functional as F# 二元交叉熵损失函数 def binary_cross_entropy(predictions, targets):# predictions应为sigmoid函数的输出&#xff0c;即概率值# targets应为0或1的二进制标…

MathType软件7.7最新版本下载安装教程+使用深度评测

嘿&#xff0c;各位亲爱的朋友们&#xff01;&#x1f44b; 今天我要来给大家安利一个神器——MathType软件&#xff01;&#x1f389; 如果你是一位学生、老师或者需要经常和数学公式打交道的科研工作者&#xff0c;那这个软件绝对是你的不二选择&#xff01;&#x1f60e; M…

ctf.bugku-备份是个好习惯

访问页面得到字符串 这串字符串是重复的&#xff1b; d41d8cd98f00b204e9800998ecf8427e 从前端、源码上看&#xff0c;除了这段字符串&#xff0c;没有其他信息&#xff1b;尝试解密&#xff0c;长度32位&#xff1b;各种解密方式试试&#xff1b; MD5免费在线解密破解_MD5在…

市面上8款AI论文大纲一键生成文献的软件推荐

在当前的学术研究和写作领域&#xff0c;AI论文大纲自动生成软件已经成为提高写作效率和质量的重要工具。这些工具不仅能够帮助研究人员快速生成论文草稿&#xff0c;还能进行内容优化、查重和排版等操作。本文将分享市面上8款AI论文大纲一键生成文献的软件&#xff0c;并特别推…

[git] github管理项目之环境依赖管理

导出依赖到 requirements.txt pip install pipreqs pipreqs . --encodingutf8 --force但是直接使用pip安装不了torch&#xff0c;需要添加源&#xff01;&#xff01; pip install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.htmlpython 项目中 …

Stable Diffusion绘画 | AI 图片智能扩充,超越PS扩图的AI扩图功能(附安装包)

来到「文生图」页面&#xff0c;输入固定的起手式提示词。 第1步&#xff0c;开启 ControlNet&#xff0c;将需要扩充的图片加载进来&#xff1a; 控制类型选择「Inpaint」&#xff0c;预处理器选择「inpaint_onlylama」&#xff0c;缩放模式选择「缩放后填充空白」&#xff1…

【数据结构】【链表代码】移除链表元素

移除链表元素 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* removeElements(struct ListNode* head, int val) { // 创建一个虚拟头节点&#xff0c;以处理头节点可能被删除的情况 struct…

代码随想录Day54

今天是国庆假期后的恢复做题的第一天&#xff0c;摆了那么久感觉还是有点没摆够哈哈哈哈&#xff01;今天两道题都是困难题&#xff0c;两道题都去看讲解了&#xff0c;感觉这两道题是高度相似的&#xff0c;接雨水用单调递增栈来做&#xff0c;柱状图中最大的矩形用单调递减栈…