unite services into a federation

My name is Vladislav Goncharov, I am a developer in the Platform V DataSpace team of SberTech. I’ll tell you how we solve the issue of combining services in GraphQL and microservice architecture, which allows you to break any large application into small services. On the one hand, they are easier to write and maintain with a small team. On the other hand, some tasks now require executing several queries at once instead of just one.

For example, let’s take a banking application. It can be divided into services:

  • “Clients” is a service that stores data about clients;

  • “Accounts” is a service that stores account data (a client ID will be required when storing this information);

  • “Credits” is a service that stores data about loans (an account ID will be required when saving this information), etc.

Let’s assume that we need to get information about the loan (loan amount and full name of the borrower) by loan agreement number. In a microservice architecture, the algorithm will be like this:

  1. Using the “Loans” service, find a loan by loan agreement number and receive the loan amount and account ID.

  2. Using the “Accounts” service, find an account by its ID and get the owner (client) ID.

  3. Using the “Clients” service, find a client by his ID and get his full name.

Let’s write this algorithm in the form of GraphQL queries.

Search for a loan by loan agreement number (“AA No. 000001”) and obtain the loan amount and account ID

Request:

query {
	searchCredit(cond: "it.contractNumber == 'AА №000001'") {
		elems {
			loanAmount
			account {
				entityId
			}
		}
	}
}

Answer:

{
  "data": {
    "searchCredit": {
      "elems": [
        {
          "loanAmount": 1000000,
          "account": {
            "entityId": "7088959748502519809"
          }
        }
      ]
    }
  }
}

Search for an account by ID (“7088959748502519809”) and obtain the owner (client) ID

Request:

query {
	searchAccount(cond: "it.$id == '7088959748502519809'") {
		elems {
			owner {
				entityId
			}
		}
	}
}

Answer:

{
  "data": {
    "searchAccount": {
      "elems": [
        {
          "owner": {
            "entityId": "7088959395241394177"
          }
        }
      ]
    }
  }
}

Search for a client by ID (“7088959395241394177”) and get full name

Request:

query {
	searchClient(cond: "it.$id == '7088959395241394177'") {
		elems {
			lastName
			firstName
			patronymic
		}
	}
}

Answer:

{
  "data": {
    "searchClient": {
      "elems": [
        {
          "lastName": "Иванов",
          "firstName": "Иван",
          "patronymic": "Иванович"
        }
      ]
    }
  }
}

To solve the problem, you need to make several requests to various services. You can also note the monotonous actions when searching for entities by identifiers from links, which would be nice to simplify. Let’s use Apollo Federation and Schema Stitching.

Apollo Federation is an open source solution that allows you to implement a microservice approach in GraphQL. Together with Schema Stitching, Apollo Federation allows you to make a service that has as a GraphQL schema a union of the GraphQL schemas of several services. Thanks to this, reference fields that were simply identifiers in the GraphQL schema of a separate service become full-fledged links.

Here’s what happened as a result – let’s look at the example of the task of finding a loan.

Search for a loan by loan agreement number (“AA No. 000001”) and obtain the loan amount and full name of the borrower

Request:

query {
    searchCredit(cond: "it.contractNumber == 'AА №000001'") {
        elems {
            loanAmount
            account {
                entity {
                    owner {
                        entity {
                            lastName
                            firstName
                            patronymic
                        }
                    }
                }
            }
        }
    }
}

Answer:

{
  "data": {
    "searchCredit": {
      "elems": [
        {
          "loanAmount": 1000000,
          "account": {
            "entity": {
              "owner": {
                "entity": {
                  "lastName": "Иванов",
                  "firstName": "Иван",
                  "patronymic": "Иванович"
                }
              }
            }
          }
        }
      ]
    }
  }
}

Combining services in DataSpace

This is what the implementation of a service with the unified GraphQL schema of DataSpace services looks like in practice.

Description of services

First of all, we describe the models of our services:

Clients.

Clients.

Accounts.

Accounts.

Loans.

Loans.

Release of a service with a unified GraphQL schema for the “Clients”, “Accounts” and “Credits” services

A service with a merged GraphQL schema is released as part of one of the merged services. As such, we will choose the “Credits” service. Let’s connect external models to it (the “Accounts” and “Clients” services):

Click the “External Models” button.

Click the “External Models” button.

Select the name of the service model from the list "Accounts".

Select the name of the “Accounts” service model from the list.

Click the “Add” button.

Click the “Add” button.

We do the same for the “Clients” service model.

We do the same for the “Clients” service model.

Then we release the service - done!

Then we release the service – ready!

Note 1. You can connect external models from spaces of other users to which access has been granted.

Note 2. The model name can be viewed in the model parameters.

Note 3. At the time of service release, the services of connected external models must be released.

Now we can go to the “Details” tab and, in addition to the endPoints of the “Credits” service, we will see the endPoint of the service with a combined GraphQL schema.

And on the “GraphQL Designer” tab, you can execute a GraphQL query for a service with a combined GraphQL schema (by checking the appropriate box next to “GraphQL Stitching”).

Note

It’s worth adding that GraphQL itself does not support entity inheritance, but we have added such a feature to DataSpace. For example, the tool allows you to query an entity or specify additional fields from child entities.

They did the same with search: GraphQL has no tools for this, the maximum is search by ID or non-standardized pagination. DataSpace implements a whole set of tools for this, available at the GraphQL level and allowing for pagination, sorting and grouping. We will tell you how and why this was done in the next article. Thank you for your attention!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *