当前位置: 首页 > news >正文

Node.js技术原理分析系列——Node.js调试能力分析

本文由体验技术团队屈金雄原创。

Node.js 是一个开源的、跨平台的 JavaScript 运行时环境,它允许开发者在服务器端运行 JavaScript 代码。Node.js 是基于 Chrome V8引擎构建的,专为高性能、高并发的网络应用而设计,广泛应用于构建服务器端应用程序、网络应用、命令行工具等。

本系列将分为9篇文章为大家介绍 Node.js 技术原理:从调试能力分析到内置模块新增,从性能分析工具 perf_hooks 的用法到 Chrome DevTools 的性能问题剖析,再到 ABI 稳定的理解、基于 V8 封装 JavaScript 运行时、模块加载方式探究、内置模块外置以及 Node.js addon 的全面解读等主题,每一篇都干货满满。

本文内容为本系列第1篇,以下为正文内容。

inspector 是什么

直接取官方文档中,对 inspector 的定义:

The node:inspector module provides an API for interacting with the V8 inspector.

翻译过来就是,inspector 模块提供了一组用于和 V8 inspector 交互的 API 。

解读:

  • node inspector 是 Node.js 内置模块
  • node inspector 仅提供与 V8 inspector 交互的能力,其本身并没有调试能力
  • Node.js 调试能力来自 V8 inspector

Node.js 调试原理

调试的目的是通过观察运行时数据来定位问题。Node.js 的运行时数据由 V8 引擎管理,为了实现调试功能,V8封装了一套 api 供外部查看运行时数据,这套 api 名字就是 V8 inspector(运行时是一个 websocket 服务)。V8 inspector 由于调试协议不同,不能直接与 Chrome DevTools 交互,于是 Node.js 提供了 inspector 模块,运行时也会启动一个 websocket 服务,用于适配。

在这里插入图片描述

如图所示,进入 Node.js 调试模式前,主线程需要创建一个 debugger server( websocket 服务,即时通讯服务,也即 node inspector ),用来实现 debugger client(例如 vscode 调试器或 Chrome DevTools ) 与 V8 inspector 通信,V8 inspector 再获取 Node.js 服务的数据,最终实现单步调试等功能。

经过封装与简化后,launch 模式启动调试时我们甚至感知不到 debugger server 了,但是它一定是存在的。

深入分析 – inspect 参数

分析过程中,我对相关源码做了粗读,除了源码本身,还参考了这篇文章:https://theanarkh.github.io/understand-nodejs/chapter24-Inspector/#11

本文使用的 Node.js 源码是 18.20.2

在这里插入图片描述

如上图所示,表示的是 Node.js 调试模式启动过程,大部分节点都是中文表述+函数名。

当我们用 node --inspect test.js 启动一个 js 脚本时,程序会启动 debugger server(一个 websocket 服务)。如上图所示,相关逻辑都在初始化 inspector 部分(蓝色节点),接下来细看一下这部分代码。

下图的起始节点 server.Start() 函数就是上图的末端节点 server.Start()。
在这里插入图片描述

图中每一个节点都对应一个函数。无需理解所有节点,我们重点关注着色的几个节点。

1.第一个蓝色节点

当我们运行 node --inspect test.js 命令,可以看到如下打印,打印的内容 Node.js 开发者一定都很熟悉。

Debugger listening on ws://127.0.0.1:9229/43b86c7c-e538-4d5c-98ba-3f5196d8e986
For help, see: https://nodejs.org/en/docs/inspector// 这一行是Node开发者写的业务代码的打印
Server running at http://127.0.0.1:3000/

这个蓝色节点已经是启动代码执行的最后一步了,第一个橙色节点之后的部分在处理连接请求,也就是说,当代码走到第一个蓝色节点时,已经成功启动了一个 websocket 服务。

通过前面的代码还能看出,这个 websocket 服务在新起的子线程上运行,正因如此,调试程序才可以在主线程出现异常而崩溃的情况下,记录发送异常信息数据。

