Linkerd 2.10(Step by Step)—使用每个路由指标调试 HTTP 应用程序

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: Linkerd 2.10(Step by Step)—使用每个路由指标调试 HTTP 应用程序

这个演示是一个Ruby应用程序,可以帮助您管理书架。它由多个微服务组成,并通过 HTTP 使用 JSON 与其他服务通信。有三种服务:


  • webapp: 前端
  • authors: 管理系统中作者的 API
  • books: 管理系统中书籍的API

出于演示目的,该应用程序带有一个简单的流量生成器。整体拓扑如下所示:


微信图片_20220612133033.png


先决条件



要使用本指南,您需要在集群上安装 Linkerd 及其 Viz 扩展。如果您还没有这样做,请按照安装 Linkerd 指南进行操作。


安装应用



首先,让我们将 books app 安装到您的集群上。在本地终端中,运行:


kubectl create ns booksapp && \
  curl -sL https://run.linkerd.io/booksapp.yml \
  | kubectl -n booksapp apply -f -


此命令为 demo 创建一个命名空间,下载其 Kubernetes 资源清单 并使用 kubectl 将其应用到您的集群。该应用程序包含在 booksapp 命名空间中 运行的 Kubernetes deployments 和 services。


第一次下载一堆容器需要一点时间。Kubernetes 可以告诉您所有服务何 时都在运行并准备好进行通信。通过运行以下命令等待它发生:


kubectl -n booksapp rollout status deploy webapp


您还可以通过运行以下命令快速查看添加到集群中的所有组件:


kubectl -n booksapp get all


部署成功完成后,您可以通过本地端口转发 webapp 访问应用程序本身:


kubectl -n booksapp port-forward svc/webapp 7000 &


在浏览器中打开 http://localhost:7000/ 以查看前端。



微信图片_20220612133132.png


不幸的是,应用程序中有一个错误:如果您单击 Add Book,它有 50% 的时间会失败。这是一个典型的不明显、间歇性故障的案例——这种故障让服务所有者抓狂,因为它很难调试。Kubernetes 本身无法检测或显示此错误。从 Kubernetes 的角度来看, 看起来一切都很好,但您知道应用程序正在返回错误。


微信图片_20220612133143.png


将 Linkerd 添加到服务中



现在我们需要将 Linkerd 数据平面代理添加到服务中。最简单的选择是做这样的事情:


kubectl get -n booksapp deploy -o yaml \
  | linkerd inject - \
  | kubectl apply -f -


此命令检索 booksapp 命名空间中所有部署的清单, 通过 linkerd inject 运行它们,然后使用 kubectl apply 重新应用。 linkerd inject 命令对每个资源进行注释, 以指定它们应该添加 Linkerd 数据平面代理, 当清单重新应用于集群时,Kubernetes 会执行此操作。最重要的是,由于 Kubernetes 进行滚动部署,因此应用程序始终保持运行。


调试



让我们使用 Linkerd 来发现此应用程序失败的根本原因。要查看 Linkerd 仪表板,请运行:


linkerd viz dashboard &


微信图片_20220612133205.png


从命名空间下拉列表中选择 booksapp 并单击 Deployments 工作负载。您应该会看到 booksapp 命名空间中的所有部署都显示出来了。会有成功率、每秒请求数和延迟百分位数。


这很酷,但你会注意到 webapp 的成功率不是 100%。这是因为流量生成器正在提交新书。你可以自己做同样的事情,把成功率推得更低。单击 Linkerd 仪表板中的 webapp 以进行实时调试会话。


您现在应该查看 webapp 服务的详细信息视图。您会看到 webapp 正在从 traffic(负载生成器)中获取流量, 并且它有两个传出依赖项:authorsbook。一个是作者信息拉取服务,一个是图书信息拉取服务。


微信图片_20220612133226.png


依赖服务中的故障可能正是导致 webapp 返回错误的原因(以及您作为用户在单击时可以看到的错误)。我们可以看到 books 服务也失败了。让我们进一步向下滚动页面, 我们将看到 webapp 正在接收的所有流量端点的实时列表。这是有趣的:


微信图片_20220612133228.png


啊哈!我们可以看到,从 webapp 服务到 books 服务的入站流量在很大一部分时间都失败了。这可以解释为什么 webapp 会引发间歇性故障。让我们点击 tap (🔬) 图标, 然后点击开始按钮来查看实际的请求和响应流。


微信图片_20220612133255.png


事实上,许多这些请求都返回 500。

诊断仅影响单一路线的间歇性问题非常容易。您现在拥有了打开详细错误报告所需的一切,该报告准确地解释了根本原因是什么。如果 books 服务是您自己的,您就知道在代码中的确切位置。


Service Profiles



