七爪源码:使用 Toxiproxy 进行弹性测试

七爪源码:使用 Toxiproxy 进行弹性测试 - 知乎

们现在构建的软件通常比 10 或 20 年前的软件复杂得多。 传统的 LAMP 堆栈或三层单体通常已被丢弃,取而代之的是微服务架构,并由某种编排平台(如 Kubernetes)提供支持。 让我们继续讨论在大多数情况下是否真的需要这种额外的复杂性(剧透——恕我直言,它可能不是),并承认这些先进的架构带来了很多好处,但也带来了很多额外的问题。

问题在于,在任何复杂的系统中——一个有许多活动部件的系统,尤其是当分布在网络中时——故障变得司空见惯。我找不到那句话,但(套用一下)一段时间前我脑海中浮现的一句话——

在任何足够复杂的软件系统中,几乎不可能所有部分都始终正常工作。故障总是发生在系统的某个地方。

 

失败工程

鉴于此,只考虑晴天场景的编码是愚蠢的。这不是新闻。故障注入和混沌工程的整个学科已经变得司空见惯,以确保我们识别和修补可能存在的漏洞。

我们可以在这里选择许多工具,从 Chaos Monkey 的祖先到更现代的 SaaS 产品(如 Gremlin),甚至是平台本身内置的工具,例如。伊斯蒂奥。

不过,在这种情况下,我们不会讨论这些重量级人物,而是一个有用的小工具,当网络上发生某些异常或错误情况时,我们可以使用它来验证我们编写的代码是否具有弹性。

 

Toxiproxy

Toxiproxy 是一种轻量级的故障注入网络代理,最初由 Shopify 开发(并广泛使用)。 Toxiproxy 可用于模拟某些网络条件,它非常适合我们想要控制的情况——特别是对于 CI、测试和测试环境。它不会从概率上拆除我们的基础设施,但非常适合测试关键环境。

让我们看一些我们可以使用 Toxiproxy 模拟的场景。然而,首先,我们需要将它连接到某些东西上。

 

基线

让我们先将 Toxiproxy 放在 Simple JSON/plain-text API to obtain the current time in, and related data about, a timezone. 前面,这是一个告诉我们时间的开放 API。例如,英国的(写作)时间是:

curl -s 'http://worldtimeapi.org/api/timezone/Europe/London' | jq
{
  "abbreviation": "BST",
  "client_ip": "195.94.111.1",
  "datetime": "2022-07-04T07:08:42.499494+01:00",
  "day_of_week": 1,
  "day_of_year": 185,
  "dst": true,
  "dst_from": "2022-03-27T01:00:00+00:00",
  "dst_offset": 3600,
  "dst_until": "2022-10-30T01:00:00+00:00",
  "raw_offset": 0,
  "timezone": "Europe/London",
  "unixtime": 1656914922,
  "utc_datetime": "2022-07-04T06:08:42.499494+00:00",
  "utc_offset": "+01:00",
  "week_number": 27
}

我们需要一种一致的方法来测试通过 Toxiproxy 运行的流量,因此我们将使用 Gatling(一个众所周知的性能测试工具),将请求限制为每秒 - 我主要希望它用于漂亮的图表而不是绝对垃圾 API .

Gatling 的基本案例图表显示了一个健康的系统。 60 个请求,没有失败,99% 的响应时间为 63 毫秒——还不错。

 

增加一秒钟的延迟

我们的第一个失败案例是让事情变慢。

Toxiproxy 允许您注入称为“毒物”的行为。 可以想象,有毒物质会污染具有不良特性的 API。 每种有毒物质都有几个关键方面:

  • type — 我们要应用的行为的类型
  • stream——我们想要应用行为的 api/service
  • toxicity——我们应该应用该行为的请求的百分比(0 到 1 之间的数字)
  • attributes — 类型特定参数,进一步改变有毒物质的行为。