2.第一个橙色节点

注意这个节点代表一个回调函数,这个函数在服务启动时并没有执行。

它的执行是由 debugger client(例如 vscode 调试器或 Chrome DevTools )发起的 http 请求触发的,这次是client发起的第一次请求。

这次请求,对 vscode 调试器来说,就是它的 attach 模式( launch模式是把启动和连接操作合并了);对Chrome DevTools 来说,感觉上应该是通过轮询连接的,这个点暂时就不再深入研究了。

3.第二个橙色节点

client 紧接着会发第二次请求(未确认),请求头会携带 upgrade websocket 信息。这时会触发第二个橙色节点处的回调函数,当识别到是升级请求时,debugger server 才真正升级为 websocket 服务。

4.第二个蓝色节点

升级完成后,控制台会打印“Debugger attached.”,这也是我们调试时常见的控制台打印信息。

接下来,debugger server 就可以正常处理业务请求了。

5.特别关注一下红色节点

这里的代码就可以看出,debugger client 与 debugger server 建立连接的过程中,debugger server 与 V8 inspector 建立了连接。

其实整个初始化 inspector(启动 debugger server )的过程,是一套完整 websocket 实现,可以作为一个整体来看待。早期 Socket.io 模块是内置在 Node.js 中的。

– inspect-brk 参数

–inspect-brk 命令,可以在用户代码启动前中断,相当于在用户代码的第一行打了个断点。

如下图所示,我们用 node --inspect-brk test.js 命令启动服务。可以看到,只有 debugger server 启动成功的提示,没有 node 服务启动成功的提示。这是因为在执行用户代码前停住了。

这个命令在我们想要研究或调试 node 代码启动,又不知道研究对象启动入口位置时,比较有用

在这里插入图片描述

启动 debugger server 后,我们用连接上,这时可以看到执行停在了业务代码的第一行,而这一行我们并没有设置断点,如下图所示。
在这里插入图片描述

– inspect-wait 参数

这是 node 20 版本新增的启动参数,用于等待调试器连接后再执行代码。这样就可以从执行一开始就开始调试。

Node.js 三种常见的调试方式

本节的介绍,没有像其他网络教程那样手把手,step by step 地写清楚操作步骤,是因为有讲调试原理。

初学者理解本节的前提是先看懂调试原理。

一、vscode 调试

vscode 调试是 Node.js 开发者最推荐的调试方式,因为可以一键启动调试模式,可以不用像 Chrome DevTools 调试那样起额外的窗口。

vscode 调试 Node.js 分为 launch 和 attach 两种模式,这里先介绍一下 launch 模式。

launch 模式调试 Node.js

1.创建一个 Node.js 服务,就是 test.js 文件,内容如下:

const { createServer } = require('node:http');const hostname = '127.0.0.1';
const port = 3000;const server = createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');res.end('Hello World');
});server.listen(port, hostname, async () => {console.log(`Server running at http://${hostname}:${port}/`);
});

2.在 Node.js 服务入口文件所在的目录,点击 create a launch.json file 按钮,然后选择 Node.js 选项(这是选择调试器),vscode 会自动创建一个 launch.json 文件。

在这里插入图片描述

launch.json 文件内容如下,本场景就直接用自动生成的不需要作任何改动。

configurations 下的 request 字段表示的就是我们前面提到的调试模式,默认使用 launch 模式;name 表示这一套配置的名称,默认名称是 Launch Program,下一步会用到该名称;program 表示项目启动的入口文件。更多调试配置参考 vscode官网

{// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{"type": "node","request": "launch","name": "Launch Program","skipFiles": [// "<node_internals>/**"],"program": "${workspaceFolder}\test.js"}]
}

如果用如上文件,屏蔽12行,设置了不跳过内部代码,还可以调试到Node.js的JS源码。

  1. 如下图所示,打断点,并选择 Launch Program,然后点击绿色三角,启动调试。

在这里插入图片描述