为了了解根本原因,我们使用了实时流量。对于某些问题,这很好,但是如果问题是间歇性的并且发生在半夜会怎样?Service profiles 为 Linkerd 提供了有关您的服务的一些附加信息。这些定义了您正在服务的路由,除其他外,还允许在每个路由的基础上收集指标。通过 Prometheus 存储这些指标,您将能够睡个好觉并在早上查找间歇性问题。

获取 service profiles 设置的最简单方法之一是使用现有的 OpenAPI (Swagger) 规范。此 demo 已发布其每项服务的规范。您可以通过运行以下命令为 webapp 创建 service profile:


curl -sL https://run.linkerd.io/booksapp/webapp.swagger \
  | linkerd -n booksapp profile --open-api - webapp \
  | kubectl -n booksapp apply -f -


这个命令会做三件事:


  1. 获取 webapp 的 swagger 规范。
  2. 获取规范并使用 profile 命令将其转换为服务配置文件。
  3. 将此配置应用于集群。


除了 installinjectprofile 也是一个纯文本操作。查看生成的配置文件:


apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  creationTimestamp: null
  name: webapp.booksapp.svc.cluster.local
  namespace: booksapp
spec:
  routes:
  - condition:
      method: GET
      pathRegex: /
    name: GET /
  - condition:
      method: POST
      pathRegex: /authors
    name: POST /authors
  - condition:
      method: GET
      pathRegex: /authors/[^/]*
    name: GET /authors/{id}
  - condition:
      method: POST
      pathRegex: /authors/[^/]*/delete
    name: POST /authors/{id}/delete
  - condition:
      method: POST
      pathRegex: /authors/[^/]*/edit
    name: POST /authors/{id}/edit
  - condition:
      method: POST
      pathRegex: /books
    name: POST /books
  - condition:
      method: GET
      pathRegex: /books/[^/]*
    name: GET /books/{id}
  - condition:
      method: POST
      pathRegex: /books/[^/]*/delete
    name: POST /books/{id}/delete
  - condition:
      method: POST
      pathRegex: /books/[^/]*/edit
    name: POST /books/{id}/edit


name 指的是你的 Kubernetes 服务的 FQDN, 在这个实例中 webapp.booksapp.svc.cluster.local。Linkerd 使用请求的 Host 头将服务配置文件与请求相关联。当代理看到 webapp.booksapp.svc.cluster.localHost 头时, 它将使用它来查找服务配置文件的配置。


路由是包含方法(例如 GET)和匹配路径的正则表达式的简单条件。这允许您将 REST 风格的资源组合在一起,而不是看到一个巨大的列表。路由的名称可以是您喜欢的任何名称。对于此 demo,该方法附加到路由正则表达式。

要获取 authorsbooks 的配置文件,您可以运行:


curl -sL https://run.linkerd.io/booksapp/authors.swagger \
  | linkerd -n booksapp profile --open-api - authors \
  | kubectl -n booksapp apply -f -
curl -sL https://run.linkerd.io/booksapp/books.swagger \
  | linkerd -n booksapp profile --open-api - books \
  | kubectl -n booksapp apply -f -


当您使用 linkerd viz tap 时,很容易验证这一切是否有效。每个实时请求都会显示正在看到的 :authorityHost 标头以及正在使用的 :pathrt_route。运行:


linkerd viz tap -n booksapp deploy/webapp -o wide | grep req


这将观察流经 webapp 的所有实时请求,看起来像:


req id=0:1 proxy=in  src=10.1.3.76:57152 dst=10.1.3.74:7000 tls=true :method=POST :authority=webapp.default:7000 :path=/books/2878/edit src_res=deploy/traffic src_ns=booksapp dst_res=deploy/webapp dst_ns=booksapp rt_route=POST /books/{id}/edit


As you can see:


  • :authority 是正确的 host
  • :path 正确匹配
  • rt_route 包含 route 名称

这些指标是 linkerd viz routes 命令的一部分, 而不是 linkerd viz stat。要查看到目前为止累积的指标,请运行:


linkerd viz -n booksapp routes svc/webapp


这将输出所有观察到的路由及其黄金指标的表。 [DEFAULT] 路由是所有与服务配置文件不匹配的所有内容。

配置文件可用于观察传出(outgoing)请求以及传入(incoming)请求。为此,请运行:


linkerd viz -n booksapp routes deploy/webapp --to svc/books


这将显示源自 webapp deployment 并发往 books 服务的所有请求和路由。与在调试部分使用 taptop 视图类似,此 demo 中错误的根本原因很明显:


