By Xin Wei, Higress Committer
This article aims to review how Spring Cloud Gateway fulfills the scenarios of HTTP request or response transformation requirements. It will also introduce the solution of using the Higress cloud-native gateway in such scenarios and provide a performance comparison between the two.
In Spring Cloud Gateway (SCG) [1], when we need to modify the HTTP request or response, SCG provides many built-in GatewayFilter [2] to meet our needs for such application scenarios, such as AddRequestHeader, AddRequestParameter, DedupeResponseHeader, MapRequestHeader, ModifyRequestBody.
Consider the following simple use case:
• Add the request header X-First and obtain the value from the request path. For example, obtain response-headers
from /response-headers?testKey=testValue
.
• Map the value of the request header X-First to X-Second.
• Add the request query parameter k1=v1.
• Eliminate duplicate response header X-Dedupe.
To use GatewayFilter in SCG, we can configure as follows:
# 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
For those of you with experience using SCG must be familiar with the above configuration. Therefore, this article will focus on providing an alternative solution that not only meets the above requirements but also performs better - utilizing the Transformer plugin of the Higress cloud-native gateway.
At the same throughput level (QPS), we enable or disable the Higress Transformer plug-in [3] and the corresponding GatewayFilters of the SCG to calculate the CPU and memory overheads of the two.
After the test [13], we have come to the following conclusions:
• Under the condition that Higress does not enable Transformer plug-in and SCG does not enable GatewayFilters, the CPU and memory resource overheads of SCG are about 3.30 and 4.88 times that of Higress, respectively.
• Under the condition that Higress enables Transformer plug-in and SCG enables GatewayFilters, the CPU and memory resource overheads of SCG are about 2.98 and 3.19 times that of Higress, respectively.
This shows that Higress Transformer has a very good performance compared with SCG GatewayFilter!
Next, we will further introduce the Higress cloud-native gateway and the Higress Transformer plug-in mentioned above.
Higress [4] is a next-generation cloud-native gateway built based on the practices of Envoy Gateway in Alibaba. It is built with open source Istio and Envoy as the core. It implements the three-in-one high integration capability of traffic gateway, microservice gateway, and security gateway. It is deeply integrated with microservice technology stacks such as Dubbo, Nacos, and Sentinel, which can help users greatly reduce the deployment and O&M costs of gateways without sacrificing capabilities. Ingress and Gateway APIs are fully supported in terms of standards, and standard API specifications under cloud native are actively embraced. In addition, the Higress controller also supports smooth migration of NGINX Ingress, helping users migrate to Higress at zero cost quickly.
Higress provides a Wasm (WebAssembly) SDK (Software Development Kit) [5]so that developers can easily use C++, Golang, and Rust to develop Wasm plug-ins to enhance gateway capabilities. In the following section, I will describe the basic functions of the Higress Transformer plug-in and conclude with a brief description of the core code logic of the Transformer plug-in.
The Higress Transformer plug-in can transform request or response headers, request query parameters, and request or response body parameters. The types of transformation operations supported include remove, rename, replace, add, append, map, and dedupe.
Next, we will reproduce the simple use case of SCG GatewayFilter mentioned at the beginning to demonstrate how to use the plug-in (The plug-in can be easily deployed using the Higress console. It can also be deployed through Kubernetes YAML Manifests[12]):
1. First, quickly install Higress according to the official document [6]. The results are as follows:
$ 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. In the Higress console, add a domain name (foo.bar.com) and a route configuration (foo) to forward traffic to the backend httpbin [7] service.
3. Add the Transformer plug-in to the foo route. The plug-in is not pushed to the official image repository. You can use docker.io/weixinx/transformer:v0.1.0 or go to the code repository to build the plug-in.
Note: In order to be able to complete the request and response transformation at the same time, we need to add another Transformer plug-in for the foo route, named transformer-resp, to handle the response direction.
4. Add the Transformer configuration and enable the plug-in:
• Add the request header X-First and obtain the value from the request path. For example, obtain response-headers
from /response-headers?testKey=testValue
.
• Map the value of the request header X-First to X-Second.
• Add the request query parameter k1=v1.
• Eliminate duplicate response header X-Dedupe.
# transformer:
type: request # Specify the Transformer type.
rules: # Specify the transformation rule.
- operate: add # Specify the type of the transformation operation.
headers: # Specify the header transformation rules.
- key: X-First
value: $1 # The regular expression capture group $1. The RE2 syntax is supported.
path_pattern: ^\/(\w+)[\?]{0,1}.*$
querys: # Specify the transformation rules of query parameters.
- 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. Send a request for testing:
# Verify the request direction transformation.
$ curl -v -H "host: foo.bar.com" "console.higress.io/get"
...
>
< HTTP/1.1 200 OK
...
<
{
"args": {
# The query parameter k1=v1 is added.
"k1": "v1"
},
"headers": {
...
"X-First": "get", # The request header X-First is added. The value "get" is from the request path.
"X-Second": "get" # The request header X-Second is mapped.
},
...
# The query parameter k1=v1 is added.
"url": "http://foo.bar.com/get?k1=v1"
}
# Verify the response direction transformation.
$ 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 # The first value of the response header X-Dedupe is retained.
...
<
{
...
# Custom response headers passed to httpbin using query parameters.
"X-Dedupe": [
"1",
"2",
"3"
],
...
}
❗It should be noted that:
• Same as the preceding example, if there is a need to process both request and response transformation, you need to add two Transformer plug-ins for the corresponding route to process the request direction and response direction respectively (being optimized).
• The request body supports the following Content-Types: application/json, application/x-www-form-urlencoded, and multipart/form-data. The response body only supports application/json.
• For more instructions, see the plug-in documentation [3].
In this section, I will briefly explain the core code logic of the Higress Transformer plug-in, hoping to provide some help for some of you who are interested in optimizing the plug-in or performing secondary development.
First, the plug-in code is located in the plugins/wasm-go/extensions/transformer directory of the Higress repository and is developed by using the Wasm SDK [5] provided by Higress (For more information about how to develop the Wasm plug-in, see the official documentation [8] ).
The configuration model for the plug-in, TransformerConfig:
# The model is exposed to the user in the form of the plug-in configuration.
type TransformerConfig struct {
typ string # Transformer type, [request, response].
rules []TransformRule # Transformation rules.
trans Transformer # A Transformer instance which does not expose configurations to users and is used for actual transformation operations.
}
}
type TransformRule struct {
operate string # The type of the transformation operations.
headers []Param # The header parameter.
querys []Param # The query parameter.
body []Param # The body parameter.
}
type Param struct {
key string # Indicates the key of the field.
value string # Indicates the value or key (map) or strategy (dedupe) of the field.
valueType string # Specify the data type of value for the application/json body.
hostPattern string # host Regular matching pattern
pathPattern string # path Regular matching pattern
}
Among them, Transformer as an interface has two implementations, requestTransformer and responseTransformer, and mainly implements three interface methods, TransformHeaders, TransformerQuerys, and 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)
Both headers and query parameters are key-value pairs. Therefore, the unified processing logic is adopted by kvHandler to process them. The request and response body support different Content-Types. Therefore, they are processed by requestBodyHandler (the combination of kvHandler and jsonHandler) and responseBodyHandler (jsonHandler), respectively. To sum up, when modifying the plug-in logic, you mainly need to modify kvHandler and jsonHandler, where jsonHandler depends on the GJSON [9] and SJSON [10] tool libraries.
Currently, the transformation sequence in the handler is hard-coded (remove -> rename -> replace -> add -> append -> map -> dedupe). We have plans to optimize this sequence, and we welcome those who are interested to participate in the project.
In this article, I introduced the Higress Transformer plugin and compared its performance with Spring Cloud Gateway. I also explained the core logic of the plugin's code, with the hope of assisting you in smoothly migrating from Spring Cloud Gateway to 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 plug-in
https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/transformer
[4] Higress official documentation
https://higress.io/en-us/
[5] Higress Wasm SDK
https://github.com/alibaba/higress/tree/main/plugins
[6] Higress quick start
https://higress.io/en-us/docs/user/quickstart/
[7] httpbin
https://httpbin.org/
[8] Develop the Higress Wasm plug-in
https://higress.io/en-us/docs/user/wasm-go/
[9] GJSON
https://github.com/tidwall/gjson
[10] SJSON
https://github.com/tidwall/sjson
[11] Higress code repository
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] Performance comparison configuration
https://gist.github.com/WeixinX/c24f4ded37832dd7e753b2d27470f0fc
508 posts | 49 followers
FollowAlibaba Cloud Native Community - April 11, 2024
Alibaba Cloud Native Community - May 14, 2024
Alibaba Cloud Native Community - September 12, 2023
Alibaba Cloud Native Community - April 4, 2023
Alibaba Cloud Native Community - July 20, 2023
Alibaba Cloud Community - April 19, 2024
508 posts | 49 followers
FollowMulti-source metrics are aggregated to monitor the status of your business and services in real time.
Learn MoreBuild business monitoring capabilities with real time response based on frontend monitoring, application monitoring, and custom business monitoring capabilities
Learn MoreOrganize and manage your resources in a hierarchical manner by using resource directories, folders, accounts, and resource groups.
Learn MoreAutomate performance monitoring of all your web resources and applications in real-time
Learn MoreMore Posts by Alibaba Cloud Native Community