attach 模式调试 Node.js

顾名思义,这个模式不会触发 Node.js 和 debugger server 的启动,只会作为 debugger client 附加到已经启动的 Node.js 服务和debugger server 上。如果能理解前面讲的调试原理,这里就很好理解了。

1.首先我们要运行 node --inspect test.js,这是在启动 debugger server。

同时启动的还有 node 服务,也就是图中的 http://127.0.0.1:3000。

在这里插入图片描述

2.在 launch.json 文件中添加 attach 模式配置

port 字段表示要连接到的 debugger server 的端口号,也就是我们上一步的 9229。

address 字段表示 debugger server 的地址,也就是上一步的 ws://127.0.0.1;debugger server 在本地的话,可以省略该配置。

{// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{"type": "node","request": "launch","name": "Launch Program","skipFiles": ["<node_internals>/**"],"program": "${workspaceFolder}\test.js"},{"type": "node","request": "attach","name": "Attach Program","port": 9229,// "address": "localhost",},]
}

3.上一步添加完 Attach Program 配置后,多了一个启动选项,如下图所示。选择 Attach Program,然后点击绿色三角按钮,启动调试,即可连接上第一步启动的 debugger server。

在这里插入图片描述

远程调试

attach模式本地调试不常用,通常用于远程调试。目前vscode官方提供了两种远程调试方案:

  • 使用远程开发扩展包(官方推荐)

这个方案不仅能远程调试,还能用于远程开发,比如我们有时可能需要在本地Windows机器上编辑远程的Linux服务器上的项目。但是要安装一系列插件,有些复杂

  • attach模式连接远程 debugger server

在前文的attach模式配置中,加一个address字段,填上远程debugger server的IP地址即可。

二、Chrome DevTools 调试

当我们理解了 Node.js 调试原理,Chrome DevTools 调试就变得手到擒来。

1.首先我们还是要运行 node --inspect test.js,这是在启动 debugger server。

同时启动的还有 node 服务,也就是图中的 http://127.0.0.1:3000

在这里插入图片描述

2.接下来再打开 chrome 控制台,就能看见 Node.js 的图标。注意没有启动 debugger server 的时候,图标是不会出现的。点击它,就可以打开 Chrome DevTools。

在这里插入图片描述

3.首次打开 DevTools 时,需要在 Connection tab 页配置准备连接的 debugger server。

可以看到 DevTools 自带了两个地址,如果是 debugger server 是在本地启动,并且使用的是默认的 9229 端口,就不需要添加连接地址了。

在这里插入图片描述

4.DevTools 连接 debugger server

之前有过介绍,vscode 连接 debugger server 需要用 attach 模式启动调试。

DevTools 这边在完成配置后,不需要任何操作就能自动连上 debugger server。(大概)是因为 DevTools 会轮询所配置的地址。

连接成功后,会触发node服务打印“Debugger attached.”提示语。

在这里插入图片描述

5.开始调试

我们切到 Sources tab 页,发现已经有了要调试的代码。在需要的位置打断点,再触发断点,即可调试。

例如下图中,断点位置的代码是请求处理代码,我们只需要访问一下 http://127.0.0.1:3000 这个地址,即可触发断点。

在这里插入图片描述

三、命令行调试

命令行调试是没有客户端之前的方式,现在一般不用,但是如果需要在不方便使用前面介绍的两种方式的情况下,例如需要在服务器本地调试,可以用命令行调试。

我们把命令的双横杠去掉,也就是运行 node inspect test.js 命令,结果如下图所示:

我们进入到了Node.js的命令行调试模式,具体的用法参考官方文档的 Debug部分。

在这里插入图片描述

接下来贴一些常用命令用法:

步进#
  • cont, c:继续执行
  • next, n:下一步
  • step,s: 进入方法内部
  • out, o:退出当前方法
  • pause:暂停正在运行的代码(类似开发者工具中的暂停按钮)