ROUTE                     SERVICE   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99
DELETE /books/{id}.json     books   100.00%   0.5rps          18ms          29ms          30ms
GET /books.json             books   100.00%   1.1rps           7ms          12ms          18ms
GET /books/{id}.json        books   100.00%   2.5rps           6ms          10ms          10ms
POST /books.json            books    52.24%   2.2rps          23ms          34ms          39ms
PUT /books/{id}.json        books    41.98%   1.4rps          73ms          97ms          99ms
[DEFAULT]                   books         -        -             -             -             -


重试



由于更新代码和推出新版本可能需要一段时间,让我们告诉 Linkerd 它可以重试对失败端点的请求。这会 增加请求延迟,因为请求将被多次重试,并不需要推出新版本。

在这个应用中,从 books deployment 到 authors service 的请求成功率很低。要查看这些指标,请运行:


linkerd viz -n booksapp routes deploy/books --to svc/authors


输出应如下所示:


ROUTE                       SERVICE   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99
DELETE /authors/{id}.json   authors         -        -             -             -             -
GET /authors.json           authors         -        -             -             -             -
GET /authors/{id}.json      authors         -        -             -             -             -
HEAD /authors/{id}.json     authors    50.85%   3.9rps           5ms          10ms          17ms
POST /authors.json          authors         -        -             -             -             -
[DEFAULT]                   authors         -        -             -             -             -


有一点很清楚,从书籍到作者的所有请求都发送到 HEAD /authors/{id}.json 路由, 并且这些请求在大约 50% 的时间内失败。


为了更正这个问题,让我们编辑 authors 服务配置文件并使那些请求可重试,运行以下命令:


kubectl -n booksapp edit sp/authors.booksapp.svc.cluster.local


您需要将 isRetryable 添加到特定路由。它应该看起来像:


spec:
  routes:
  - condition:
      method: HEAD
      pathRegex: /authors/[^/]*\.json
    name: HEAD /authors/{id}.json
    isRetryable: true ### ADD THIS LINE ###


编辑服务配置文件后,Linkerd 将开始自动重试对该路由的请求。我们可以看到通过运行以下命令:


linkerd viz -n booksapp routes deploy/books --to svc/authors -o wide


这应该是这样的:


ROUTE                       SERVICE   EFFECTIVE_SUCCESS   EFFECTIVE_RPS   ACTUAL_SUCCESS   ACTUAL_RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99
DELETE /authors/{id}.json   authors                   -               -                -            -             -           0ms
GET /authors.json           authors                   -               -                -            -             -           0ms
GET /authors/{id}.json      authors                   -               -                -            -             -           0ms
HEAD /authors/{id}.json     authors             100.00%          2.8rps           58.45%       4.7rps           7ms          25ms          37ms
POST /authors.json          authors                   -               -                -            -             -           0ms
[DEFAULT]                   authors                   -               -                -            -             -           0ms


你会注意到 -o wide 标志在 routes 视图中添加了一些列。这些显示了 EFFECTIVE_SUCCESSACTUAL_SUCCESS 之间的区别。这两者之间的差异表明重试的效果如何。 EFFECTIVE_RPSACTUAL_RPS 显示有多少请求被发送到目标服务, 以及有多少请求被客户端的 Linkerd 代理接收。


现在自动重试,成功率看起来不错,但 p95 和 p99 延迟增加了。这是可以预料的,因为重试需要时间。


超时



Linkerd 可以限制在传出请求到另一个服务失败之前等待的时间。这些超时通过向服务配置文件的路由配置添加另一个 key 来工作。

首先,让我们看一下从 webappbooks 服务的请求的当前延迟:


linkerd viz -n booksapp routes deploy/webapp --to svc/books


这应该类似于:


ROUTE                     SERVICE   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99
DELETE /books/{id}.json     books   100.00%   0.7rps          10ms          27ms          29ms
GET /books.json             books   100.00%   1.3rps           9ms          34ms          39ms
GET /books/{id}.json        books   100.00%   2.0rps           9ms          52ms          91ms
POST /books.json            books   100.00%   1.3rps          45ms         140ms         188ms
PUT /books/{id}.json        books   100.00%   0.7rps          80ms         170ms         194ms
[DEFAULT]                   books         -        -             -             -             -


books 服务的 PUT /books/{id}.json 路由的请求包括当该服务调用 authors 服务 作为服务这些请求的一部分时的重试,如上一节所述。这以额外的延迟为代价提高了成功率。出于本 demo 的目的,让我们为对该路由的调用设置 25 毫秒超时。您的延迟数字将根据集群的特征而有所不同。要编辑 books 服务配置文件,请运行:


kubectl -n booksapp edit sp/books.booksapp.svc.cluster.local


更新 PUT /books/{id}.json 路由以设置超时:


