SENG3011
🌿  2.4 - Advanced Data Interchange
In this lecture
- What is GraphQL?
- What is gRPC?
- Trade-offs of using GraphQL and gRPC
Problems with REST
-
Over-fetching/under-fetching - when an endpoint provides more or less data than a client needs
- REST APIs have a fixed structure
- We often either fetch more data than we actually need, or need to make calls to multiple endpoints to fulfil our needs
- No type system - no assurance on types in request/response - easier for bugs to creep in
- Performance - slow to send JSON across the wire
gRPC - gRPC Remote Procedure Calls
- Fundamental idea - a client application can directly call a method on a server application on a different machine as if it were a local object
- Designed for building distributed applications
- Based around the idea of defining a service, specifying a series of methods that can be called remotely with parameters and return types
- Server side implements the interface and runs a gRPC server to handle client calls
- Client side has a stub that provides the same methods
- Useful for service-to-service communication
Protocol Buffers
- A mature open source mechanism for serialising data
- Define data structure to serialise in a .proto file
- Use protocol buffer compiler protoc to generate data access classes in preferred languages from proto definition
- Data access classes provide simple getters/setters, methods to serialise/parse the string from raw bytes
- Save time and space on the wire, sending serialised bytes instead of sending a raw JSON string
Protocol Buffers
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
Defining a gRPC API
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
gRPC: Trade-offs
-
Pros
- Big performance gain via compared data format, fast message encoding/decoding and use of HTTP/2
- Better security with TLS/SSL
-
Cons
- Need to use tools to analyse payloads and perform debugging
- Limited browser support - difficult to use in customer-facing web applications
GraphQL
- A query language for APIs and a runtime for fulfilling those queries with your existing data
- SQL for Web APIs!
- Developed by Facebook
- Useful for public-facing APIs
Making a Query
{
hero {
name
}
}
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
Parent and child fields
{
hero {
name
friends {
name
}
}
}
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
Fragments
{
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
appearsIn
friends {
name
}
}
{
"data": {
"leftComparison": {
"name": "Luke Skywalker",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
},
{
"name": "C-3PO"
},
{
"name": "R2-D2"
}
]
},
}
}
A full query
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
{
"episode": "JEDI"
}
Mutations
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
Types and Interfaces
type Character {
name: String!
appearsIn: [Episode!]!
}
interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
starships: [Starship]
totalCredits: Int
}
GraphQL Servers and Clients
- GraphQL server consists of a predefined schema
- Languages define a library to create GraphQL servers and resolve queries
- Need to define a series of resolvers/data fetchers to form an API layer
- Different GraphQL clients have different specialisations and use cases
Pagination
- How do we deal with large volumes of continuous data?
- Seperate data into "pages" - pagination
- Need to keep track of start/end of each page
{
user(id: "ZW5jaG9kZSBIZWxsb1dvcmxk") {
id
name
friendsConnection(first: 3) {
edges {
cursor
node {
id
name
}
}
}
}
}
The Graph in GraphQL
The Graph in GraphQL
Defining connections, edges and nodes in the graph
type UserFriendsConnection {
pageInfo: PageInfo!
edges: [UserFriendsEdge]
}
type UserFriendsEdge {
cursor: String!
node: User
}
type User {
id: ID!
name: String
friendsConnection(
first: Int,
after: String,
last: Int,
before: String
): UserFriendsConnection
}
GraphQL: Trade-offs
-
Pros
- Autogenerates documentation and allows for straightforward API versioning
- Leads to better performance, since there's no over/under fetching
- Consolidates scattered APIs under a single endpoint
-
Cons
- Harder to setup, more overhead
- Caching implementations more difficult
Common Architectural Patterns
Further Reading
- GraphQL connections https://www.apollographql.com/blog/graphql/explaining-graphql-connections/Â
- GraphQL info https://graphql.org/learn/
- Rest vs GraphQL vs gRPC https://www.baeldung.com/rest-vs-graphql-vs-grpc
- How to use GraphQL with Postman https://www.baeldung.com/graphql-postman
- gRPC Info https://grpc.io/docs/
SENG3011 23T1 - 2.4 - Advanced Data Interchange
By npatrikeos
SENG3011 23T1 - 2.4 - Advanced Data Interchange
- 321