SlideShare a Scribd company logo
1 of 53
1
Cutting through the fog of Microservices
Lightsabers Optional
2
Graham’s potted history of distributed computing*
*It may not be accurate or even true
1960 1970 1980 1990 2000 2010 2020
Distributed
Computing
Born
RPC
RMI
CORBA
8 Fallacies of
Distributed
Computing
Roy Fielding
Dissertation
REST
SOAP
and SOA GraphQL
gRPC
HTTP/1.1 HTTP/2
JSON
JSON-RPC
XML
Webazoic periodNetassic period
TCP/IP
Ethernet
Microservices
33
Analysis
4
What follows includes opinions
5
We are unlikely to all agree
6
Considerations
• Capabilities/Scope
• Ease of Use
• Applicability
• Ubiquity/Adoption
• Approach
7
Approach
ContractContract
Service
Service
Client
ClientContract-driven
Bottom-up
8
Method
• Show each technology for the same scenario
• Retrieve and Update Person records
• Include a relationship
Person
• id
• firstName
• lastName
• dob
• addressID
Address
• id
• nameOrNumber
• street
• line2
• city
• state
• country
• zip
99
{REST}
10
Background
• Born out of Roy Fielding’s PhD dissertation
o “Architectural Styles and the Design of Network-based Software Architectures”
• Argues for the appropriate use of the basic Web building blocks
o HTTP and URIs
• An architectural style, not a specification or a protocol
• Support in numerous languages and frameworks
o I’m going to show JAX-RS with JSON-B
11
Approach
OpenAPIOpenAPI
JAX-RS
JSON-B
JAX-RS
JSON-B
Client
ClientContract-driven
Bottom-up
12
Concepts
• Resources
• URLs/URIs
• HTTP
o Verbs - typically POST, GET, PUT, DELETE
o Response Codes – 200 OK, 201 CREATED, 404 NOT FOUND,
...
13
Idempotent vs safe
HTTP Method Idempotent Safe
POST no no
GET yes yes
PUT yes no
DELETE yes no
PATCH no no
HEAD yes yes
OPTIONS yes yes
Idempotent => can be retried
Safe => can be cached, prefetched
14
Application
@ApplicationPath("/v1")
public class PersonApplication extends Application {
}
15
Resources - GET
@Path("/person")
@RequestScoped
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {
PersonRepository personRepo = new PersonRepository();
@GET
@Path("/")
public List<Person> people() {
return personRepo.allPeople();
}
@GET
@Path("/{id}")
public Person personWithId(@PathParam("id") String id) {
Optional<Person> person = Optional.ofNullable(personRepo.personWithId(id));
return person.orElseThrow(() -> new NotFoundException("Person does not exist."));
}
...
}
16
Resources – GET (relationships and filtering)
@Path("/person")
@RequestScoped
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {
PersonRepository personRepo = new PersonRepository();
...
@GET
@Path("/{id}/address")
public Address addressOfPersonWithId(@PathParam("id") String id) {
Optional<Person> optPerson = Optional.ofNullable(personRepo.personWithId(id));
Person person = optPerson.orElseThrow(() -> new NotFoundException("Person does not exist."));
Optional<Address> optAddress = Optional.ofNullable(personRepo.addressWithId(person.getAddressId()));
return optAddress.orElseThrow(() -> new NotFoundException("Person does not have an address."));
}
@GET
@Path("/filter")
public List<Person> contains(@QueryParam("lastName") String lastName) {
List<Person> matches = personRepo.personWithLastName(lastName);
if (matches.isEmpty())
throw new NotFoundException("No people with matching lastName");
else
return matches;
}
}
17
Resources - POST
@Path("/person")
@RequestScoped
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {
PersonRepository personRepo = new PersonRepository();
@POST
@Path("/")
public Person createPerson(Person person) {
if ("".equals(person.getId()))
return personRepo.save(person);
else
throw new BadRequestException("Person Id provided on create request.");
}
...
}
18
Resources - PUT
@Path("/person")
@RequestScoped
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {
PersonRepository personRepo = new PersonRepository();
@PUT
@Path("/{personId}")
public Person updatePerson(@PathParam("personId") String personId, Person person) {
person.setId(personId);
Optional<Person> optPerson = Optional.ofNullable(personRepo.update(person));
return optPerson.orElseThrow(() -> new NotFoundException("Person does not exist."));
}
...
}
19
Resources - DELETE
@Path("/person")
@RequestScoped
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {
PersonRepository personRepo = new PersonRepository();
...
@DELETE
@Path("/{personId}")
public void deletePerson(@PathParam("personId") String personId) {
Person person = personRepo.delete(personId);
if (person == null)
throw new NotFoundException("Person does not exist.");
}
}
20
Representation
public class Person {
private String id = "";
private String firstName = "";
private String lastName = "";
private String dob = null;
private String addressId = "";
...
public Person() {
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
}
{
"addressId": "ded64e7b-c68c-469f-a4ba-f96079491053",
"dob": "31-12-1999",
"firstName": "Bob",
"id": "a64998a0-6b11-4033-bd17-2b9f8049aa45",
"lastName": "Bobson"
}
JSON-B,
Jackson,
etc...
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Person personWithId(@PathParam("id") String id) {
...
}
21
URLs/URIs
https://www.acme-hr.com:9080/rest/v1/person/a64998a0-6b11-4033-bd17-2b9f8049aa45
protocol
host
port
context
root
application
path
resource
path
resource
id
22
REST Client (MicroProfile)
@Path("/address")
@RegisterRestClient
public interface AddressClient {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public List<Address> addresses();
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Address addressWithId(@PathParam("id") String id);
...
}
23
Demo
2424
25
Background
• Developed by Facebook
• Released 2015
• Moved to a foundation 2018
• Enables clients to query data and receive only the fields requested
• Also supports update and subscription
• Multi-language support: Java, JavaScript, Go, Python, etc.
• GraphQL Client support in Relay and Apollo Client
26
Approach
Schema
graphql-
java
ClientBottom-up
27
Concepts
• Schema
• Types
• Query
• Mutation
• Subscription
• Resolver
28
Types
type Person {
id: ID!
firstName: String!
lastName: String!
dob: String
address: Address
}
type Address {
id: ID!
nameOrNumber: String!
street: String
line2: String
state: String
zip: String!
country: String!
}
package gcc.demos.graphql.model;
public class Address {
private String id = "";
private String nameOrNumber = "";
private String street = "";
...
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setNameOrNumber(String nameOrNumber) {
this.nameOrNumber = nameOrNumber;
}
public String getNameOrNumber() {
return nameOrNumber;
}
public void setStreet(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
...
}
schema.graphqls
29
Query Resolver
schema.graphqls
type Query {
people: [Person]
person (id: ID!): Person
addresses: [Address]
address (id: ID!): Address
}
public class Query implements GraphQLQueryResolver {
private final PersonRepository personRepository;
public Query (PersonRepository personRepository) {
this.personRepository = personRepository;
}
public List<Person> people() {
return personRepository.allPeople();
}
public List<Address> addresses() {
return personRepository.allAddresses();
}
public Person person(String id) {
return personRepository.personWithId(id);
}
public Address address(String id) {
return personRepository.addressWithId(id);
}
}
30
Person Resolver
public class PersonResolver implements GraphQLResolver<Person> {
private PersonRepository personRepository;
public PersonResolver(PersonRepository personRepository) {
this.personRepository = personRepository;
}
public Address address(Person person) {
return personRepository.addressWithId(person.getAddressId());
}
}
31
Mutation Resolver
type Mutation {
createPerson(firstName: String!,
lastName: String!,
dob: String!): Person
createAddress(nameOrNumber: String!,
street: String!,
line2: String,
state: String,
zip: String!,
country: String!): Address
setAddressOfPerson(personId: String!,
addressId: String!): Person
}
public class Mutation implements GraphQLMutationResolver {
private final PersonRepository personRepository;
public Mutation(PersonRepository personRepository) {
this.personRepository = personRepository;
}
public Person createPerson(String firstName, String lastName,
String dob) {
...
}
public Address createAddress(String nameOrNumber, String street,
String line2, String state,
String zip, String country) {
...
}
public Person setAddressOfPerson(String personId,
String addressId) {
...
}
}
schema.graphqls
32
Declaring the entry-points
schema {
query: Query
mutation: Mutation
}
schema.graphqls
33
Set-up
@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLHttpServlet {
...
@Override
protected GraphQLConfiguration getConfiguration() {
return GraphQLConfiguration.with(createSchema()).build();
}
private static GraphQLSchema createSchema() {
return SchemaParser.newParser()
.file("schema.graphqls")
.resolvers(
new Query(personRepository),
new Mutation(personRepository),
new PersonResolver(personRepository))
.build()
.makeExecutableSchema();
}
}
34
Demo
3535
36
Background
• RPC System
• Developed by Google
• Open Source in 2015
• Optimized for low-latency communication
o E.g. server to server or mobile clients
• Multi-language support: Java (incl. Android), Node.js, Go, Objective-
C, Ruby, etc...
37
Approach
protobuf
ImplBaseStubContract-driven
38
Concepts
• Protobuf
o IDL
o Messages
o Binary serialization, deserialization
o Compact (not self-describing)
• gRPC
o Uses same IDL - adds Services and RPC methods
o Communication over HTTP/2
o Advanced features – fault tolerance, deadlines, field masks, load
balancing, blocking and streaming APIs
39
Message generation
message Person {
string id = 1;
string firstName = 2;
string lastName = 3;
string dob = 4;
string addressId = 5;
}
message Address {
string id = 1;
string nameOrNumber = 2;
string street= 3;
string line2 = 4;
string state = 5;
string zip = 6;
string country = 7;
}
2,247 LoC
person.proto
Person person = Person.newBuilder()
.setId(id).build();
String firstName = person.getFirstName();
40
ServiceImplBase & Stub generation
service PersonService {
rpc GetPeople (google.protobuf.Empty) returns (stream Person) {}
rpc GetPerson (Person) returns (Person) {}
rpc SetPerson (Person) returns (Person) {}
rpc GetAddress (Person) returns (Address) {}
rpc SetPersonAndAddress (PersonAndAddress) returns (PersonAndAddress) {}
rpc GetPersonAndAddress (Person) returns (PersonAndAddress) {}
rpc GetAgeInYears (Person) returns (AgeInYearsResponse) {}
}
service AddressService {
rpc GetAddresses (google.protobuf.Empty) returns (stream Person) {}
rpc GetAddress (Address) returns (Address) {}
rpc SetAddress (Address) returns (Address) {}
}
1,143 LoC
person.proto
41
Implementing a Service
class AddressServiceImpl extends AddressServiceGrpc.AddressServiceImplBase {
private static PersonRepository repository = new PersonRepository();
@Override
public void getAddresses(Empty request, StreamObserver<Address> responseObserver) {
for (Address address : repository.allAddresses()) {
responseObserver.onNext(address);
}
responseObserver.onCompleted();
}
@Override
public void setAddress(Address req, StreamObserver<Address> responseObserver) {
responseObserver.onNext(repository.save(req));
responseObserver.onCompleted();
}
@Override
public void getAddress(Address req, StreamObserver<Address> responseObserver) {
responseObserver.onNext(repository.addressWithId(req.getId()));
responseObserver.onCompleted();
}
}
42
Calling a Service
public class PersonClient {
private final ManagedChannel channel;
private final PersonServiceGrpc.PersonServiceBlockingStub blockingStub;
PersonClient(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port).build();
blockingStub = PersonServiceGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public void getPerson(String id) {
Person request = Person.newBuilder().setId(id).build();
Person response;
try {
response = blockingStub.getPerson(request);
} catch (StatusRuntimeException e) {
System.out.println("RPC failed: ", e.getStatus());
return;
}
System.out.println("Person: " + response.getFirstName());
}
}
43
Performance
https://auth0.com/blog/beating-json-performance-with-protobuf/
Uncompressed, JavaScript to Java
Java to Java
44
Demo
4545
Bringing it all together
46
Adoption
47
Bringing it all together
{REST}
Web Mobile Third-party
{REST}{REST} {REST}
Front-end
Gateway
Backend
48
GraphQL
{REST}
Web Mobile Third-party
{REST}{REST} {REST}
Front-end
Gateway
Backend
• Flexible
• View-centered
• Gateway
• Simple
• Limited functionality
49
gRPC
{REST}
Web Mobile Third-party
{REST}{REST} {REST}
``
Front-end
Gateway
Backend
• High-performance
• Machine-to-machine
• Full-featured
• Higher complexity
50
REST
{REST}
Web Mobile Third-party
{REST}{REST} {REST}
Front-end
Gateway
Backend
• General purpose
• Ubiquitous
• Simple (ish)
• Aligned with HTTP (but
dev needs to get it right)
51
Summary
Consideration REST GraphQL gRPC
Capabilities/Scope General Narrow scope Feature-rich
Ease of Use Simple -> Medium Simple Medium -> Hard
Applicability General Excels at
web/gateway
Excels at high
perf/throughput
Ubiquity/Adoption Universal, High
adoption
Many languages Many languages,
but not all
environments
Approach Contract-driven,
bottom-up
Bottom-up Contract-driven
5252
Questions?
5353
Thank You!

More Related Content

What's hot

Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02
Ramamohan Chokkam
 

What's hot (20)

Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#
 
Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#
 
Using Regular Expressions and Staying Sane
Using Regular Expressions and Staying SaneUsing Regular Expressions and Staying Sane
Using Regular Expressions and Staying Sane
 
Going reactive in java
Going reactive in javaGoing reactive in java
Going reactive in java
 
Clean code
Clean codeClean code
Clean code
 
Functional concepts in C#
Functional concepts in C#Functional concepts in C#
Functional concepts in C#
 
C# 7
C# 7C# 7
C# 7
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
Javascript2839
Javascript2839Javascript2839
Javascript2839
 
Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
Java 8 Stream API and RxJava Comparison
Java 8 Stream API and RxJava ComparisonJava 8 Stream API and RxJava Comparison
Java 8 Stream API and RxJava Comparison
 
PostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practicePostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practice
 
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
Expression trees in C#
Expression trees in C#Expression trees in C#
Expression trees in C#
 
Oleksii Holub "Expression trees in C#"
Oleksii Holub "Expression trees in C#" Oleksii Holub "Expression trees in C#"
Oleksii Holub "Expression trees in C#"
 
Collectors in the Wild
Collectors in the WildCollectors in the Wild
Collectors in the Wild
 
C++ Windows Forms L07 - Collections
C++ Windows Forms L07 - CollectionsC++ Windows Forms L07 - Collections
C++ Windows Forms L07 - Collections
 

Similar to Cutting through the fog of microservices: lightsabers optional

infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!
infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!
infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!
Infoshare
 
Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced
Flink Forward
 

Similar to Cutting through the fog of microservices: lightsabers optional (20)

Dev Day Andreas Roth.pdf
Dev Day Andreas Roth.pdfDev Day Andreas Roth.pdf
Dev Day Andreas Roth.pdf
 
Developing and maintaining a Java GraphQL back-end: The less obvious - Bojan ...
Developing and maintaining a Java GraphQL back-end: The less obvious - Bojan ...Developing and maintaining a Java GraphQL back-end: The less obvious - Bojan ...
Developing and maintaining a Java GraphQL back-end: The less obvious - Bojan ...
 
Best of build 2021 - C# 10 & .NET 6
Best of build 2021 -  C# 10 & .NET 6Best of build 2021 -  C# 10 & .NET 6
Best of build 2021 - C# 10 & .NET 6
 
An introduction into Spring Data
An introduction into Spring DataAn introduction into Spring Data
An introduction into Spring Data
 
Kill the DBA
Kill the DBAKill the DBA
Kill the DBA
 
Lombokの紹介
Lombokの紹介Lombokの紹介
Lombokの紹介
 
infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!
infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!
infoShare 2014: Gino Marckx, Forget about Agile, let's write great code first!
 
Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!
 
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
 
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
Next-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNext-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and Prisma
 
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
Применение паттерна Page Object для автоматизации веб сервисов - новый взглядПрименение паттерна Page Object для автоматизации веб сервисов - новый взгляд
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
 
Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced
 
A evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidA evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no android
 
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofitjSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
 
Java 8 revealed
Java 8 revealedJava 8 revealed
Java 8 revealed
 
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
 
Drupal Mobile
Drupal MobileDrupal Mobile
Drupal Mobile
 
Annotation processing and code gen
Annotation processing and code genAnnotation processing and code gen
Annotation processing and code gen
 

More from Graham Charters

More from Graham Charters (10)

Explore Jakarta EE and MicroProfile on Azure with Open Liberty & OpenShift
Explore Jakarta EE and MicroProfile on Azure with Open Liberty & OpenShiftExplore Jakarta EE and MicroProfile on Azure with Open Liberty & OpenShift
Explore Jakarta EE and MicroProfile on Azure with Open Liberty & OpenShift
 
How to get along with HATEOAS without letting the bad guys steal your lunch?
How to get along with HATEOAS without letting the bad guys steal your lunch?How to get along with HATEOAS without letting the bad guys steal your lunch?
How to get along with HATEOAS without letting the bad guys steal your lunch?
 
Are you ready for cloud-native Java?
Are you ready for cloud-native Java?Are you ready for cloud-native Java?
Are you ready for cloud-native Java?
 
Optimizing Spring Boot apps for Docker
Optimizing Spring Boot apps for DockerOptimizing Spring Boot apps for Docker
Optimizing Spring Boot apps for Docker
 
A first look at Open Liberty
A first look at Open LibertyA first look at Open Liberty
A first look at Open Liberty
 
Microservices and OSGi: Better together?
Microservices and OSGi: Better together?Microservices and OSGi: Better together?
Microservices and OSGi: Better together?
 
Get Rapid Right-sized and Recent with the Liberty Repository
Get Rapid Right-sized and Recent with the Liberty RepositoryGet Rapid Right-sized and Recent with the Liberty Repository
Get Rapid Right-sized and Recent with the Liberty Repository
 
Monoliths are so 2001 – What you need is Modularity
Monoliths are so 2001 – What you need is ModularityMonoliths are so 2001 – What you need is Modularity
Monoliths are so 2001 – What you need is Modularity
 
Towards a Modularity Maturity Model
Towards a Modularity Maturity ModelTowards a Modularity Maturity Model
Towards a Modularity Maturity Model
 
Hints and Tips for Modularizing Existing Enterprise Applications (OSGi Commun...
Hints and Tips for Modularizing Existing Enterprise Applications (OSGi Commun...Hints and Tips for Modularizing Existing Enterprise Applications (OSGi Commun...
Hints and Tips for Modularizing Existing Enterprise Applications (OSGi Commun...
 

Recently uploaded

Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
FIDO Alliance
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
FIDO Alliance
 
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
panagenda
 

Recently uploaded (20)

AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentation
 
Navigating the Large Language Model choices_Ravi Daparthi
Navigating the Large Language Model choices_Ravi DaparthiNavigating the Large Language Model choices_Ravi Daparthi
Navigating the Large Language Model choices_Ravi Daparthi
 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptx
 
UiPath manufacturing technology benefits and AI overview
UiPath manufacturing technology benefits and AI overviewUiPath manufacturing technology benefits and AI overview
UiPath manufacturing technology benefits and AI overview
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptx
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
Intro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxIntro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptx
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
 
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream Processing
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
ChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps ProductivityChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps Productivity
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
 

Cutting through the fog of microservices: lightsabers optional

  • 1. 1 Cutting through the fog of Microservices Lightsabers Optional
  • 2. 2 Graham’s potted history of distributed computing* *It may not be accurate or even true 1960 1970 1980 1990 2000 2010 2020 Distributed Computing Born RPC RMI CORBA 8 Fallacies of Distributed Computing Roy Fielding Dissertation REST SOAP and SOA GraphQL gRPC HTTP/1.1 HTTP/2 JSON JSON-RPC XML Webazoic periodNetassic period TCP/IP Ethernet Microservices
  • 5. 5 We are unlikely to all agree
  • 6. 6 Considerations • Capabilities/Scope • Ease of Use • Applicability • Ubiquity/Adoption • Approach
  • 8. 8 Method • Show each technology for the same scenario • Retrieve and Update Person records • Include a relationship Person • id • firstName • lastName • dob • addressID Address • id • nameOrNumber • street • line2 • city • state • country • zip
  • 10. 10 Background • Born out of Roy Fielding’s PhD dissertation o “Architectural Styles and the Design of Network-based Software Architectures” • Argues for the appropriate use of the basic Web building blocks o HTTP and URIs • An architectural style, not a specification or a protocol • Support in numerous languages and frameworks o I’m going to show JAX-RS with JSON-B
  • 12. 12 Concepts • Resources • URLs/URIs • HTTP o Verbs - typically POST, GET, PUT, DELETE o Response Codes – 200 OK, 201 CREATED, 404 NOT FOUND, ...
  • 13. 13 Idempotent vs safe HTTP Method Idempotent Safe POST no no GET yes yes PUT yes no DELETE yes no PATCH no no HEAD yes yes OPTIONS yes yes Idempotent => can be retried Safe => can be cached, prefetched
  • 15. 15 Resources - GET @Path("/person") @RequestScoped @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class PersonResource { PersonRepository personRepo = new PersonRepository(); @GET @Path("/") public List<Person> people() { return personRepo.allPeople(); } @GET @Path("/{id}") public Person personWithId(@PathParam("id") String id) { Optional<Person> person = Optional.ofNullable(personRepo.personWithId(id)); return person.orElseThrow(() -> new NotFoundException("Person does not exist.")); } ... }
  • 16. 16 Resources – GET (relationships and filtering) @Path("/person") @RequestScoped @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class PersonResource { PersonRepository personRepo = new PersonRepository(); ... @GET @Path("/{id}/address") public Address addressOfPersonWithId(@PathParam("id") String id) { Optional<Person> optPerson = Optional.ofNullable(personRepo.personWithId(id)); Person person = optPerson.orElseThrow(() -> new NotFoundException("Person does not exist.")); Optional<Address> optAddress = Optional.ofNullable(personRepo.addressWithId(person.getAddressId())); return optAddress.orElseThrow(() -> new NotFoundException("Person does not have an address.")); } @GET @Path("/filter") public List<Person> contains(@QueryParam("lastName") String lastName) { List<Person> matches = personRepo.personWithLastName(lastName); if (matches.isEmpty()) throw new NotFoundException("No people with matching lastName"); else return matches; } }
  • 17. 17 Resources - POST @Path("/person") @RequestScoped @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class PersonResource { PersonRepository personRepo = new PersonRepository(); @POST @Path("/") public Person createPerson(Person person) { if ("".equals(person.getId())) return personRepo.save(person); else throw new BadRequestException("Person Id provided on create request."); } ... }
  • 18. 18 Resources - PUT @Path("/person") @RequestScoped @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class PersonResource { PersonRepository personRepo = new PersonRepository(); @PUT @Path("/{personId}") public Person updatePerson(@PathParam("personId") String personId, Person person) { person.setId(personId); Optional<Person> optPerson = Optional.ofNullable(personRepo.update(person)); return optPerson.orElseThrow(() -> new NotFoundException("Person does not exist.")); } ... }
  • 19. 19 Resources - DELETE @Path("/person") @RequestScoped @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class PersonResource { PersonRepository personRepo = new PersonRepository(); ... @DELETE @Path("/{personId}") public void deletePerson(@PathParam("personId") String personId) { Person person = personRepo.delete(personId); if (person == null) throw new NotFoundException("Person does not exist."); } }
  • 20. 20 Representation public class Person { private String id = ""; private String firstName = ""; private String lastName = ""; private String dob = null; private String addressId = ""; ... public Person() { } public void setId(String id) { this.id = id; } public String getId() { return id; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getFirstName() { return firstName; } } { "addressId": "ded64e7b-c68c-469f-a4ba-f96079491053", "dob": "31-12-1999", "firstName": "Bob", "id": "a64998a0-6b11-4033-bd17-2b9f8049aa45", "lastName": "Bobson" } JSON-B, Jackson, etc... @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) public Person personWithId(@PathParam("id") String id) { ... }
  • 22. 22 REST Client (MicroProfile) @Path("/address") @RegisterRestClient public interface AddressClient { @GET @Path("/") @Produces(MediaType.APPLICATION_JSON) public List<Address> addresses(); @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) public Address addressWithId(@PathParam("id") String id); ... }
  • 24. 2424
  • 25. 25 Background • Developed by Facebook • Released 2015 • Moved to a foundation 2018 • Enables clients to query data and receive only the fields requested • Also supports update and subscription • Multi-language support: Java, JavaScript, Go, Python, etc. • GraphQL Client support in Relay and Apollo Client
  • 27. 27 Concepts • Schema • Types • Query • Mutation • Subscription • Resolver
  • 28. 28 Types type Person { id: ID! firstName: String! lastName: String! dob: String address: Address } type Address { id: ID! nameOrNumber: String! street: String line2: String state: String zip: String! country: String! } package gcc.demos.graphql.model; public class Address { private String id = ""; private String nameOrNumber = ""; private String street = ""; ... public String getId() { return id; } public void setId(String id) { this.id = id; } public void setNameOrNumber(String nameOrNumber) { this.nameOrNumber = nameOrNumber; } public String getNameOrNumber() { return nameOrNumber; } public void setStreet(String street) { this.street = street; } public String getStreet() { return street; } ... } schema.graphqls
  • 29. 29 Query Resolver schema.graphqls type Query { people: [Person] person (id: ID!): Person addresses: [Address] address (id: ID!): Address } public class Query implements GraphQLQueryResolver { private final PersonRepository personRepository; public Query (PersonRepository personRepository) { this.personRepository = personRepository; } public List<Person> people() { return personRepository.allPeople(); } public List<Address> addresses() { return personRepository.allAddresses(); } public Person person(String id) { return personRepository.personWithId(id); } public Address address(String id) { return personRepository.addressWithId(id); } }
  • 30. 30 Person Resolver public class PersonResolver implements GraphQLResolver<Person> { private PersonRepository personRepository; public PersonResolver(PersonRepository personRepository) { this.personRepository = personRepository; } public Address address(Person person) { return personRepository.addressWithId(person.getAddressId()); } }
  • 31. 31 Mutation Resolver type Mutation { createPerson(firstName: String!, lastName: String!, dob: String!): Person createAddress(nameOrNumber: String!, street: String!, line2: String, state: String, zip: String!, country: String!): Address setAddressOfPerson(personId: String!, addressId: String!): Person } public class Mutation implements GraphQLMutationResolver { private final PersonRepository personRepository; public Mutation(PersonRepository personRepository) { this.personRepository = personRepository; } public Person createPerson(String firstName, String lastName, String dob) { ... } public Address createAddress(String nameOrNumber, String street, String line2, String state, String zip, String country) { ... } public Person setAddressOfPerson(String personId, String addressId) { ... } } schema.graphqls
  • 32. 32 Declaring the entry-points schema { query: Query mutation: Mutation } schema.graphqls
  • 33. 33 Set-up @WebServlet(urlPatterns = "/graphql") public class GraphQLEndpoint extends SimpleGraphQLHttpServlet { ... @Override protected GraphQLConfiguration getConfiguration() { return GraphQLConfiguration.with(createSchema()).build(); } private static GraphQLSchema createSchema() { return SchemaParser.newParser() .file("schema.graphqls") .resolvers( new Query(personRepository), new Mutation(personRepository), new PersonResolver(personRepository)) .build() .makeExecutableSchema(); } }
  • 35. 3535
  • 36. 36 Background • RPC System • Developed by Google • Open Source in 2015 • Optimized for low-latency communication o E.g. server to server or mobile clients • Multi-language support: Java (incl. Android), Node.js, Go, Objective- C, Ruby, etc...
  • 38. 38 Concepts • Protobuf o IDL o Messages o Binary serialization, deserialization o Compact (not self-describing) • gRPC o Uses same IDL - adds Services and RPC methods o Communication over HTTP/2 o Advanced features – fault tolerance, deadlines, field masks, load balancing, blocking and streaming APIs
  • 39. 39 Message generation message Person { string id = 1; string firstName = 2; string lastName = 3; string dob = 4; string addressId = 5; } message Address { string id = 1; string nameOrNumber = 2; string street= 3; string line2 = 4; string state = 5; string zip = 6; string country = 7; } 2,247 LoC person.proto Person person = Person.newBuilder() .setId(id).build(); String firstName = person.getFirstName();
  • 40. 40 ServiceImplBase & Stub generation service PersonService { rpc GetPeople (google.protobuf.Empty) returns (stream Person) {} rpc GetPerson (Person) returns (Person) {} rpc SetPerson (Person) returns (Person) {} rpc GetAddress (Person) returns (Address) {} rpc SetPersonAndAddress (PersonAndAddress) returns (PersonAndAddress) {} rpc GetPersonAndAddress (Person) returns (PersonAndAddress) {} rpc GetAgeInYears (Person) returns (AgeInYearsResponse) {} } service AddressService { rpc GetAddresses (google.protobuf.Empty) returns (stream Person) {} rpc GetAddress (Address) returns (Address) {} rpc SetAddress (Address) returns (Address) {} } 1,143 LoC person.proto
  • 41. 41 Implementing a Service class AddressServiceImpl extends AddressServiceGrpc.AddressServiceImplBase { private static PersonRepository repository = new PersonRepository(); @Override public void getAddresses(Empty request, StreamObserver<Address> responseObserver) { for (Address address : repository.allAddresses()) { responseObserver.onNext(address); } responseObserver.onCompleted(); } @Override public void setAddress(Address req, StreamObserver<Address> responseObserver) { responseObserver.onNext(repository.save(req)); responseObserver.onCompleted(); } @Override public void getAddress(Address req, StreamObserver<Address> responseObserver) { responseObserver.onNext(repository.addressWithId(req.getId())); responseObserver.onCompleted(); } }
  • 42. 42 Calling a Service public class PersonClient { private final ManagedChannel channel; private final PersonServiceGrpc.PersonServiceBlockingStub blockingStub; PersonClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port).build(); blockingStub = PersonServiceGrpc.newBlockingStub(channel); } public void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } public void getPerson(String id) { Person request = Person.newBuilder().setId(id).build(); Person response; try { response = blockingStub.getPerson(request); } catch (StatusRuntimeException e) { System.out.println("RPC failed: ", e.getStatus()); return; } System.out.println("Person: " + response.getFirstName()); } }
  • 47. 47 Bringing it all together {REST} Web Mobile Third-party {REST}{REST} {REST} Front-end Gateway Backend
  • 48. 48 GraphQL {REST} Web Mobile Third-party {REST}{REST} {REST} Front-end Gateway Backend • Flexible • View-centered • Gateway • Simple • Limited functionality
  • 49. 49 gRPC {REST} Web Mobile Third-party {REST}{REST} {REST} `` Front-end Gateway Backend • High-performance • Machine-to-machine • Full-featured • Higher complexity
  • 50. 50 REST {REST} Web Mobile Third-party {REST}{REST} {REST} Front-end Gateway Backend • General purpose • Ubiquitous • Simple (ish) • Aligned with HTTP (but dev needs to get it right)
  • 51. 51 Summary Consideration REST GraphQL gRPC Capabilities/Scope General Narrow scope Feature-rich Ease of Use Simple -> Medium Simple Medium -> Hard Applicability General Excels at web/gateway Excels at high perf/throughput Ubiquity/Adoption Universal, High adoption Many languages Many languages, but not all environments Approach Contract-driven, bottom-up Bottom-up Contract-driven

Editor's Notes

  1. 1960s distributed computing 1970s RPC 1973/4 Ethernet invented. Standardized in the 1980s 1980s RPC emergence 1991 – CORBA 1994-97 – Fallacies of distributed computing 1996 – HTTP 1.1 XML 1.0 1998 – XML-RPC => SOAP Born 2000 Roy Fielding dissertation 2003 SOAP adds GET 2002-5 Microservices emergence 2005 JSON-RPC 2007 SOAP adds PUT, DELETE 2012 REST overtakes SOAP 2015 HTTP/2 – binary, server push, multiplexing (Standardization of Google SPDY) 2015 GraphQL released (2018 donated to Linux Foundation) 2015 gRPC Open Sourced - https://opensource.googleblog.com/2015/02/introducing-grpc-new-open-source-http2.html
  2. Int : Signed 32‐bit integer. Float : Signed double-precision floating-point value. String : UTF‐8 character sequence. Boolean : true or false. ID (serialized as String ): A unique identifier, often used to refetch an object or as the key for a cache. Can also define Custom Scalar types