断点#
  • setBreakpoint(), sb():在当前行设置断点
  • setBreakpoint(line), sb(line):在特定行设置断点
  • setBreakpoint(‘fn()’), sb(…):在函数主体的第一个语句上设置断点
  • setBreakpoint(‘script.js’, 1), sb(…):在第一行设置断点 script.js
  • setBreakpoint(‘script.js’, 1, ‘num < 4’), sb(…):在第一行设置条件断点script.js,仅当num < 4 计算结果为true
  • clearBreakpoint(‘script.js’, 1), cb(…):清除script.js 第一行的断点
信息#
  • backtrace, bt:打印当前调用栈

  • list(5):列出脚本源代码以及 5 行上下文(前后 5 行)

  • watch(expr):将表达式添加到观察列表,注意表达式需用引号括起来,如watch(“test2”)

  • unwatch(expr):从观察列表中删除表达式

  • unwatch(index):从观察列表中删除特定索引处的表达式

  • watchers:列出所有观察者及其值(每个断点上自动列出)

  • repl:打开调试器的 repl,在调试脚本的上下文中查看数据或表达式

  • exec expr, p expr:在调试脚本的上下文中执行表达式并打印其值

  • profile:启动 CPU profiling session

  • profileEnd:停止当前 CPU profiling session

  • profiles:列出所有已完成的 CPU profiling session

  • profiles[n].save(filepath = ‘node.cpuprofile’):将 CPU profiling session以 JSON 格式保存到磁盘

  • takeHeapSnapshot(filepath = ‘node.heapsnapshot’):获取堆快照并以 JSON 格式保存到磁盘

注意一下,repl命令可以进入断点所在上下文,方便地查看数据或表达式:

在这里插入图片描述

inspector 模块的 API

Node.js 的 inspector 模块提供了一组 API,用于在运行时与 V8 引擎进行交互,调试和分析 Node.js 应用程序。

这些 API 使开发者可以通过编程方式启动调试会话、设置断点、执行调试命令、收集性能数据等。

在这里插入图片描述

这里仅详细介绍两个方法:

1.inspector.Session 类的 post 方法可以向 v8 inspector 发送消息(指令),获取各种信息。v8 inspector 能识别的指令可以在 Chrome DevTools Protocol 中查看

贴一份官网的示例,对该类的能力可见一斑。

import { Session } from'node:inspector/promises';
import fs from'node:fs';
const session = newSession();
session.connect();await session.post('Profiler.enable');
await session.post('Profiler.start');
// Invoke business logic under measurement here...// some time later...
const { profile } = await session.post('Profiler.stop');// Write profile to disk, upload, etc.
fs.writeFileSync('./profile.cpuprofile', JSON.stringify(profile));

2.inspector.open方法可以在节点启动后,以编程方式启动debugger server。

vscode有个通过进程id,attach到没有用–inspect模式启动的node服务的能力,大概就是通过该接口实现的,暂未确认。

下一节,我们将讲解如何在Node.js中新增一个内置模块,请大家持续关注本系列内容~学习完本系列,你将获得:

  • 提升调试与性能优化能力
  • 深入理解模块化与扩展机制
  • 探索底层技术与定制化能力

关于OpenTiny

欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~
OpenTiny 官网:https://opentiny.design/
OpenTiny 代码仓库:https://github.com/opentiny/
TinyVue 源码:https://github.com/opentiny/tiny-vue
TinyEngine 源码: https://github.com/opentiny/tiny-engine
欢迎进入代码仓库 Star🌟TinyEngine、TinyVue、TinyNG、TinyCLI~ 如果你也想要共建,可以进入代码仓库,找到 good first issue标签,一起参与开源贡献~

相关文章:

Node.js技术原理分析系列——Node.js调试能力分析

本文由体验技术团队屈金雄原创。 Node.js 是一个开源的、跨平台的 JavaScript 运行时环境&#xff0c;它允许开发者在服务器端运行 JavaScript 代码。Node.js 是基于 Chrome V8引擎构建的&#xff0c;专为高性能、高并发的网络应用而设计&#xff0c;广泛应用于构建服务器端应…...

