通过 Higress Wasm 插件 3 倍性能实现 Spring-cloud-gateway 功能

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
云原生网关 MSE Higress,422元/月
性能测试 PTS,5000VUM额度
简介: 通过 Higress Wasm 插件 3 倍性能实现 Spring-cloud-gateway 功能

作者:韦鑫,Higress Committer,来自南京航空航天大学分布式系统实验室


导读:本文将和大家一同回顾 Spring Cloud Gateway 是如何满足 HTTP 请求/响应转换需求场景的,并为大家介绍在这种场景下使用 Higress 云原生网关的解决方案,同时还对比了两者的性能差异。


01 SCG 修改请求/响应


在 Spring Cloud Gateway[1](以下简称为 SCG) 中,当我们需要对 HTTP 请求或响应进行修改时,SCG 提供了许多内置的 GatewayFilter[2]来满足我们对这种应用场景的需求,例如 AddRequestHeader,AddRequestParameter, DedupeResponseHeader,MapRequestHeader, ModifyRequestBody 等。


考虑以下简单用例:


  • 添加请求头部 X-First,值从请求路径中获取,例如从 /response-headers?testKey=testValue 中获取 "response-headers";
  • 将请求头部 X-First 的值映射给 X-Second;
  • 添加请求查询参数 k1=v1;
  • 剔除重复的响应头部 X-Dedupe。


在 SCG 中使用 GatewayFilter 我们可以这样配置:


# application.yaml:
spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: lb://httpbin-svc
          predicates:
            - Path=/{api}/**
          filters:
            - AddRequestHeader=X-First, {api}
            - MapRequestHeader=X-First, X-Second
            - AddRequestParameter=k1, v1
            - DedupeResponseHeader=X-Dedupe, RETAIN_FIRST


相信拥有 SCG 使用经验的同学对上述配置一定不陌生,那么本文将重点给出另一种能够满足上述需求并且性能更加优越的解决方案——使用 Higress 云原生网关的 Transformer 插件。


02 Higress 插件与 SCG 性能比较


我们在同一吞吐量水平(QPS)上,开启/关闭 Higress Transformer 插件[3]和 SCG 相应 GatewayFilters,统计两者在 CPU 和内存资源上的开销。


经过测试[13],我们得到的结论是:


  • 在 Higress 未启用 Transformer 插件,SCG 未启用 GatewayFilters 的条件下,SCG 的 CPU, 内存资源开销分别约为 Higress的 3.30, 4.88倍;
  • 在 Higress 启用 Transformer 插件,SCG 启用相应 GatewayFilters 的条件下,SCG 的 CPU,内存资源开销分别约为 Higress 的 2.98, 3.19倍。




可见 Higress Transformer 相比于 SCG GatewayFilter 有着相当不错的性能表现!


接下来我们将进一步为大家介绍 Higress 云原生网关以及上述提到的 Higress Transformer 插件。


03 Higress 简介


Higress[4]是基于阿里内部的 Envoy Gateway 实践沉淀、以开源 Istio + Envoy 为核心构建的下一代云原生网关,实现了流量网关+微服务网关+安全网关三合一的高集成能力,深度集成 Dubbo、Nacos、Sentinel 等微服务技术栈,能够帮助用户极大地降低网关的部署及运维成本且能力不打折;在标准上全面支持 Ingress 与 Gateway API,积极拥抱云原生下的标准 API 规范;同时,Higress Controller 也支持 Nginx Ingress 平滑迁移,帮助用户零成本快速迁移到 Higress。


Higress 提供了一套 Wasm (WebAssembly) SDK[5],使得开发者能够轻松使用 C++,Golang,Rust 开发 Wasm 插件增强网关能力。下面将为大家介绍 Higress Transformer 插件的基本功能,最后简单说明 Transformer 插件的核心代码逻辑。



04 Transformer 插件介绍


Higress Transformer 插件可以对请求/响应头部、请求查询参数、请求/响应体参数进行转换,支持的转换操作类型包括删除(remove)、重命名(rename)、更新(replace)、添加(add)、追加(append)、映射(map)和去重(dedupe)。


接下来我们复现最开始提到的 SCG GatewayFilter 简单用例,来演示如何使用该插件(以下使用 Higress 控制台可以很方便地部署插件,当然也可以使用 K8s YAML Manifests 的方式[12]):


1. 首先根据官方文档[6]快速安装 Higress,结果如下:


$ kubectl -n higress-system get deploy
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
higress-console              1/1     1            1           1d
higress-console-grafana      1/1     1            1           1d
higress-console-prometheus   1/1     1            1           1d
higress-controller           1/1     1            1           1d
higress-gateway              1/1     1            1           1d


2. 通过 Higress 控制台添加域名(foo.bar.com)、路由配置(foo),将流量转发至后端的 httpbin[7]服务:




3. 为 foo 路由添加 Transformer 插件(当前未推送插件至官方镜像仓库,可以先使用 docker.io/weixinx/transformer:v0.1.0,或到代码仓库自行构建):



注:为了能够同时完成请求和响应转换的需求,我们需要为 foo 路由再添加一个 Transformer 插件,命名为 transformer-resp,用于处理响应方向。


4. 添加 Transformer 配置并开启该插件:


  • 添加请求头部 X-First,值从请求路径中获取,例如从 /response-headers?testKey=testValue 中获取 "response-headers";
  • 将请求头部 X-First 的值映射给 X-Second;
  • 添加请求查询参数 k1=v1;
  • 剔除重复的响应头部 X-Dedupe。


# transformer:
type: request  # 指定 Transformer 类型
rules:         # 指定转换规则
- operate: add # 指定转换操作类型
  headers:     # 指定头部转换规则
  - key: X-First
    value: $1  # 正则表达式捕获组 $1,支持 RE2 语法
    path_pattern: ^\/(\w+)[\?]{0,1}.*$
  querys:      # 指定查询参数转换规则
  - key: k1
    value: v1
- operate: map
  headers:
  - key: X-First
    value: X-Second
---
# transformer-resp:
type: response
rules:
- operate: dedupe
  headers:
  - key: X-Dedupe
    value: RETAIN_FIRS


5. 发送请求进行测试:


# 验证请求方向转换
$ curl -v -H "host: foo.bar.com" "console.higress.io/get"
...
>
< HTTP/1.1 200 OK
...
<
{
  "args": {
    # 添加了查询参数 k1=v1
    "k1": "v1"
  },
  "headers": {
    ...
    "X-First": "get", # 添加了请求头部 X-First,值 "get" 来自请求路径
    "X-Second": "get" # 映射了请求头部 X-Second
  },
  ...
  # 添加了查询参数 k1=v1
  "url": "http://foo.bar.com/get?k1=v1"
}
# 验证响应方向转换
$ curl -v -H "host: foo.bar.com" \
"console.higress.io/response-headers?X-Dedupe=1&X-Dedupe=2&X-Dedupe=3"
...
>
< HTTP/1.1 200 OK
< x-dedupe: 1 # 保留了响应头部 X-Dedupe 的第一个值
...
<
{
  ...
  # 通过查询参数传给 httpbin 的自定义响应头部
  "X-Dedupe": [
    "1",
    "2",
    "3"
  ],
  ...
}


❗️需要注意的是:


  • 与上述例子相同,若有同时处理请求和响应转换的需求,则需要为相应路由添加两个 Transformer 插件,分别处理请求方向和响应方向(正在优化);
  • 请求体支持的 Content-Type 有:application/json,application/x-www-form-urlencoded,multipart/form-data;而响应体仅支持 application/json;
  • 更多说明详见插件文档[3]


05 Transformer 逻辑


本节将简单说明 Higress Transformer 插件的核心代码逻辑,希望可以为有兴趣优化该插件或进行二次开发的同学提供一些帮助。


首先该插件代码位于Higress 仓库的 plugins/wasm-go/extensions/transformer 目录下,使用 Higress 提供的 Wasm SDK[5]进行开发(关于如何开发 Wasm 插件详见官方文档[8])。


插件的配置模型 TransformerConfig:


# 模型以插件配置的形式暴露给用户
type TransformerConfig struct {
  typ   string          # Transformer 类型,[request, response]
  rules []TransformRule # 转换规则
  trans Transformer # Transformer 实例,不对用户暴露配置,用于实际的转换操作
}
type TransformRule struct {
  operate string   # 转换操作类型
  headers []Param  # header 参数 
  querys  []Param  # query 参数
  body    []Param  # body 参数
}
type Param struct {
  key         string # 表示字段的 key
  value       string # 表示字段的 value 或 key (map) 或 strategy (dedupe)
  valueType   string # 为 application/json body 指定 value 的数据类型
  hostPattern string # host 正则匹配模式
  pathPattern string # path 正则匹配模式
}


其中 Transformer 作为接口分别有请求和响应两个实现(requestTransformer, responseTransformer),主要实现了 3 个接口方法 TransformHeaders,TransformerQuerys 和 TransformBody:


type Transformer interface {
 TransformHeaders(host, path string, hs map[string][]string) error
 TransformQuerys(host, path string, qs map[string][]string) error
 TransformBody(host, path string, body interface{}) error
 ...
}
var _ Transformer = (*requestTransformer)(nil)
var _ Transformer = (*responseTransformer)(nil)


由于头部(Headers)和查询参数(Querys)都是以 key-value 的形式存在,因此通过 kvHandler 对两者采用统一的处理逻辑;而 Body 由于请求、响应支持不同的 Content-Type,因此分别通过 requestBodyHandler (kvHandler,jsonHandler 组合)和 responseBodyHandler (jsonHandler) 进行处理。综上,在修改该插件逻辑时,主要对kvHandler 和 jsonHandler 进行修改即可,其中 jsonHandler 依赖 GJSON[9]和 SJSON[10]工具库。



目前 handler 中的转换顺序是被硬编码的(remove -> rename -> replace -> add -> append -> map -> dedupe),我们对此有优化的打算,也欢迎感兴趣的同学参与进来 ~


06 总结


本文带大家了解了 Higress Transformer 插件,并与 Spring Cloud Gateway 进行了性能比较,在文章的最后还说明了该插件的核心代码逻辑,希望能够为大家从 Spring Cloud Gateway 迁移至 Higress 提供帮助!



如果您觉得 Higress 对您有帮助,欢迎前往 Github: Higress[11]为我们 star⭐️ 一下!期待与您在 Higress 社区相遇 ~


相关链接:

[1] Spring Cloud Gateway

https://cloud.spring.io/spring-cloud-gateway/reference/html/

[2] SCG GatewayFilter Factories

https://cloud.spring.io/spring-cloud-gateway/reference/html/#gatewayfilter-factories

[3] Higress Transformer 插件

https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/transformer

[4] Higress 官方文档

https://higress.io/zh-cn/

[5] Higress Wasm SDK

https://github.com/alibaba/higress/tree/main/plugins

[6] Higress 快速开始

https://higress.io/zh-cn/docs/user/quickstart

[7] httpbin

https://httpbin.org/

[8] 开发 Higress Wasm 插件

https://higress.io/zh-cn/docs/user/wasm-go

[9] GJSON

https://github.com/tidwall/gjson

[10] SJSON

https://github.com/tidwall/sjson

[11] Higress 代码仓库

https://github.com/alibaba/higress

[12] Transformer Demo

https://github.com/higress-group/higress-demo/tree/main/wasm-demo/wasm-demo-go/wasm-plugin-transformer

[13] 性能对比配置

https://gist.github.com/WeixinX/c24f4ded37832dd7e753b2d27470f0fc

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
21天前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
|
14天前
|
Java UED 开发者
Spring Boot 降级功能的神秘面纱:Hystrix 与 Resilience4j 究竟藏着怎样的秘密?
【8月更文挑战第29天】在分布式系统中,服务稳定性至关重要。为应对故障,Spring Boot 提供了 Hystrix 和 Resilience4j 两种降级工具。Hystrix 作为 Netflix 的容错框架,通过隔离依赖、控制并发及降级机制增强系统稳定性;Resilience4j 则是一个轻量级库,提供丰富的降级策略。两者均可有效提升系统可靠性,具体选择取决于需求与场景。在面对服务故障时,合理运用这些工具能确保系统基本功能正常运作,优化用户体验。以上简介包括了两个工具的简单示例代码,帮助开发者更好地理解和应用。
37 0
|
2月前
|
缓存 监控 Java
优化Spring Boot应用的数据库访问性能
优化Spring Boot应用的数据库访问性能
|
8天前
|
NoSQL 前端开发 Java
使用 Spring Boot + Neo4j 实现知识图谱功能开发
在数据驱动的时代,知识图谱作为一种强大的信息组织方式,正逐渐在各个领域展现出其独特的价值。本文将围绕使用Spring Boot结合Neo4j图数据库来实现知识图谱功能开发的技术细节进行分享,帮助读者理解并掌握这一技术栈在实际项目中的应用。
56 4
|
13天前
|
机器学习/深度学习 文字识别 前端开发
基于 Spring Boot 3.3 + OCR 实现图片转文字功能
【8月更文挑战第30天】在当今数字化信息时代,图像中的文字信息越来越重要。无论是文档扫描、名片识别,还是车辆牌照识别,OCR(Optical Character Recognition,光学字符识别)技术都发挥着关键作用。本文将围绕如何使用Spring Boot 3.3结合OCR技术,实现图片转文字的功能,分享工作学习中的技术干货。
37 2
|
13天前
|
安全 Java 应用服务中间件
如何在 Spring Boot 3.3 中实现请求 IP 白名单拦截功能
【8月更文挑战第30天】在构建Web应用时,确保应用的安全性是至关重要的。其中,对访问者的IP地址进行限制是一种常见的安全措施,特别是通过实施IP白名单策略,可以只允许特定的IP地址或IP段访问应用,从而有效防止未授权的访问。在Spring Boot 3.3中,我们可以通过多种方式实现这一功能,下面将详细介绍几种实用的方法。
20 1
|
14天前
|
算法 Java UED
你的Spring Boot应用是否足够健壮?揭秘限流功能的实现秘诀
【8月更文挑战第29天】限流是保障服务稳定性的关键策略,通过限制单位时间内的请求数量防止服务过载。本文基于理论介绍,结合Spring Boot应用实例,展示了使用`@RateLimiter`注解和集成`Resilience4j`库实现限流的方法。无论采用哪种方式,都能有效控制请求速率,增强应用的健壮性和用户体验。通过这些示例,读者可以灵活选择适合自身需求的限流方案。
30 2
|
14天前
|
Prometheus 监控 Cloud Native
Spring Boot 性能护航!Prometheus、Grafana、ELK 组合拳,点燃数字化时代应用稳定之火
【8月更文挑战第29天】在现代软件开发中,保证应用性能与稳定至关重要。Spring Boot 作为流行的 Java 框架,结合 Prometheus、Grafana 和 ELK 可显著提升监控与分析能力。Prometheus 负责收集时间序列数据,Grafana 将数据可视化,而 ELK (Elasticsearch、Logstash、Kibana)则管理并分析应用日志。通过具体实例演示了如何在 Spring Boot 应用中集成这些工具:配置 Prometheus 获取度量信息、Grafana 显示结果及 ELK 分析日志,从而帮助开发者快速定位问题,确保应用稳定高效运行。
30 1
|
21天前
|
SQL 存储 OLAP
OneSQL OLAP实践问题之Flink SQL Gateway的功能如何解决
OneSQL OLAP实践问题之Flink SQL Gateway的功能如何解决
24 1
|
2月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14578 23