大型网站重构指南 第1.2部分:Nodejs 系统可观测性 OpenTelemetry+SigNoz

简介: 大型网站重构指南 第1.2部分:Nodejs 系统可观测性 OpenTelemetry+SigNoz

在上一篇文章中我们介绍了 SonarQube,它是一种代码静态质量检查的工具。

但有时候一些问题在静态检查期间并不能完全暴露出来,这些问题会带到线上,在用户使用软件的时候,出现问题。

这时候就需要针对程序的运行时进行检测,这项能力也就是可观测行。也就是本篇文章要做的事。


OpenTelemetry 介绍


OpenTelemetry 是系统可观测行框架这个领域的佼佼者。

它是一个完全开源的库,它提供了一组 API/SDK 来帮助我们对程序进行监控、日志和追踪。而这三者就是目前可观测性的三大核心。

在可观测性这个领域,它几乎是唯一的事实标准。

OpenTelemetry 最初只是针对复杂的后端应用进行设计的,但现在同时也支持前端。不过 OpenTelemetry 在前端方面并不是最优的选择。

所以 ichati.cn 只在后端使用了 OpenTelemetry。前端可以选择一些更合适的工具,比如 Sentry。

OpenTelemetry 支持 C++、Java、JS、Go、Python、Rust 等 11 种主流语言。同时还可以轻松地和很多主流框架进行集成。比如 Java 的 Spring、Nodejs 的 Express、Nestjs、ASP.NET Core 等。

它的原理我就不讲了,稍微会复杂一些,通过进程间通信和上下文传播来完成的。我们主要关注如何利用 OpenTelemetry 来达到观测 ichati.cn 的目的。


OpenTelemetry 与 Nestjs 集成


ichati.cn 的后端使用 Nestjs 开发的,所以我们先将 OpenTelemetry 和项目进行集成。

这里你必须有一个 Nodejs 的项目,可以不是 Nestjs 框架的项目,比如 Express 也可以。

然后安装 OpenTelemetry 的依赖。


npm install @opentelemetry/sdk-node \
  @opentelemetry/api \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/sdk-metrics
接下来创建一个 instrumentation.ts 文件。
TypeScript
复制代码
import { NodeSDK } from '@opentelemetry/sdk-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { PeriodicExportingMetricReader, ConsoleMetricExporter } from '@opentelemetry/sdk-metrics';
const sdk = new NodeSDK({
  traceExporter: new ConsoleSpanExporter(),
  metricReader: new PeriodicExportingMetricReader({
    exporter: new ConsoleMetricExporter()
  }),
  instrumentations: [getNodeAutoInstrumentations()]
});
sdk
  .start()

然后在项目的 HTTP 服务启动之前导入这个文件。通常会是 main.ts。

重新启动项目。随着你的接口被调用,你会发现控制台会有很多类似的输出:


{
  traceId: 'd4b107c7971580478eef859a2fd979aa',
  parentId: undefined,
  traceState: undefined,
  name: 'GET /user',
  id: '573d0fb86048fc11',
  kind: 1,
  timestamp: 1685629667330000,
  duration: 345450,
  attributes: {
    'http.url': 'http://127.0.0.1:4401/user',
    'http.host': '127.0.0.1:4401',
    'net.host.name': '127.0.0.1',
    'http.method': 'GET',
    'http.scheme': 'http',
    'http.target': '/user',
    'http.user_agent': 'insomnia/2023.1.0',
    'http.request_content_length_uncompressed': 0,
    'http.flavor': '1.1',
    'net.transport': 'ip_tcp',
    'net.host.ip': '::ffff:127.0.0.1',
    'net.host.port': 4401,
    'net.peer.ip': '::ffff:127.0.0.1',
    'net.peer.port': 53063,
    'http.status_code': 200,
    'http.status_text': 'OK',
    'http.route': '/user'
  },
  status: { code: 0 },
  events: [],
  links: []
}

不仅仅是 HTTP 的入站/出站会被检测,几乎其他所有的行为都会被检测,包括TLS 的连接/断开、文件系统的调用、中间件的调用、定时任务等等。

