This article introduces the features of Apache APISIX and GraphQL, how to use the API gateway Apache APISIX to proxy GraphQL requests, and proposes solutions to solve the pain points of practical scenarios.

Background Information

GraphQL is an open source, API-oriented data query operation language and corresponding runtime environment. Originally developed internally by Facebook in 2012, it was released publicly in 2015. On November 7, 2018, Facebook transferred the GraphQL project to the newly formed GraphQL Foundation.

You can understand GraphQL by analogy with SQL query statements. Compared with SQL query statements, GraphQL provides a complete set of easy-to-understand descriptions for the data in the API, allowing clients to obtain exactly what they need through custom descriptions The data. This also allows the API to cope with the development of increasingly complex interfaces without ending up with a dauntingly complex interface.

As a cloud native gateway, Apache APISIX has the matching ability to recognize GraphQL syntax from the beginning of its design. Through efficient matching of GraphQL statements carried in requests, abnormal traffic is filtered out to further ensure security and improve system performance.

scene analysis

We are in the era of big data and large traffic. Apache APISIX and GraphQL can be combined to form a win-win situation. The following is a detailed description of a scenario.

This article will discuss the practical application of Apache APISIX and GraphQL in the context of microservice architecture.

Problems encountered in actual scenarios

When the project is in the late stage, there are often problems of business complexity and high mobility of team personnel, and the microservice architecture has become a common solution to such problems. In the microservice architecture, the interfaces exposed by GraphQL are divided into two types: decentralized and centralized. However, only centralized interface design can maximize the advantages of GraphQL. However, in centralized interface design, all microservices are exposed to the outside world. is the same interface, , so the routing that handles traffic cannot simply be forwarded based on the URL, but should be forwarded based on different fields included in the request .

Because NGINX only processes URLs and some parameters when processing requests, but only by parsing the query information in the request parameters can the resources accessed by the client be known and routed forwarding. Therefore, this route and forwarding method cannot be completed by traditional NGINX. . In practical application scenarios, it is very dangerous to directly expose the GraphQL interface, so a professional high-performance API gateway is required to protect the GraphQL interface.

solution

Based on the security, stability and high performance of Apache APISIX, adding flexible routing matching rules of GraphQL is the best solution to the problem of centralized interface design of GraphQL.

Pasting blocks outside Docs is not supported

In this scheme, Apache APISIX is deployed as an API gateway before GraphQL Server, which provides security for the entire back-end system, and Apache APISIX filters some requests according to its own GraphQL matching function, and then processes them by GraphQL Server, so that The whole process of requesting resources becomes more efficient.

Thanks to the dynamic features of Apache APISIX, you can enable plug-ins such as current limiting, authentication, and observability without restarting services, which further improves the operating efficiency of this solution and facilitates operation and maintenance.

In addition, Apache APISIX can also perform different permission checks for different graphql_operation , and forward to different Upstreams for different graphql_name . The specific details will be described below.

summary , the Apache APISIX + GraphQL of solve program , in make full use of the advantages of search GraphQL while owning the Apache APISIX as the API security gateway provided in and stability .

GraphQL in Apache APISIX

basic logic

Pasting blocks outside Docs is not supported

The current execution logic of GraphQL in Apache APISIX is as follows:

  1. Clients make requests with GraphQL statements to Apache APISIX;
  2. Apache APISIX matches routes and extracts preset GraphQL data;
  3. Apache APISIX matches request data with preset GraphQL data;

    1. If the match is successful, Apache APISIX will continue to forward the request;
    2. If the match fails, Apache APISIX will immediately terminate the request.
  4. Whether there is a plugin;

    1. If there is a plugin, the request will continue to be processed by the plugin, and after the processing is complete, it will continue to be forwarded to the GraphQL Server;
    2. If no plugin is present, the request will be forwarded directly to GraphQL Server.

In the internal matching in APISIX core, Apache APISIX implements support for GraphQL through the graphql-lua library. The Apache APISIX GraphQL parsing library will first parse the request carrying the GraphQL syntax, and then match the parsed request with the configuration data preset in the Apache APISIX database. If the match is successful, Apache APISIX will release and forward the request, otherwise it will terminate the request.

Specific configuration

Apache APISIX currently supports filtering routes by some properties of GraphQL:

  • graphql_operation
  • graphql_name
  • graphql_root_fields

GraphQL properties correspond one-to-one with the GraphQL query statement shown below:

query getRepo {
    owner {
        name
    }
    repo {
        created
    }
}
  • graphql_operation corresponds to query
  • graphql_name corresponds to getRepo
  • graphql_root_fields corresponds to ["owner", "repo"]

You can verify GraphQL matching capabilities by setting up a route for Apache APISIX with the following example:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
    "methods": ["POST"],
    "uri": "/_graphql",
    "vars": [
        ["graphql_operation", "==", "query"],
        ["graphql_name", "==", "getRepo"],
        ["graphql_root_fields", "has", "owner"]
    ],
    "upstream": {
        "type": "roundrobin",
        "nodes": {
            "192.168.1.200:4000": 1
        }
    }
}'