在Mac arm架构终端中运行 corepack enable yarn 命令,安装yarn

文章目录 1. 什么是 Corepack&#xff1f;2. 运行 corepack enable yarn 的作用3. 如何运行 corepack enable yarn4. 可能遇到的问题及解决方法问题 1&#xff1a;corepack 命令未找到问题 2&#xff1a;Yarn 未正确安装问题 3&#xff1a;权限问题 5. 验证 Yarn 是否启用成功6…...

蓝桥杯试题:计数问题

一、题目描述 试计算在区间 1 到 n的所有整数中&#xff0c;数字 x&#xff08;0≤x≤9&#xff09;x&#xff08;0≤x≤9&#xff09; 共出现了多少次&#xff1f; 例如&#xff0c;在 1 到 11 中&#xff0c;即在 1、2、3、4、5、6、7、8、9、10、11 中&#xff0c;数字 1 …...

数学建模与MATLAB实现:数据拟合全解析

引言 数据拟合是数学建模与实验分析中的核心任务&#xff0c;旨在通过数学模型逼近实际观测数据&#xff0c;揭示变量间的潜在规律。本文基于最小二乘法的理论框架&#xff0c;结合MATLAB代码实战&#xff0c;系统讲解线性拟合、非线性拟合的实现方法&#xff0c;并通过电阻温…...

C语言——排序(冒泡,选择,插入)

基本概念 排序是对数据进行处理的常见操作&#xff0c;即将数据按某字段规律排列。字段是数据节点的一个属性&#xff0c;比如学生信息中的学号、分数等&#xff0c;可针对这些字段进行排序。同时&#xff0c;排序算法有稳定性之分&#xff0c;若两个待排序字段一致的数据在排序…...

git如何下载指定版本

要使用Git下载指定版本&#xff0c;可以通过以下步骤进行操作‌&#xff1a; ‌1. 使用Git命令行下载指定版本‌&#xff1a; 1.1 首先&#xff0c;使用git clone命令克隆整个git库到本地。例如&#xff1a;git clone [库的URL]。这将下载最新的代码到本地。‌ 1.2 进入克隆…...

数字电路-基础逻辑门实验

基础逻辑门是数字电路设计的核心元件&#xff0c;它们执行的是基本的逻辑运算。通过这些基本运算&#xff0c;可以构建出更为复杂的逻辑功能。常见的基础逻辑门包括与门&#xff08;AND&#xff09;、或门&#xff08;OR&#xff09;、非门&#xff08;NOT&#xff09;、异或门…...

新数据结构(9)——Java异常体系

异常的种类 程序本身通常无法主动捕获并处理错误&#xff08;Error&#xff09;&#xff0c;因为这些错误通常表示系统级的严重问题&#xff0c;但程序可以捕获并处理异常&#xff08;Excrption&#xff09;&#xff0c;而Error则被视为一种程序无法或不应尝试恢复的异常类型。…...

每日十题八股-补充材料-2025年2月15日

1.TCP是如何保证消息的顺序和可靠的&#xff1f; 写得超级好的文章 首先肯定是三次握手和四次挥手保证里通讯双方建立了正确有效的连接。 其次是校验和、序列号&#xff0c;ACK消息应答机制还有重传机制&#xff0c;保证了消息顺序和可靠。 同时配合拥塞机制和流量控制机制&am…...

使用 Python 爬虫获取微店快递费用 item_fee API 接口数据

在电商运营中&#xff0c;快递费用是影响商家利润和用户体验的重要因素之一。微店作为国内知名的电商平台&#xff0c;提供了丰富的 API 接口供开发者使用&#xff0c;其中也包括查询商品快递费用的接口。通过调用微店的 item_fee 接口&#xff0c;开发者可以获取指定商品的快递…...

通过用户名和密码登录服务器有哪些方法