我们仅仅是把这些数据输出到控制台中显然是不够的,因为纯文本的内容不利于数据的分析和可视化。

我们还需要有一个平台来存储、查询、分析这些日志。


SigNoz 介绍


OpenTelemetry 中有一个 Exporters 的概念,其实就是一个提供存储日志数据和搜索的系统。

这类系统的开源项目有很多,比如 Jaeger、SkyWalking、Zipkin、Haystack、SigNoz 和 Grafana 等。

它们中的大多数最初都支持系统检测功能,但是后面都演变变成了纯粹的存储和可视化系统。把检测功能让给了 OpenTelemetry,让专业的人做专业事。

这里 ichati.cn 选择了 SigNoz。

SigNoz 不是里面最好的,也不是最成熟的。选择它的理由是,它可视化功能非常强大。我认为这类系统最重要的功能就是数据可视化和查询。


安装并启动 SigNoz


安装 SigNoz 很简单,但是过程可能比较慢。

第一步,首先电脑上安装 Docker。SigNoz 只支持 Docker 一种方式部署。

第二步,运行以下三行命令。


git clone -b main https://github.com/SigNoz/signoz.git
cd signoz/deploy/
./install.sh

不出意外的话,就可以看到启动成功。


++++++++++++++++++ SUCCESS ++++++++++++++++++++++
🟢 Your installation is complete!
🟢 Your frontend is running on http://localhost:3301

然后浏览器访问 http://localhost:3301 就可以看到 Dashboard 了。

现在的几个项目都是 SigNoz 默认的演示项目。

image.png


将 OpenTelemetry 的数据发送到 SigNoz


我们之前的代码实现是将 OpenTelemetry 的数据输出到控制台,现在我们要输出到 SigNoz。

要把 OpenTelemetry 的检测数据发送到 SigNoz,还需要安装三个包。


npm install @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources @opentelemetry/semantic-conventions

然后修改代码。


import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: 'http://localhost:4318/v1/traces',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'ichati-backend',
  }),
});
process.on('SIGTERM', () => {
  sdk
  .shutdown()
  .then(() => console.log('Tracing terminated'))
  .catch((error) => console.log('Error terminating tracing', error))
  .finally(() => process.exit(0));
});
export default sdk;

注意代码中的 4318 端口是 SigNoz 默认的端口。

最后在 main.ts 中导入 sdk 运行。


import instrumentation from './instrumentation';
instrumentation.start();

现在我们发送一些请求,就可以在 SigNoz 中查看到项目了。

image.png


SigNoz 云托管


实际上,像 ichati.cn 这类中小型团队,不想花太多时间在基础设施上面,所以运行了一段时间的 SigNoz 后,觉得管理服务器比较麻烦。

后面切换到了云服务商 elest 上面: elest.io

在 elest 上面,SigNoz 最便宜的套餐是每月 36 美元,2C、8G、80G 存储。我认为还算划算。虽然比自己买裸机要贵一点,但绝对比单独招个人来做运维划算得多。


数据的用途


以上步骤都只是一些繁琐无聊的项目搭建和配置,现在我们才正式进入主题。

我们应该关心应用的哪些数据呢?

第一是接口的延迟。

SigNoz 将接口延迟分为了三类:

  • P50,也就是中位数
  • P95,前 95% 的情况
  • p99,也就是前 99% 的情况。

这个数据指标可以反应系统的性能和稳定性。

第二是 Rate。单位是 ops/s,也就是系统每秒处理的请求数。

这个指标主要反应系统的性能。

image.png

第三是操作的错误率。

这个指标主要反映系统的稳定性。

image.png

我们还可以通过条件筛选来查看更详细的内容,SigNoz 支持的筛选项非常多,包括时段、操作名、HTTP 请求方法、请求 URL、请求来源、Trace ID 等。

image.png

如果你想查看某些特殊的接口,我们还可以查看它的火焰图和调用堆栈,比较有利于排查问题。

image.png

以上就是常见的数据功能。