Next use a request with a GraphQL statement to access:

curl -H 'content-type: application/graphql' -X POST http://127.0.0.1:9080/graphql -d '
query getRepo {
    owner {
        name
    }
    repo {
        created
    }
}'

If the match is successful, Apache APISIX proceeds with request forwarding.

HTTP/1.1 200 OK

Otherwise, the request is terminated.

HTTP/1.1 404 Not Found

Advanced operation

Apache APISIX can forward to different Upstreams according to different graphql_name , and perform different permission checks according to different graphql_operation . The code configuration for this feature is shown below for you.

Match Upstream with graphql_name

  1. Create the first upstream service:
curl http://192.168.1.200:9080/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "type": "chash",
    "key": "remote_addr",
    "nodes": {
        "192.168.1.200:1980": 1
    }
}'   
  1. Create a GraphQL route bound to the first upstream service, graphql_name set to getRepo111 :
curl http://192.168.1.200:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
    "methods": ["POST"],
    "uri": "/graphql",
    "vars": [
        ["graphql_operation", "==", "query"],
        ["graphql_name", "==", "getRepo111"],
        ["graphql_root_fields", "has", "owner"]
    ],    
    "upstream_id": "1"
}'   
  1. Create a second upstream service:
curl http://192.168.1.200:9080/apisix/admin/upstreams/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "type": "chash",
    "key": "remote_addr",
    "nodes": {
        "192.168.1.200:1981": 1
    }
}'
  1. Create a GraphQL route bound to the second upstream service, with graphql_name set to getRepo222 :
curl http://192.168.1.200:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
    "methods": ["POST"],
    "uri": "/graphql",
    "vars": [
        ["graphql_operation", "==", "query"],
        ["graphql_name", "==", "getRepo222"],
        ["graphql_root_fields", "has", "owner"]
    ],
    "upstream_id": 2
}'
  1. Test example

Test with the two graphql_name services created before, you can find that Apache APISIX can automatically select the forwarded Upstream according to the different graphql_name in the request.

  1. If the request is this example:
curl -i -H 'content-type: application/graphql' -X POST http://192.168.1.200:9080/graphql -d '
query getRepo111 {
    owner {
        name
    }
    repo {
        created
    }
}'

will return a response from upstream 192.168.1.200:1980 :

HTTP/1.1 200 OK
---URI
/graphql
---Service Node
Centos-port: 1980
  1. If the request is this example:
curl -i -H 'content-type: application/graphql' -X POST http://192.168.1.200:9080/graphql -d '
query getRepo222 {
    owner {
        name
    }
    repo {
        created
    }
}'

will return a response from upstream 192.168.1.200:1981 :

HTTP/1.1 200 OK
---URI
/graphql
---Service Node
Centos-port: 1981

Use graphql_operation for different permission checks

The above example provides a matching rule where graphql_operation is query , now a mutation request of the form 06226c6c0ad160 is used.

  1. Configure Apache APISIX:
curl http://192.168.1.200:9080/apisix/admin/routes/11 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "methods": ["POST"],
    "uri": "/hello",
    "vars": [
        ["graphql_operation", "==", "mutation"],
        ["graphql_name", "==", "repo"]
    ],
    "upstream": {
        "nodes": {
            "192.168.1.200:1982": 1
        },
        "type": "roundrobin"
    }
}'
  1. Make a mutation request to verify the Apache APISIX configuration:
curl -i -H 'content-type: application/graphql' -X POST http://192.168.1.200:9080/hello -d '
mutation repo($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}'

The returned result is as follows:

HTTP/1.1 200 OK
---URI
/hello
---Service Node
Centos-port: 1982

With plug-ins

Apache APISIX has a rich plug-in ecosystem to apply different usage scenarios. If you add suitable plug-ins when using Apache APISIX + GraphQL, you can make more application scenarios.

This article only selects the following two types of plug-ins as examples.

limit-count speed plugin

With the use of the limit-count plugin, the traffic is further restricted after being forwarded through GraphQL matching rules. Thanks to the characteristics of Apache APISIX, dynamic, refined and distributed current and speed limit can be achieved. For details, please refer to Apache APISIX official document .

Observability plugin

Apache APISIX provides observability plug-ins including but not limited to prometheus , skywalking , etc., which can provide the system with more monitoring indicator data and facilitate the implementation of subsequent operation and maintenance of the system.

Summarize

This article briefly introduces the application of GraphQL in Apache APISIX, and uses the actual code to show you the combination of Apache APISIX and GraphQL. Users can use GraphQL in Apache APISIX according to their own business needs and actual scenarios.

For more description and complete configuration information of GraphQL , please refer to official document .

The Apache APISIX project is currently developing additional plugins to support integrating more services, and if you are interested, you can start a discussion on the GitHub Discussions , or chat on the mailing list .


API7_技术团队
99 声望47 粉丝

API7.ai 是一家提供 API 处理和分析的开源基础软件公司,于 2019 年开源了新一代云原生 API 网关 -- APISIX 并捐赠给 Apache 软件基金会。此后,API7.ai 一直积极投入支持 Apache APISIX 的开发、维护和社区运营...