在appsignal上设置node.js应用程序的跟踪
#node #tracing #apm

在这篇文章中,您将学习如何将跟踪添加到appsignal上的node.js应用程序。您将使用与PostgreSQL数据库对话的现有报价应用程序获取报价。

让我们开始!

为什么需要跟踪和APM工具:案例研究

让我们从一个故事开始。您的经理人告诉您,您昨天部署的应用程序已报告为用户缓慢。您的经理声称投诉于昨天下午2点开始,您在下午1:55发布了更改。没有应用程序性能监视(APM)工具或数据跟踪,您只是在努力了解真正发生的事情。

您的分期测试很好,并且在使用本地机器上的小型数据集开发时,您没有遇到任何问题。经过将近两个小时的挖掘,您发现由于生产数据库中的数据量大量,您昨天提出的一些查询引起了慢速。您将修复程序推开,在问题表中添加几个索引,然后该应用再次返回其正常响应时间。

这是APM和跟踪的力量变得至关重要,即使对于您的应用程序至关重要(尤其是在生产环境中)。如果您有像AppSignal这样的APM,则通过检查应用程序的performance graphs时,您会知道问题的几分钟。

如果您设置了用于吞吐量或响应时间的trigger and alert,则该问题将在部署新更改后几分钟。

正确的跟踪可以查明引入问题的代码和查询行。在下一节中,我们将设置跟踪和示例应用程序的APM。

跟踪和apm for node.js应用程序

您将使用express建立使用node.js构建的示例引号应用程序。它从ElephantsQL上托管的PostgreSQL获取数据。使用Node.js and Postgres构建的应用程序是开源的,code is available on GitHub

该应用程序免费在render.com上托管,数据库也在ElephantsQL上的免费计划中。您可以看到下面的API返回的报价的示例:

Quotes app deployed and running on Render

要遵循本教程,您可以克隆GitHub存储库,然后将代码复制到您的计算机:

git clone git@github.com:geshan/nodejs-posgresql.git

然后运行npm install安装所有依赖项。它已通过Node.js V18进行了测试,即撰写时最新的LTS。之后,如果您运行npm start并在选择的浏览器上点击http://localhost:3000/quotes,则会看到与上述相似的输出。

现在,让我们将应用程序库添加到此引号应用程序。

将应用程序信号添加到node.js project

要向任何项目添加应用程序,您首先需要注册一个帐户。 AppSignal提供30天的免费试用版,无需信用卡信息,因此您可以无需任何问题即可。

注册后,您可以关注官方的Node installation docs在您的node.js应用程序中设置应用程序。

使用appsignal报告运行node.js应用

由于已将库添加到应用程序时,运行应用程序时,它将开始将数据报告给AppSignal。 npx命令在项目的根上创建一个appsignal.cjs文件,该文件将您的应用程序连接到应用程序信号。要包含此预运行脚本,您需要将应用程序启动脚本更改为package.json文件start脚本中的node --require './appsignal.cjs' ./bin/www

现在,如果您再次使用npm start运行引号应用程序并通过某些请求键入它,它将显示在项目的开发环境中,即taken from the NODE_ENV variable。几个请求后,它看起来与下面类似:

AppSignal showing stats for a couple of requests

hooray!您已成功将应用程序信号库添加到您的应用中,该库将数据和指标传达给您本地计算机的应用程序。

在下一节中,我们将向应用程序发送一些请求。

将请求发送到Node.js应用

同时发送大量捏造请求的最简单方法之一是使用Vegeta load testing tool。作为负载测试工具,它可以每秒始终如一地向给定的目标URL发送很多请求。您可以read more about Vegeta on GitHub。无需安装即可下载和使用binary

将Vegeta的可执行文件可执

echo "GET http://localhost:3000/quotes/" | vegeta attack -duration=60s -rate=3 | vegeta report --type=text

运行60秒后将显示下面的输出:

Sending 3 requests per second for 60 seconds with Vegeta

报告说,总共发送了180(3*60)请求,所有内容都带有200个状态代码。最快的请求花费了184.803毫秒,最慢的要求是2.95秒。这里还有其他有趣的统计数据。

多个因素可以减慢您的应用程序的响应能力。幸运的是,他们中的大多数人都在您的控制之下,您可以努力使您的应用程序更快。您可能会影响您的应用程序的某些因素包括:

  • 平衡分配给应用程序的资源
  • 代码级优化
  • 添加数据库索引
  • 改进SQL查询

根据项目的架构和基础架构,您也可以查看horizontal scaling和缓存。

如何将查询发送到数据库也可能是一个问题。 AppSignal可以使您对查询及其执行时间的更深入了解。我们将介绍如何在本文中稍后加快SQL查询。

分析统计和图形

现在,如果您在一分钟后检查应用程序的应用程序的开发环境,则可以在指标和图表中查看该应用程序处理的负载。您可以检查内存使用情况,响应时间,吞吐量和错误。

检查内存使用情况

在Node.js Heap Statistics仪表板上,您可以看到该应用程序在每秒提供3个请求时的内存消耗约为40 MB。

Memory usage of 40 MB while serving 3 RPS seen on AppSignal