为了在我们的 API 调用中注入缓慢,我们将利用延迟毒性并将延迟设置为一秒。 这将应用于所有请求(毒性为 1)。 我们可以通过对 Toxiproxy 的 API 调用来设置它。 让我们试试看。

curl --location --request POST 'http://localhost:8474/proxies/time/toxics' \
--header 'Content-Type: text/plain' \
--data-raw '{
        "name": "latency",
        "type": "latency",
        "stream": "upstream",
        "toxicity": 1.0,
        "attributes": {
            "latency": 1000,
            "jitter": 0
        }
    }'

将结果与基线进行比较,您会发现 Toxiproxy 已明显启动。 我们将响应时间向上移动了一秒(加特林将超过 800 毫秒的任何内容标记为警告,因此以黄色突出显示)。 一个好的开始,现在我们还能做什么?

 

延迟增加 0-2 秒(抖动)

缓慢的上游服务通常是不可预测的。 我们真正想要的是响应时间的差异。 我们可以通过利用 jitter 属性来实现这一点,给响应带来随机感。 抖动会在我们设置的基线上增加或减少额外的延迟。 我们现在应该看到添加了 0 毫秒到 2000 毫秒之间的延迟。

curl --location --request POST 'http://localhost:8474/proxies/time/toxics' \
--header 'Content-Type: text/plain' \
--data-raw '{
        "name": "latency",
        "type": "latency",
        "stream": "upstream",
        "toxicity": 1.0,
        "attributes": {
            "latency": 1000,
            "jitter": 1000
        }
    }'

这次响应时间分布更广,从最小的 129ms 到另一边的 4693。

 

使用 RESET_PEER 失败 ~ 一半的上游请求

如果我们想完全拒绝一个请求,模拟一个失败的网络状况怎么办? 我们可以使用 reset_peer 毒性来做到这一点。

让我们添加有毒物质,但只有 50% 的时间(平均)使用它。 在拒绝请求之前,我们还将使失败的响应挂起 5 秒。

curl --location --request POST 'http://localhost:8474/proxies/time/toxics' \
--header 'Content-Type: text/plain' \
--data-raw '{
        "name": "reset_peer",
        "type": "reset_peer",
        "stream": "upstream",
        "toxicity": 0.5,
        "attributes": {
            "timeout": 5000
        }
    }'

不完全是 50% 的失败率,但这是有道理的概率。 不过,您肯定可以看到效果,包括我们在失败调用中添加的 5 秒挂起 — 查看 max 和 std dev 字段。

 

数据包拆分

我们的最后一个例子——对于这么小的请求来说并不是特别容易演示的——是数据包拆分。 通过将 TCP 请求拆分为许多较小的请求,我们可以通过另一种方式模拟网络上的奇怪行为,尽管在这种情况下,它主要只是另一种导致延迟的方式。

我们将使用有毒的切片器将我们的请求分成 2 到 6 个字节的数据包,给它们每个大约 500 毫秒的延迟。

curl --location --request POST 'http://localhost:8474/proxies/time/toxics' \
--header 'Content-Type: text/plain' \
--data-raw '{
        "name": "slicer",
        "type": "slicer",
        "stream": "upstream",
        "toxicity": 0.5,
        "attributes": {
            "average_size": 4,
            "size_variation": 2,
            "delay": 500000
        }
    }'

同样,我们的响应差异很大。 清楚地将这些请求分成许多数据包(有些有延迟),可以将我们的响应时间从低端的 176 毫秒扩展到最大超过 10 秒。

 

结论

Toxiproxy 是一个很好的小工具,可以帮助您强制网络错误并帮助您提高应用程序的弹性,希望我们已经在这里展示了这一点。 无论如何,它肯定不是一个全面的混沌工程套件——它也不假装是——而是一种在该领域获得快速胜利的方法。

posted @ 2025-12-11 17:58  CharyGao  阅读(0)  评论(0)    收藏  举报