SigNoz 的强大还不止于此,它还有一些其他功能,比如自定义 Dashboard、定义 Alert、服务地图等等。

这样当系统出现故障时可以方便的通过某行方式通知到对应的人。比如邮箱、飞书、微信等等。

但目前 ichati.cn 还用不到这么多功能。所以就不对这些功能做更深入地介绍了。

篇幅所限,本文暂时结束。

后面会持续更新,让我们一起期待《大型网站重构指南》的下一篇。

如果你对最新的技术感兴趣,特别是对 Web3、AI 相关的内容感兴趣,可以添加我的微信 LZQ20130415,拉你进群交流。



相关文章
|
6月前
|
前端开发 JavaScript Java
基于vue-node的共享车位管理系统的设计与实现_kaic
基于vue-node的共享车位管理系统的设计与实现_kaic
|
5月前
|
缓存 JSON JavaScript
Node.js模块系统
Node.js模块系统
31 1
|
1月前
|
缓存 JSON JavaScript
Node.js模块系统
10月更文挑战第4天
36 2
|
1月前
|
Web App开发 JavaScript API
构建高效后端系统:Node.js与Express框架的实践之路
【9月更文挑战第37天】在数字化时代的浪潮中,后端开发作为技术架构的核心,承载着数据处理和业务逻辑的重要职责。本文将深入探讨如何利用Node.js及其强大的Express框架来搭建一个高效、可扩展的后端系统。我们将从基础概念讲起,逐步引导读者理解并实践如何设计、开发和维护一个高性能的后端服务。通过实际代码示例和清晰的步骤说明,本文旨在为初学者和有经验的开发者提供一个全面的指南,帮助他们在后端开发的旅途上走得更远。
48 3
|
28天前
|
运维 JavaScript Linux
容器内的Nodejs应用如何获取宿主机的基础信息-系统、内存、cpu、启动时间,以及一个df -h的坑
本文介绍了如何在Docker容器内的Node.js应用中获取宿主机的基础信息,包括系统信息、内存使用情况、磁盘空间和启动时间等。核心思路是将宿主机的根目录挂载到容器,但需注意权限和安全问题。文章还提到了使用`df -P`替代`df -h`以获得一致性输出,避免解析错误。
|
6月前
|
监控 JavaScript API
局域网监控软件的实时通知系统:利用Node.js和WebSocket实现即时消息推送
本文介绍了如何使用Node.js和WebSocket构建局域网监控软件的实时通知系统。实时通知对于网络安全和家庭监控至关重要,能即时发送监控数据变化的通知,提高响应速度。通过Node.js创建WebSocket服务器,当数据变化时,监控软件发送消息至服务器,服务器随即推送给客户端。此外,还展示了如何利用Node.js编写API,自动将监控数据提交到网站,便于用户查看历史记录,从而提升监控体验。
180 3
|
3月前
|
存储 缓存 JSON
Node.js有哪些模块系统
【8月更文挑战第12天】Node.js有哪些模块系统
40 3
|
2月前
crash —— 获取系统NODE、ZONE、SECTION、MEMBLOCK等信息
crash —— 获取系统NODE、ZONE、SECTION、MEMBLOCK等信息
|
3月前
|
JavaScript
【Deepin 20系统】Jupyter notebook解决ValueError: Please install Node.js and npm before continuing installa
文章讨论了在Deepin 20系统上安装Jupyter Notebook的debug插件时出现的"ValueError: Please install Node.js and npm before continuing installation"错误,并提供了使用conda安装Node.js的解决方法。
121 1
|
3月前
|
JavaScript Linux
【Deepin 20系统】解决ValueError: Please install nodejs >=12.0.0 before continuing
文章讨论了在尝试安装JupyterLab的debugger扩展时遇到的"ValueError: Please install nodejs >=12.0.0 before continuing"错误。由于使用conda和其他包管理器安装的Node.js版本只有10.x,作者提供了从Node.js官网直接下载并安装一个更新版本(至少12.0.0)的解决方法,包括下载对应系统版本的Node.js,解压,并建立软链接以更新版本。
53 0