GraphQL
The type system
{
user {
id
email
username
repos(first: 10) {
id
url
name
issues(first: 20) {
id
author
title
}
}
}
}
Copy the code
schema {
query: Query
mutation: Mutation
}
Copy the code
Centralized vs. decentralized
Relay standard
- Provide a mechanism to retrieve objects;
- Provides a description of how to page connections;
- Standardize mutation requests to make them more predictable;
Object identifier
interface Node {
id: ID!
}
type Faction : Node {
id: ID!
name: String
ships: ShipConnection
}
type Ship : Node {
id: ID!
name: String
}
Copy the code
Connection and paging
query {
viewer {
name
email
posts(first: 1) {
edge {
cursor
node {
title
}
}
}
}
}
Copy the code
{
"viewer": {
"name": "Draveness",
"email": "[email protected]",
"posts": {
"edges": [
"cursor": "YXJyYXljb25uZWN0aW9uOjI=",
"node": {
"title": "Post title",
}
]
}
}
}
Copy the code
query {
viewer {
name
email
posts(first: 1, after: "YXJyYXljb25uZWN0aW9uOjI=") {
edge {
cursor
node {
title
}
}
}
}
}
Copy the code
├── Post ├─ PageInfo ├── Bass ├─ PageInfo ├── Bass ├─ PageInfo ├─ bass ├─ bass ├─ PageInfo ├─ bass ├─ bass ├─ PageInfo ├─ bass ├─ bass ├─ PageInfo ├─ bass ├─ bass ├─ PageInfo ├─ bass ├─ bass ├─ PageInfo ├─ bass ├─ PageInfo ├─ bass ├─ bass ├─ endCursorCopy the code
Variable request
input IntroduceShipInput {
factionId: ID!
shipName: String!
clientMutationId: String!
}
type IntroduceShipPayload {
faction: Faction
ship: Ship
clientMutationId: String!
}
Copy the code
summary
N + 1 problem
SELECT * FROM users LIMIT 3;
SELECT * FROM posts WHERE user_id = 1;
SELECT * FROM posts WHERE user_id = 2;
SELECT * FROM posts WHERE user_id = 3;
SELECT * FROM users LIMIT 3;
SELECT * FROM posts WHERE user_id IN (1, 2, 3);
Copy the code
Microservices Architecture
Schema design
http://draveness.me/posts/api/graphql
http://draveness.me/comments/api/graphql
http://draveness.me/subscriptions/api/graphql
Copy the code
http://draveness.me/api/graphql
Copy the code
{
post(id: 1) {
user {
id
email
}
id
title
content
}
Copy the code
The prefix
glue
const linkTypeDefs = `
extend type User {
chirps: [Chirp]
}
`;
Copy the code
const mergedSchema = mergeSchemas({ schemas: [ chirpSchema, authorSchema, linkTypeDefs, ], resolvers: { User: { chirps: { fragment: `... on User { id }`, resolve(user, args, context, info) { return info.mergeInfo.delegateToSchema({ schema: chirpSchema, operation: 'query', fieldName: 'chirpsByAuthorId', args: { authorId: user.id, }, context, info, }); },},},},});Copy the code
mergeSchemas({ schemas: Array<string | GraphQLSchema | Array<GraphQLNamedType>>; resolvers? : Array<IResolvers> | IResolvers; onTypeConflict? : ( left: GraphQLNamedType, right: GraphQLNamedType, info? : { left: { schema? : GraphQLSchema; }; right: { schema? : GraphQLSchema; }; }, ) => GraphQLNamedType; })Copy the code
combination
summary
Authentication and Authorization
certification
authorization
summary
Routing design
Architecture evolution
Centralized Schema versus RPC
Schema for decentralized management
- There is no official or large open source support for the Elixir language for components used in Schema warp-aging. The handwrap-up components are under great pressure to carry a large service load, and their functions have many imperfections.
- In the case that internal services do not have much context for the whole request, once complex authentication requirements are encountered, the design way of handing authentication to internal services will lead to increased coupling between services — micro-services need to constantly pass the context of the request for authentication, and also increase the development cost;
Service grid and RPC
conclusion
Draveness. Me/graphql – mic…