🎉像专业人士一样监控你的 Javascript 应用程序🧙‍♂️💫

2025-06-07

🎉像专业人士一样监控你的 Javascript 应用程序🧙‍♂️💫

TL;DR

在本教程中,您将学习如何使用现代工具最佳实践来监控您的 Javascript 应用程序。

探索分布式跟踪的强大功能,并了解如何无缝集成和利用 Odigos 和 Jaeger 等工具来增强您的监控能力。

你将学到:✨

  • 如何使用 Javascript 构建微服务🐜。
  • 为微服务设置 Docker 容器📦。
  • 配置 Kubernetes ☸️ 来管理微服务。
  • 集成跟踪后端以实现跟踪可视化🔍。

您准备好成为JS 应用程序监控专家了吗?😍先生,说“是”

我听不见。大声点说。🙉

大声点说出来 GIF


让我们开始吧🦄

🚨 在博客的这一部分,我们将构建一个虚拟的 JavaScript 微服务应用程序,并将其部署到本地 Kubernetes 上。如果您已经有一个 Kubernetes 并且正在继续阅读,请跳过此部分。

为您的应用程序创建初始文件夹结构,如下所示。👇🏻

mkdir microservices-demo
cd microservices-demo
mkdir src
cd src
Enter fullscreen mode Exit fullscreen mode

设置服务器🖥️

👀 为了演示目的,我将创建两个相互通信的微服务,最终我们可以使用它来可视化分布式跟踪。

  • 构建并 Docker化微服务 1

在文件夹内/src创建一个新文件夹/microservice-1。在文件夹内初始化一个NodeJS项目并安装所需的依赖项。

mkdir microservice-1
cd microservice-1
npm init -y
npm install --save express node-fetch
Enter fullscreen mode Exit fullscreen mode

创建一个新文件index.js并添加以下代码:

// 👇🏻/src/microservice-1/index.js
const express = require("express");
const fetch   = require("node-fetch")

const app = express();
const PORT = 3001;

app.use(express.json());

app.get("/", async (req, res) => {
  try {
    const response = await fetch("http://microservice2:8081/api/data");
    const data = await response.json();
    res.json({
      data: "Microservice 2 data received in Microservice 1",
      microservice2Data: data,
    });
  } catch (error) {
    console.error(error.message);
    res.status(500).json({ error: "Internal Server Error" });
  }
});