spec:
  routes:
  - condition:
      method: PUT
      pathRegex: /books/[^/]*\.json
    name: PUT /books/{id}.json
    timeout: 25ms ### ADD THIS LINE ###


Linkerd 现在将在达到超时时将错误返回给 webapp REST 客户端。此超时包括重试请求,并且是 REST 客户端等待响应的最长时间。


运行 routes 以查看发生了什么变化:


linkerd viz -n booksapp routes deploy/webapp --to svc/books -o wide


现在发生超时,指标将发生变化:


ROUTE                     SERVICE   EFFECTIVE_SUCCESS   EFFECTIVE_RPS   ACTUAL_SUCCESS   ACTUAL_RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99
DELETE /books/{id}.json     books             100.00%          0.7rps          100.00%       0.7rps           8ms          46ms          49ms
GET /books.json             books             100.00%          1.3rps          100.00%       1.3rps           9ms          33ms          39ms
GET /books/{id}.json        books             100.00%          2.2rps          100.00%       2.2rps           8ms          19ms          28ms
POST /books.json            books             100.00%          1.3rps          100.00%       1.3rps          27ms          81ms          96ms
PUT /books/{id}.json        books              86.96%          0.8rps          100.00%       0.7rps          75ms          98ms         100ms
[DEFAULT]                   books                   -               -                -            -             -


延迟数字包括在 webapp 应用程序本身中花费的时间, 因此预计它们会超过我们为从 webappbooks 的请求设置的 25 毫秒超时。我们可以通过观察路由的有效成功率下降到 100% 以下来看到超时正在起作用。


清理



要从集群中删除 books 应用程序和 booksapp 命名空间,请运行:


curl -sL https://run.linkerd.io/booksapp.yml \
  | kubectl -n booksapp delete -f - \
  && kubectl delete ns booksapp


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
6天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
15天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
30 3
|
2月前
|
安全 网络协议 应用服务中间件
AJP Connector:深入解析及在Apache HTTP Server中的应用
【9月更文挑战第6天】在Java Web应用开发中,Tomcat作为广泛使用的Servlet容器,经常与Apache HTTP Server结合使用,以提供高效、稳定的Web服务。而AJP Connector(Apache JServ Protocol Connector)作为连接Tomcat和Apache HTTP Server的重要桥梁,扮演着至关重要的角色
74 2
|
3天前
|
缓存 安全 网络安全
HTTP/2与HTTPS在Web加速中的应用
HTTP/2与HTTPS在Web加速中的应用
|
12天前
|
缓存 安全 前端开发
HTTP 协议的请求方法在实际应用中有哪些注意事项?
【10月更文挑战第29天】HTTP协议的请求方法在实际应用中需要根据具体的业务场景和需求,合理选择和使用,并注意各种方法的特点和限制,以确保网络通信的安全、高效和数据的一致性。
|
16天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
17 3
|
16天前
|
网络协议 前端开发 API
HTTP 和 TCP 协议的应用场景有哪些不同
【10月更文挑战第25天】HTTP(超文本传输协议)和 TCP(传输控制协议)处于网络协议栈的不同层次,各自具有独特的功能和特点,因此它们的应用场景也存在明显的差异。
|
1月前
|
JavaScript 安全 Java
谈谈UDP、HTTP、SSL、TLS协议在java中的实际应用
下面我将详细介绍UDP、HTTP、SSL、TLS协议及其工作原理,并提供Java代码示例(由于Deno是一个基于Node.js的运行时,Java代码无法直接在Deno中运行,但可以通过理解Java示例来类比Deno中的实现)。
68 1
|
6月前
状态码对于理解HTTP请求和响应的流程,以及调试网络问题非常重要
【5月更文挑战第15天】HTTP状态码由三位数字表示,分为1xx-5xx五类。1xx为信息响应,2xx表示成功,如200(请求成功)、201(创建成功)。3xx是重定向,如301(永久移动)、302(临时重定向)。4xx表示客户端错误,如400(坏请求)、404(未找到)。5xx是服务器错误,包括500(内部服务器错误)和503(服务不可用)。这些状态码用于理解请求响应流程和调试网络问题。
74 1
|
2月前
|
安全 网络安全 数据安全/隐私保护
HTTP与HTTPS协议区别及应用场景
在互联网高速发展的今天,HTTP与HTTPS作为数据传输的基石,作用至关重要。HTTP允许客户端与服务器间传输超文本文档,但其数据传输过程未加密,存在安全隐患;HTTPS则在此基础上加入了SSL/TLS协议,实现了数据加密传输,增强了安全性,广泛应用于电子商务、网上银行、政府网站及社交媒体平台等涉及敏感信息传输的领域,有效保护了用户隐私和数据安全。随着网络安全意识提升,HTTPS正逐渐成为主流。