×
Community Blog Implement Spring-cloud-gateway Using Higress Wasm Plug-in

Implement Spring-cloud-gateway Using Higress Wasm Plug-in

This article reviews how Spring Cloud Gateway fulfills the scenarios of HTTP request or response transformation requirements.

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.

Use SCG to Modify Request or Response

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.

Performance Comparison Between Higress Plug-in and SCG

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.

1
2

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.

Introduction to Higress

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.

3

Introduction to 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.

4
5

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.

6

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].

Transformer Logic

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.

7

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.

Summary

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!

Reference

[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

0 1 0
Share on

You may also like

Comments