Facebook launched graph-Query-Language (GRAPH-Query-Language) queries in 2015. So far, IBM, Twitter, Walmart Labs, The New York Times, Coursera, and many others have internally shifted from RESTful to GraphQL APIS.
As a query language, GraphQL has the following features:
(1) There is no need to worry about how to update the document, all queries and changes will automatically form a document (Cchema).
(2) There is no need to obtain the whole data set. Through the mapping between **schema and resolver (processor) **, the corresponding resolver obtains the data and returns the result to the front end, so that the query that only returns the requested data can be written.
(3) Provide a unified access point to the front end. Getting data from different apis is not easy, and GraphQL supports concatenation of all apis.
In the process of implementing microservitization, the technical team of IQiyi was subjected to low-code development proposed by Forrester Research. Inspired by the development concept that applications can be generated quickly without coding or with little code), BFF (Backend for Frontends) is built based on GraphQL to help developers intuitively create an API to be called by the front-end with drag-and-drop operations. This paper will summarize the experience in the implementation process.
GraphQL introduction
Like RESTful apis, the GraphQL API is designed to handle HTTP requests and provide responses to those requests. The REST API is built on the connection between the request method and the endpoint, while the GraphQL API is designed to go through just one endpoint, always querying with a POST request, usually with a URL of xxx.com/graphql. Figure 1-1 shows the GraphQL deployment architecture, which is in the “middle tier” of the system.
FIG. 1-1
GraphQL stands for Graph Query Language. It is officially marketed as “a Query Language tailored for your API”. Think of your collection of back-end apis as a database. The user terminal sends a query statement, and your GraphQL service parses this statement and returns the query results from your API database through a set of rules. GraphQL is the system’s query language. What SQL is to MySQL. GraphQL execution process is shown in Figure 1-2:
Figure 1-2
Figure 1-2 shows the general execution process of GraphQL. The first step is to verify whether the query statement conforms to GraphQL’s Schema specification and confirm the validity of the query content. The second step is to generate the execution context. All fields that need to be queried can be retrieved in the query statement, which is how GraphQL avoids returning redundant data. After getting all the fields to be queried, the fourth step is to execute the resolver for each field and get the corresponding data from the data returned by the resolver. Finally, format the result and return it.
The emphasis is on the fourth step. Expand and explain it, as shown in Figure 1-3 and Figure 1-4:
Figure 1-3
Figure 1-4
In GraphQL, there is a concept called type. Each type corresponds to one or more fields, and each field is bound to a processor (Resolver). The function of the resolver is to obtain the corresponding data of the field.
As shown in Figure 1-4, the UserInfo type has three fields: nickName, contractNo, and fansNumber. Each field corresponds to a resolver. The resolver must be redefined by the developer; otherwise, an error message will be reported. Therefore, the three fields nickName, contractNo and fansNumber under UserInfo need to implement their respective resolver to obtain user information, contract information and fan information respectively from user micro-service, contract micro-service and fan micro-service, and then aggregate them back. This completes the purpose of data concatenation using GraphQL.
BFF architecture
In the process of microservitization, iQiyi has added the front and back end architecture of BFF, as shown in Figure 2-1:
Figure 2-1
As you can see from the figure, BFF serves as a mid-tier service for the front and back ends. The main business logic is encapsulated in the BFF layer, and the front end is accessed through BFF to reduce the mutual call between microservices. The BFF layer provides services through REST apis. As more services are provided, more interfaces are provided, resulting in more and more REDUNDANT REST apis. For the front end, some API granularity is coarse and does not meet the requirements; Some apis are too fine-grained, increasing response time and wasting traffic. For the back end, the data required by the front end is often similar in different places, but not the same. For example, for user information, some places need users’ brief basic information and detailed video information, while others need users’ detailed basic information and brief video information. This often requires the development of different interfaces to meet various customization requirements, increasing the workload of developers and increasing the repetition of development efforts.
- GraphQL vs. Rest API:
Table 2-1
As can be seen from the comparison in Table 2-1, GraphQL performs better than Rest API and can effectively reduce the communication cost of front-end and back-end development. However, The official Implementation of Facebook is only THE JS version, and the query method and Rest API are also different (as shown in Table 2-2), which has certain migration and learning costs for old projects.
Table 2-2
Next, this article will focus on how to reduce migration costs while improving the efficiency of back-end developers and avoiding repetitive development based on GraphQL-Java.
Iqiyi API generation platform practice
Iqiyi API generation platform, is a low code platform. As the technology stack of IQiyi is mainly based on Java, Java implementation of GraphQL is used. Based on GraphQL-Java, the API generation platform mainly makes the following function optimization and enhancement.
(1) Support Rest API: reduce front-end access costs.
(2) ** Dynamic access monitoring: ** Dynamically generated API supports Prometheus monitoring like other common interfaces, ensuring monitoring flexibility and service stability.
(3) Flexible configuration: GraphQL schema can be dynamically generated to facilitate the back-end access to new services.
(4) ** visual API management platform: **API interface provides visual operation, convenient to view, add, modify and reuse.
The above functions will be described in detail next:
1. Support Rest apis
Graphql-java is wrapped by Spring and is located in the gateway layer or BFF layer of the entire architecture. The user-Info-GraphQL project relies on graphQL-Java-Spring to support Rest API requests. The overall architecture of the platform is shown in Figure 3-1:
Figure 3-1
Figure 3-2 shows the service flow chart of user-info-graphQL. The client requests through the GRAPHQL/prefix Rest API, and the back end binds the prefix with graphQL Query to obtain the mapping relationship from the DB, which is finally converted into the Query syntax supported by GraphQL.
Figure 3-2
2. Dynamic access monitoring
In the user-Info-GraphQL project, the template URL was originally used to match any custom URL; As a result, the monitoring platform can only display the template URL request information, as shown in Figure 3-3. This problem can be solved by rewriting the method of obtaining tags in spring-boot-Actuator and exposing the actual URL request information to the /actuator/ Prometheus endpoint of Spring Boot, as shown in Figure 3-4.
Figure 3-3
Figure 3-4
Connect the exposed monitoring endpoint to Prometheus for real-time dynamic monitoring of the newly generated API. Figure 3-5 shows an example:
Figure 3-5
3. Flexible configuration
Micro services are added to facilitate quick access to the back-end and support API dynamic extension. In the project, the Schema template was defined by Velocity, and graphQls template file was dynamically generated by Java annotation and reflection mechanism, as shown in Figure 3-6:
Figure 3-6
The GraphQL Schema template shown in Figure 3-6 supports querying user information by user UID. The user information is aggregated by multiple microservices, which are asynchronously invoked to obtain data in parallel. Based on this template, users only need to implement the interfaces defined by SPI to implement support for new microservices. 4. Visual API management platform Through the API generation management platform, developers can realize the visual configuration, generation, dynamic monitoring and other functions of API interfaces, out of the box effect, greatly improve the efficiency of development and operation and maintenance.
conclusion
GraphQL is used to dynamically build BFF service layer API and aggregate different microservices. Compared with Rest API, it can reduce back-end repetitive development and speed up response to front-end requirements. Back-end developers only need to develop and maintain the new microservices and add BFF layer support for the new microservices through SPI.
Value: By introducing GraphQL into the back-end microservice of IQiyi to build the BFF service layer, the following effects can be achieved:
Advantages in development
-
Improve development efficiency: the responsibilities of back-end developers are clearly divided, and the microservices and BFF layer are independently developed and maintained. The new microservice is easy to access. Because the EXTERNAL API of THE BFF layer supports dynamic generation, there is no need to change the code of the BFF layer and only need to centrally maintain the microservice. The front-end can view the data returned by the interface through the GraphQL Schema to reduce the communication cost of the front-end and back-end.
-
Form a low code platform: As the microservices infrastructure built is fully developed, the BFF layer supports the dynamic generation of API interfaces, which greatly reduces the repetitive workload.
Advantages when running maintenance
-
Easy monitoring: Added BFF layer API, no development cost by supporting Prometheus endpoint monitoring.
-
Support system high throughput: BFF service and micro service are deployed based on Docker, support QPS dynamic expansion, and support high concurrency.
-
Easy to maintain and expand: BFF layer built based on GraphQL, API interface dynamically generated, clear hierarchy, easy to maintain and expand.
Difficult points:
-
Dynamic query expansion support. At present, schema definitions are based on explicit fields. If dynamic query support is required, dynamic schema expansion and parsing need to be supported.
-
There are few Chinese documents, and Only JS implementation is officially released by Facebook. Java implementation is based on the open source community, so the documentation and functions are not very perfect.
Future planning:
With the diversity of API requests on the BFF side, new method extensions and monitoring need to be dynamically supported. At present, the mapping between API and request is persisted in MySQL, which needs to support cluster and high performance. Subsequently, it will be gradually migrated to ZK or Redis and cached locally.
With the rise of cloud native and K8s, Go services deployed based on K8s are easier to expand and maintain. GraphQL based on Java implementation, if migrated to K8s deployment, it is difficult to achieve the effect of rapid scaling. However, the star of GraphQL-Go on Github is as high as 7K, which shows its high popularity. If the BFF end is implemented based on Go, the mapping relationship between API and request can be stored in THE Pod configuration file of K8s, and a class of Pod can be deployed through an API to carry out service isolation, which can guarantee service stability to a higher degree.