app.listen(PORT, () => {
  console.log(`Microservice 1 listening on port ${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

💡 如果你注意到了,我们正在从 请求数据http://microservice2:8081/api/data。你可能会好奇,这个 microservice2 是什么?其实,我们可以将服务名用作主机名。😉 我们稍后会构建这个服务。

服务器正在监听端口3001,并在获取请求时/请求数据microservice2并以 JSON 对象的形式返回响应。📦

现在,是时候将这个微服务docker化了。在文件Dockerfile夹中创建一个新的/microservice-1,并添加以下代码:

// 👇🏻/src/microservice-1/Dockerfile
FROM node:18

# Use /usr/src/app as the working directory
WORKDIR /usr/src/app

# Copy package files and install production dependencies
COPY --chown=node:node package*.json /usr/src/app
RUN npm install --production

# Copy the rest of the files
COPY --chown=node:node . /usr/src/app/

# Switch to the user node with limited permissions
USER node

# Expose the application port
EXPOSE 3001

# Set the default command to run the application
CMD ["node", "index.js"]

Enter fullscreen mode Exit fullscreen mode

最好将.dockerignore我们不想推送的文件添加到容器中。创建一个.dockerignore文件,其中包含我们不想推送的文件的名称。

// 👇🏻/src/microservice-1/.dockerignore
node_modules
Dockerfile
Enter fullscreen mode Exit fullscreen mode

最后,通过运行以下命令构建🏗️docker 镜像:

docker build -t microservice1-image:latest .
Enter fullscreen mode Exit fullscreen mode

现在,这就是我们第一个微服务的完整设置。✨

  • 构建并 Docker化微服务 2

我们将有一个类似的设置microservice1,只是这里和那里有一些变化。

在文件夹内/src,创建一个新文件夹/microservice-2。在文件夹内,初始化一个NodeJS项目并安装所需的依赖项。

mkdir microservice-2
cd microservice-2
npm init -y
npm install --save express node-fetch
Enter fullscreen mode Exit fullscreen mode

创建一个新文件index.js并添加以下代码:

// 👇🏻/src/microservice-2/index.js
const express = require("express");
const fetch   = require("node-fetch")

const app = express();
const PORT = 3002;

app.use(express.json());

app.get("/api/data", async (req, res) => {
  const url = "https://jsonplaceholder.typicode.com/users";

  try {
    const response = await fetch(url);
    const data = await response.json();
    res.json(data);
  } catch (error) {
    console.error(error.message);
    res.status(500).json({ error: "Internal Server Error" });
  }
});

app.listen(PORT, () => {
  console.log(`Microservice 2 listening on port ${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

服务器正在监听端口 3002,当收到请求时GET request/api/data我们从中获取数据jsonplaceholder并以 JSON 对象的形式返回响应。📦

现在,是时候将此微服务也 docker 化了。复制并粘贴所有Dockerfile内容microservice1,只需将端口从 3001 更改为 3002。

另外,添加一个.dockerignore文件并包含我们在创建时添加的相同文件microservice1

最后,通过运行以下命令构建🏗️Docker 镜像:

docker build -t microservice2-image:latest .
Enter fullscreen mode Exit fullscreen mode

现在,这也是我们第二个微服务的完整设置。✨

  • 设置 Kubernetes

确保已安装Minikube ,或按照链接获取安装说明。👀

运行以下命令创建一个新的本地 Kubernetes 集群。设置 Odigos 和 Jaeger 时需要用到它。

启动 Minikube:🚀

minikube start
Enter fullscreen mode Exit fullscreen mode

现在我们已经准备好两个微服务并将其 dockerized,现在是时候设置 Kubernetes 来管理这些服务了。

在项目根目录下创建一个新文件夹/k8s/manifests。在此文件夹中,我们将为两个微服务添加部署和服务配置。

  • 部署配置📜:用于在 Kubernetes 集群上实际部署容器。
  • 服务配置📄:将 pod 暴露给集群内部和集群外部。

首先,让我们为创建清单microservice1。创建一个新文件microservice1-deployment-service.yaml并添加以下内容:

// 👇🏻/k8s/manifests/microservice1-deployment-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice1
spec:
  selector:
    matchLabels:
      app: microservice1
  template:
    metadata:
      labels:
        app: microservice1
    spec:
      containers:
        - name: microservice1
          image: microservice1-image
          # Make sure to set it to Never, or else it will pull from the docker hub and fail.
          imagePullPolicy: Never
          resources:
            limits:
              memory: "200Mi"
              cpu: "500m"
          ports:
            - containerPort: 3001
---
apiVersion: v1
kind: Service
metadata:
  name: microservice1
  labels:
    app: microservice1
spec:
  type: NodePort
  selector:
    app: microservice1
  ports:
    - port: 8080
      targetPort: 3001
      nodePort: 30001
Enter fullscreen mode Exit fullscreen mode

此配置部署了一个名为 的微服务,microservice1其资源限制为200MB 内存🗃️ 和0.5 个 CPU 核心。它通过 Deployment 在端口 3001 上向内部公开该微服务,并通过 Service在NodePort 30001 上向外部公开该微服务。

🤔 还记得Dockerfile我们用名字构建的microservice1-image吗?我们使用相同的镜像来创建容器。

它可以在集群内的 8080 端口上访问。我们假设microservice1-image可以在本地使用imagePullPolicy: Never。如果没有,它会尝试从 Docker Hub 🐋 拉取镜像,但会失败。

现在,让我们创建清单microservice2。创建一个名为 的新文件microservice2-deployment-service.yaml并添加以下内容:

// 👇🏻/k8s/manifests/microservice1-deployment-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice2
spec:
  selector:
    matchLabels:
      app: microservice2
  template:
    metadata:
      labels:
        app: microservice2
    spec:
      containers:
        - name: microservice2
          image: microservice2-image
          # Make sure to set it to Never, or else it will pull from the docker hub and fail.
          imagePullPolicy: Never
          resources:
            limits:
              memory: "200Mi"
              cpu: "500m"
          ports:
            - containerPort: 3002
---
apiVersion: v1
kind: Service
metadata:
  name: microservice2
  labels:
    app: microservice2
spec:
  type: NodePort
  selector:
    app: microservice2
  ports:
    - port: 8081
      targetPort: 3002
      nodePort: 30002
Enter fullscreen mode Exit fullscreen mode

它与的清单类似microservice1,只有少量变化。👀

此配置部署了一个名为 的微服务microservice2,并通过 Deployment 在端口 3002 上向内部公开它,并通过 Service在NodePort 30002 上向外部公开它。

可在集群内的端口 8081 上访问,假设microservice2-image可在本地使用imagePullPolicy: Never

完成所有操作后,请确保应用这些配置并使用这些服务启动 Kubernetes 集群。将目录更改为以下位置/manifests并执行以下命令:👇🏻

kubectl apply -f microservice1-deployment-service.yaml
kubectl apply -f microservice2-deployment-service.yaml
Enter fullscreen mode Exit fullscreen mode

通过执行以下命令检查我们的部署是否正在运行:👇🏻

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Kubernetes Pod

最后,我们的应用程序已准备就绪,并使用必要的部署配置部署在 Kubernetes 上。🎉


安装 Odigos 😍

💡 Odigos是一个开源可观察性控制平面,使组织能够创建和维护其可观察性管道。

Odigos - 监控工具

ℹ️如果您在 Mac 上运行,请运行以下命令在本地安装 Odigos。

brew install keyval-dev/homebrew-odigos-cli/odigos
Enter fullscreen mode Exit fullscreen mode

ℹ️ 如果您使用的是 Linux 系统,请考虑通过执行以下命令从 GitHub 版本进行安装。请确保根据您的 Linux 发行版更改文件。

ℹ️ 如果 Odigos 二进制文件不可执行,请chmod +x odigos在运行安装命令之前运行此命令使其可执行。

curl -LJO https://github.com/keyval-dev/odigos/releases/download/v1.0.9/cli_1.0.9_linux_amd64.tar.gz
tar -xvzf cli_1.0.9_linux_amd64.tar.gz
./odigos install
Enter fullscreen mode Exit fullscreen mode

Odigos 安装

如果您需要有关安装的更多简要说明,请点击此链接

现在,Odigos 已准备好运行 🎉。我们可以执行它的 UI,配置跟踪后端,并相应地发送跟踪信息。


将 Odigos 与追踪后端连接起来💫

💡 Jaeger是一个开源的端到端分布式跟踪系统。

Odigos - 分布式追踪平台

设置 Jaeger!

在本教程中,我们将使用Jaeger 🕵️‍♂️,这是一个流行的开源平台,用于查看微服务应用程序中的分布式跟踪信息。我们将使用它来查看 Odigos 生成的跟踪信息。

有关 Jaeger 的安装说明,请点击此链接。👀

要在 Kubernetes 集群上部署 Jaeger,请运行以下命令:👇🏻

kubectl create ns tracing
kubectl apply -f https://raw.githubusercontent.com/keyval-dev/opentelemetry-go-instrumentation/master/docs/getting-started/jaeger.yaml -n tracing
Enter fullscreen mode Exit fullscreen mode

在这里,我们创建一个tracing命名空间并在该命名空间中应用 Jaeger 的部署配置📃。

此命令设置自托管的 Jaeger 实例及其服务。👀

运行以下命令获取正在运行的 pod 的状态:👇🏻

kubectl get pods -A -w
Enter fullscreen mode Exit fullscreen mode

等待所有三个 pod 都运行完毕后再继续下一步。

Kubernetes Pod

现在,要在本地查看 Jaeger 界面💻,我们需要进行端口转发。将流量从本地机器的 16686 端口转发到 Kubernetes 集群中选定 Pod 的 16686 端口。

kubectl port-forward -n tracing svc/jaeger 16686:16686
Enter fullscreen mode Exit fullscreen mode

此命令在本地机器和 Jaeger pod 之间创建一个隧道,公开 Jaeger UI 以便您与其交互。

最后,打开http://localhost:16686浏览器,查看正在运行的 Jaeger 实例。

Jaeger 用户界面

设置 Odigos 与 Jaeger 合作! 🌟

ℹ️ 对于 Linux 用户,请转到从 GitHub 版本下载 Odigos 二进制文件的文件夹,然后运行以下命令来启动 Odigos UI。

./odigos ui
Enter fullscreen mode Exit fullscreen mode

ℹ️ 对于 Mac 用户,只需运行:

odigos ui
Enter fullscreen mode Exit fullscreen mode

访问http://localhost:3000后,您将看到 Odigos 界面,您将在其中看到default命名空间中的部署。

Odigos登陆页面

选择这两个,然后单击“下一步”。在下一页上,选择 Jaeger 作为后端,并在出现提示时添加以下详细信息:

  • 目的地名称🛣️:输入您想要的任何名称,例如express-tracing
  • 端点🎯jaeger.tracing:4317为端点添加。

就这样——Odigos 已设置好,可以向 Jaeger 后端发送追踪信息了。就是这么简单。🤯

包含两个微服务的 Odigos UI


查看分布式跟踪🧐

设置 Odigos 后,在 Jaeger 主页上http://localhost:16686,您将看到列出的我们的两个微服务。

Jaeger UI 列出了两个微服务

Odigos 已经开始向 Jaeger 发送我们应用程序的痕迹了。😉

microservice1记住,这是我们的微服务应用程序。由于它是起点,因此请再发出几个请求,它将随后请求microservice2数据并返回。最终,Jaeger 将开始填充跟踪信息。

Jaeger 分布式追踪

单击任意一个请求,您应该能够观察请求如何流经您的应用程序以及完成每个请求所需的时间。

这一切都是在没有更改任何代码的情况下完成的。🤯 这一切都要感谢Odigos!🤩

令人震惊的 GIF

试想一下,这只是一个很小的虚拟应用程序,但对于一个运行着大量微服务🏃🏻‍♂️并相互交互的大型应用程序来说,分布式跟踪将非常强大!💪

通过分布式跟踪,您可以轻松识别应用程序中的瓶颈,并确定哪个服务导致了问题或花费了更长的时间。🕒


让我们总结一下!🥱

到目前为止,您已经学习了如何使用分布式跟踪密切监视👀您的 Javascript 应用程序,并使用Odigos作为应用程序和跟踪后端Jaeger之间的中间件。👏

如果你已经做到了这一点,那就给自己一个赞吧。🥳 这是你应得的!😉

如果您发现本文和工具有用,请务必在OdigosJaeger的 GitHub 存储库上给予一颗星 🌟。

本教程的源代码可以在这里找到:

https://github.com/keyval-dev/blog/tree/main/odigos-monitor-JS-like-a-pro

如果您对本文有任何疑问或建议,请在下面的评论部分分享。👇🏻

好了,本文就到这里。感谢阅读!🎉🫡

文章来源:https://dev.to/odigos/monitor-your-javascript-application-like-a-pro-581p
PREV
Building a URL shortening service with NodeJS and MongoDB. Deploy to Azure. Front end Server Yayy we have come a long way!! NEXT STEP LAST STEP!!!
NEXT
理解 JavaScript 扩展运算符 - 从初学者到专家 简介 我们将学习什么 为什么要使用扩展运算符 扩展运算符如何工作? 克隆数组和对象 将类数组对象转换为数组 扩展运算符作为参数 添加新元素 合并数组/对象 结论