通过用户名和密码登录到服务器的方式取决于你使用的工具和协议。以下是几种常见的方法&#xff1a; 1. 使用 SSH 登录到 Linux 服务器 你可以通过 SSH&#xff08;Secure Shell&#xff09;使用用户名和密码连接到远程服务器。通常&#xff0c;你会使用 ssh 命令来进行连接。…...

sort快排

当然可以!让我们通过类似的详细步骤来解释 快速排序(Quick Sort) 的原理和实现,就像之前解释 a &= (a - 1) 的原理一样。 快速排序(Quick Sort)原理 快速排序是一种高效的排序算法,其核心思想是分而治之。它通过选择一个“基准值”(pivot),将数组分为两部分: …...

用xml配置spring, bean标签有哪些属性?

用xml配置spring, bean标签有哪些属性? 在Spring框架中&#xff0c;使用XML配置文件时&#xff0c;<bean>标签用于定义一个Bean。以下是一些常用的<bean>标签属性&#xff1a; 1. class 描述&#xff1a;指定Bean的类名。示例&#xff1a;<bean id"myBe…...

纪念日倒数日项目的实现-【纪念时刻-时光集】

纪念日/倒数日项目的实现## 一个练手的小项目&#xff0c;uniappnodemysql七牛云。 在如今快节奏的生活里&#xff0c;大家都忙忙碌碌&#xff0c;那些具有特殊意义的日子一不小心就容易被遗忘。今天&#xff0c;想给各位分享一个“纪念日”项目。 【纪念时刻-时光集】 一…...

无人机不等同轴旋翼架构设计应用探究

“结果显示&#xff0c;对于不等组合&#xff0c;用户应将较小的螺旋桨置于上游以提高能效&#xff0c;但若追求最大推力&#xff0c;则两个相等的螺旋桨更为理想。” 在近期的研究《不等同轴旋翼性能特性探究》中&#xff0c;Max Miles和Stephen D. Prior博士深入探讨了不同螺…...

1-8 gitee码云的注册与使用

码云的网址&#xff1a;Gitee - 基于 Git 的代码托管和研发协作平台 这是一个国内的托管代码平台&#xff0c;速度要比国外的快 1.0 注册 如何注册码云&#xff1f; 查考文章&#xff1a;https://jingyan.baidu.com/article/425e69e6a8cad6ff14fc1615.html 2.0 使用 使用码云进…...

嵌入式硬件篇---OpenMV的硬件流和软件流

文章目录 前言一、硬件流控制&#xff08;Hardware Flow Control&#xff09;1. 基本原理RTSCTS 2. OpenMV中的实现• 硬件要求• 代码配置• 工作流程 二、软件流控制&#xff08;Software Flow Control&#xff09;1. 基本原理XONXOFF 2. OpenMV中的实现• 代码配置• 工作流…...

Word 里面嵌入DeepSeek

目录 一、问题描述 二、解决方法 三、代码 四、注意事项 五、总结 一、问题描述 如何在Word里面嵌入DeepSeek? 二、解决方法 1、新建文档&#xff0c;按 AltF11&#xff0c;进入VB界面。 2、选中文档&#xff0c;右键->插入->模块。 3、进入模块&#xff0c;粘入…...

聊聊 IP 地址和端口号的区别

在计算机网络中&#xff0c;两个基本概念对于理解设备如何通过网络进行通信至关重要。IP 地址和端口号是 TCP/IP 的典型特征&#xff0c;其定义如下&#xff1a;IP 地址是分配给连接到网络的每台机器的唯一地址&#xff0c;用于定位机器并与其通信。相反&#xff0c;端口号用于…...

rust学习一、入门之搭建简单开发环境

1、搭建开发环境(windows11&#xff09; a.登录官网 一看就明白&#xff0c;此处略。 b.安装rustup 一看就明白&#xff0c;此处略。 c.安装 cargo script 或者 rust-script script cargo install cargo-script 完成后 注意&#xff1a;时间有一点点久。 测试 cargo s…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...