检查内存使用情况非常有用,可以知道您的应用程序消耗了多少内存。假设您的应用程序同时获得了很多流量,并且仅分配了128 MB的内存。容器/POD可能由于不记忆(OOM)问题而被杀死。

同样,另一方面,您的应用程序也许是分配了512 MB的内存,并且在数周内,它在其高峰时只消耗了100 MB。然后是时候分配较低的内存。这也节省了成本,因为未使用80%的分配内存,也不会用于预期流量。相同的逻辑可以应用于分配给应用程序的其他资源,例如CPU。

可视化响应时间

,您还可以检查应用程序的响应时间,吞吐量和其他统计数据,同时在performance> Graphs时1分钟每秒提供3个请求(RPS)。上述贝吉塔负载测试看起来如下。

Response time and througput while serving 3 RPS seen on AppSignal

因此,以每分钟约180个请求(使用Vegeta发送的负载),在第95个百分位数上响应〜760毫秒。

这意味着最慢的5%的请求在760毫秒内响应了客户。响应时间对于API和Web应用程序非常重要。十多年前,Amazon found every 100ms of latency could cost them $1.6 billion in sales。因此,缓慢的网站和API对您的业务并不是很好。

保留响应时间的选项卡,并执行优化它们所需的工作。响应时间可以通过消耗更少的资源(例如CPU和内存)来减少,或者在服务器/容器中添加更多资源。

响应时间也可以通过加快缓慢的查询来降低,我们将在下一个讨论。

知道您的慢速查询

您可以根据performance>慢速查询查询应用程序中的慢速查询。例如,请参见下面的慢速SQL查询。

Showing details of slow SQL query on AppSignal

如果您知道慢速查询,则可以多种方式修复它们。您可以使用EXPLAIN前缀来了解为什么SELECT查询很慢。它返回查询计划者生成的执行计划。

要过度简化koude8,它进行了完整的表扫描,以告诉您查询是否包含更多的行以获得结果(即,查询可以通过扫描较少的数据来获得相同的行)。您可以将indexes添加到相关列中,以更快地使查询。索引使读取很快,但它们也使writes slow读取。因此,就您是否应该添加索引做出明智的决定。

加快慢速SQL的另一种方法是重写和重构查询。例如,您可以删除不需要的加入或将子查询转换为逐案。

现在,让我们将注意力转向跟踪Appsignal中的错误。

跟踪错误

您可以转到AppSignal中的错误>图形以查看应用程序的错误率。根据错误甚至响应时间,您可以在异常检测>触发器上添加触发器。然后对这些错误设置警报。

例如,如果您的吞吐量少于每分钟100,则可以触发电子邮件警报。如果错误率超过2%,则可以触发另一个警报,依此类推。

以下是code snippet from the quotes file in the example app,故意引入了错误。

/* GET quotes listing error. */
router.get("/error-fix", async function (req, res, next) {
  try {
    res.json(await quotes.getError(req.query.page));
  } catch (err) {
    console.error(`Error while getting quotes `, err.message);
    appSignal.setError(err);
    res.status(err.statusCode || 500).json({ message: err.message });
  }
});

引号服务没有getError方法。这将始终进入捕获部分。由于appSignal.setError方法的调用带有错误,因此将其发送到appsignal。击中URL后,一段时间后,错误将在错误>“问题列表”下的应用程序信号界面中显示,如下:

Errors list on AppSignal

然后,您可以单击GET /quotes/error-fix路径中的特定错误。您将看到错误摘要,并可以单击“样本”选项卡以查看以下内容:

Error Samples on AppSignal

如果选择其中一个样本,则可以查看有关该错误示例的更多详细信息:

More details about the Error samples on AppSignal

然后,如果您向下滚动到Backtrace部分,然后单击“ Show full backtrace”的绿色按钮,则可以准确查看错误来自何处(以及哪些文件和功能导致该功能调用),如下:

Error trace on AppSignal

鉴于这是一个虚假的错误,它将在Quotes服务上调用现有方法后立即修复。您还可以在应用程序信号上查看不同时间范围的错误图如下:

Error trace on AppSignal

现在,想象一下调试讨厌的错误或性能问题,并拥有所有这些数据,指标和统计数据。这就像在黑暗的房间里拥有强大的火炬 - 您可以更快地发现问题,并且更近一步地解决了问题。

AppSignal中的其他有用功能

在AppSignal中使用左侧栏上的链接。您可以add an uptime monitor。如果您的网站或Web应用程序由于某种原因而关闭,则将收到通知。您的应用程序每分钟从全球4个不同的位置进行ping。

还有Host metrics section,其中包括CPU使用,负载平均值,内存使用量和其他主机统计。

包起来

在这篇文章中,您首先了解了为什么跟踪和应用程序性能监控(APM)很重要。之后,我们引入了一个示例应用程序,该应用程序通过JSON API提供报价。然后,我们在该示例应用程序中添加了AppsSignal APM并跟踪。

我们探索了Appsignal的一些有用功能。

快乐的追踪!

P.S。如果您喜欢这篇文章,subscribe to our JavaScript Sorcery list每月深入研究更神奇的JavaScript技巧和技巧。

P.P.S。如果您需要用于node.js应用的APM,则GO和check out the AppSignal APM for Node.js