SlideShare uma empresa Scribd logo
1 de 197
gRPC vs REST
let the battle begin!
Alex Borysov, Software Engineer @ Google
Mykyta Protsenko, Software Engineer @ Roku
Kraków, 9-11 May 2018
Who are we?
Mykyta Protsenko
Software Engineer @ Roku
• passionate about all things scalable
• 18+ years in software engineering
• avid biker
• Author of Henka
REST vs gRPC
Alex Borysov
Software Engineer @ Google
• large scale systems developer
• 12+ years in software engineering
• devoxx.org.ua PC member
• Active gRPC user
REST vs gRPC
@aiborisov
@mykyta_p
@aiborisov
@mykyta_p
@aiborisov
@mykyta_p
JSON over HTTP
@aiborisov
@mykyta_p
I am getting frustrated by the number of people calling any
HTTP-based interface a REST API.
Roy Fielding
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
@aiborisov
@mykyta_p
@aiborisov
@mykyta_p
@aiborisov
@mykyta_p
RESTful API
GET /user/15
{
“name”: “John Doe”,
“email”:“john.doe@gmail.com”,
...
}
non-RESTful API
GET /last_search?page=2
{
“products”: [...]
...
}
@aiborisov
@mykyta_p
What is gRPC?
@aiborisov
@mykyta_p
What is gRPC?
A high performance, general purpose, feature-rich
RPC framework.
Part of Cloud Native Computing Foundation cncf.io
HTTP/2 and mobile first.
Open sourced version of Stubby RPC used in Google.
@aiborisov
@mykyta_p
g in gRPC stands for
1.0 'gRPC'
1.1 'good'
1.2 'green'
1.3 'gentle'
. . .
1.9 'glossy'
1.10 'glamorous'
1.11 'gorgeous'
1.12 'glorious'
@aiborisov
@mykyta_p
https://github.com/grpc/grpc/blob/master/doc/g_stands_for.md
RPC?! But...
AMF?
RMI?
CORBA?
@aiborisov
@mykyta_p
gRPC is not RMI
Maitainability
Ease of use
Performance
Scalability
L
e
s
s
o
n
s
Years of using Stubby
@aiborisov
@mykyta_p
What is gRPC?
Abstractions and best practices on how to design
RPCs.
Default implementation(s) from Google.
Extension points to plug custom implementations and
modifications.
Supports 10+ programming languages
@aiborisov
@mykyta_p
What is gRPC?
Abstractions and best practices on how to design
RPCs.
Default implementation(s) from Google.
Extension points to plug custom implementations and
modifications.
Supports 10+ programming languages, including JS!
@aiborisov
@mykyta_p
gRPC Interoperability
Java
Service
Python
Service
GoLang
Service
C++
Service
gRPC
Service
gRPC
Stub
gRPC
Stub
gRPC
Stub
gRPC
Service
gRPC
Service
gRPC
Service
@aiborisov
@mykyta_p
gRPC
Stub
gRPC-
Web
Stub
Apples to Oranges?
@aiborisov
@mykyta_p
Microservices?
@aiborisov
@mykyta_p
Microservices?
How to draw an owl?
@aiborisov
@mykyta_p
Microservices?
How to draw an owl?
How to build microservices?
@aiborisov
@mykyta_p
Microservices?
How to draw an owl?
How to build microservices?
Draw some circles.
@aiborisov
@mykyta_p
Microservices?
How to draw an owl?
How to build microservices?
Draw some circles.
Take XYZ framework.
@aiborisov
@mykyta_p
Microservices?
How to draw an owl?
How to build microservices?
Draw the REST of the owlDraw some circles.
Take XYZ framework.
@aiborisov
@mykyta_p
Microservices?
How to draw an owl?
How to build microservices?
Draw the REST of the owl
Write your microservices!
Draw some circles.
Take XYZ framework.
@aiborisov
@mykyta_p
Microservices
@aiborisov
@mykyta_p
Microservices
@aiborisov
@mykyta_p
Microservices
@aiborisov
@mykyta_p
Microservices
@aiborisov
@mykyta_p
Remote Calls
@aiborisov
@mykyta_p
Call Flow
@aiborisov
@mykyta_p
Service Discovery?
?
?
?
?
?
?
@aiborisov
@mykyta_p
Multiple Instances
#1
#N
#2
. . .
@aiborisov
@mykyta_p
Multiple Instances
#1
#N
#2
?
?
?
. . .
@aiborisov
@mykyta_p
Call Flow
@aiborisov
@mykyta_p
Call Flow
@aiborisov
@mykyta_p
Call Flow
@aiborisov
@mykyta_p
Call Flow
@aiborisov
@mykyta_p
Call Flow
@aiborisov
@mykyta_p
Slow Services?
@aiborisov
@mykyta_p
Failure Scenarios
@aiborisov
@mykyta_p
A distributed system is one in which the failure of a
computer you didn't even know existed can render your own
computer unusable.
Leslie Lamport, 1987
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/Distribution.pdf
@aiborisov
@mykyta_p
Fault Tolerance
@aiborisov
@mykyta_p
Microservices?! But...
Performance Hit?
Service Discovery?
Load Balancing?
Fault Tolerance?
Monitoring?
Testing?
@aiborisov
@mykyta_p
Sample Problem
Client
@aiborisov
@mykyta_p
Sample Problem: Aggregator
Src
#2
Src
#1
Aggr
...
Src
#X
Client
@aiborisov
@mykyta_p
Heterogeneous Data Format
Src
#2
Src
#1
Aggr
...
Src
#X
<XML>...<XML>
{JSON}
Binary 110011
[ Unified Format ]
Client
@aiborisov
@mykyta_p
REST: It’s All About Resources
@aiborisov
@mykyta_p
REST: Call Hierarchy
Controller
Service
Data Source A
. . .
Data Source N
RestTemplate
RestTemplate
RestTemplate
@aiborisov
@mykyta_p
REST: Data Source
JSON
URL: http://pokemon.com/content/11
{
"id": 11,
"content": "Pikachu"
}
XML
URL: http://crypto.com/content/22
<ContentResponse>
<id>22</id>
<content>Ethereum</content>
</ContentResponse>
@aiborisov
@mykyta_p
REST: Data Source
...
ResponseEntity<Content> contentEntity = restTemplate.getForEntity(
url + "{content_id}"
Content.class,
ImmutableMap.of("content_id", contentId));
...
@aiborisov
@mykyta_p
REST: Service
public class AggregatingService {
public AggregatedContent fetch(int id) {
...
return new AggregatedContent(...);
}
}
public class AggregatedContent {
private Integer id;
private String type;
private String content;
private Integer nextId;
@aiborisov
@mykyta_p
REST: Service
public class AggregatingService {
public AggregatedContent fetch(int id) {
...
return new AggregatedContent(...);
}
}
public class AggregatedContent {
private Integer id;
private String type;
private String content;
private Integer nextId;
@aiborisov
@mykyta_p
REST: Service
public class AggregatingService {
public AggregatedContent fetch(int id) {
...
return new AggregatedContent(...);
}
}
public class AggregatedContent {
private Integer id; // 115
private String type; // Pokemon
private String content; // Pikachu
private Integer nextId; // 116
@aiborisov
@mykyta_p
REST: Service
public class AggregatingService {
public AggregatedContent fetch(int id) {
...
return new AggregatedContent(...);
}
}
public class AggregatedContent {
private Integer id; // 115
private String type; // Pokemon
private String content; // Pikachu
private Integer nextId; // 116
@aiborisov
@mykyta_p
REST: Controller
@GetMapping(
value = "/content/{id}",
produces = "application/json")
public AggregatedContent aggregated(@PathVariable("id") int id) {
return aggregatingService.fetch(id);
}
@aiborisov
@mykyta_p
REST: It’s All About Resources
@GetMapping(
value = "/content/{id}",
produces = "application/json")
public AggregatedContent aggregated(@PathVariable("id") int id) {
return aggregatingService.fetch(id);
}
@aiborisov
@mykyta_p
REST: It’s simple
http://localhost:8080/content/115
{
"id": 115,
"content_type": "CRYPTO",
"content": "Ethereum",
"next_uri": "/content/116"
}
@aiborisov
@mykyta_p
REST: Service Discovery
@aiborisov
@mykyta_p
k8s/pokemon.yaml
...
kind: Service
metadata:
name: rest-pokemon-content-service
k8s/aggregator.yaml
...
env:
- name: datasource_a_url
value: "http://rest-pokemon-content-service:8080"
REST: Service Discovery
@aiborisov
@mykyta_p
k8s/pokemon.yaml
...
kind: Service
metadata:
name: rest-pokemon-content-service
k8s/aggregator.yaml
...
env:
- name: datasource_a_url
value: "http://rest-pokemon-content-service:8080"
REST: Service Discovery
@aiborisov
@mykyta_p
Controllers and POJOs, oh my!
public class AggregatedContent {
@JsonProperty("id")
private Integer id;
@JsonProperty("type")
private String type;
@JsonProperty("content")
private String content;
@JsonProperty("next_uri")
private String nextUri;
...
}
{
"id": 115,
"content_type": "Pokemon",
"content": "Pikachu",
"next_uri": "/content/116"
}
@aiborisov
@mykyta_p
gRPC: It’s All About APIs
@aiborisov
@mykyta_p
Sample Problem: Aggregator
Src
#2
Src
#1
Aggr
...
Src
#X
Client
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Get(AggregationRequest)
returns (AggregationResponse);
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Get(AggregationRequest)
returns (AggregationResponse);
}
message AggregationRequest {
int32 item_id = 1;
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
int32 next_item_id = 4;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Service Definition
aggregator.proto
@aiborisov
@mykyta_p
Service Definition
aggregator.proto
gRPC Runtime
@aiborisov
@mykyta_p
Service Definition
aggregator.proto
AggregationServiceImplBase.java AggregationRequest.java
AggregationResponse.java
AggregationServiceStub.java
AggregationServiceFutureStub.java
AggregationServiceBlockingStub.java
Service Implementation Request and response Client libraries
gRPC Java runtime
@aiborisov
@mykyta_p
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
StreamObserver<AggregationResponse> responseObserver) {
}
}
@aiborisov
@mykyta_p
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
StreamObserver<AggregationResponse> responseObserver) {
}
}
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
StreamObserver<AggregationResponse> responseObserver) {
}
}
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Blocking API (aka Thread-per-Request)?
Thread #3
Thread #2
Thread #1
Thread pool
of size X
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Blocking API (aka Thread-per-Request)?
Thread #3
Thread #2
Thread #1
Thread pool
of size X
1
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Blocking API (aka Thread-per-Request)?
Thread #3
Thread #2
Thread #1
Thread pool
of size X
1
2
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Blocking API (aka Thread-per-Request)?
Thread #3
Thread #2
Thread #1
Thread pool
of size X
1
2
3
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Thread #3
Thread #2
Blocking API (aka Thread-per-Request)?
Thread #1
Thread pool
of size X
1
2
3
X
. . .
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Thread #3
Thread #2
Blocking API (aka Thread-per-Request)?
Thread #1
Thread pool
of size X
1
2
3
X
. . .
X + 1
@aiborisov
@mykyta_p
Thread #X
Thread ...
Thread #7
Thread #6
Thread #5
Thread #4
Thread #3
Thread #2
Blocking API (aka Thread-per-Request)?
Thread #1
Thread pool
of size X
1
2
3
X
. . .
X + 1
@aiborisov
@mykyta_p
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
StreamObserver<AggregationResponse> responseObserver) {
}
}
@aiborisov
@mykyta_p
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
public interface StreamObserver<AggregationResponse> responseObserver){{
void onNext(AggregationResponse response);
void onCompleted();
void onError(Throwable error);
}
}
}
@aiborisov
@mykyta_p
Non-Blocking API
1
2
3
. . .
X + Y
X
. . .
@aiborisov
@mykyta_p
Non-Blocking API (aka Hollywood Principle)
1
2
3
. . .
X + Y
X
. . .
WillCallYouLater!
@aiborisov
@mykyta_p
Non-Blocking API (aka Hollywood Principle)
1
2
3
. . .
X + Y
X
. . .
WillCallYouLater!
onNext(1)
@aiborisov
@mykyta_p
Non-Blocking API (aka Hollywood Principle)
1
2
3
. . .
X + Y
X
. . .
WillCallYouLater!
onNext(3)
@aiborisov
@mykyta_p
Non-Blocking API (aka Hollywood Principle)
1
2
3
. . .
X + Y
X
. . .
WillCallYouLater!
onNext(X)
@aiborisov
@mykyta_p
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
StreamObserver<AggregationResponse> responseObserver) {
AggregationResponse response = AggregationResponse
.newBuilder()
.setId(request.getItemId())
.setContent("Ethereum")
.setType(ResponseType.CRYPTO)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
@aiborisov
@mykyta_p
Implement gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void get(AggregationRequest request,
StreamObserver<AggregationResponse> responseObserver) {
AggregationResponse response = AggregationResponse
.newBuilder()
.setId(request.getItemId())
.setContent("Ethereum")
.setType(ResponseType.CRYPTO)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Get(AggregationRequest)
returns (AggregationResponse);
}
message AggregationRequest {
int32 item_id = 1;
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
int32 next_item_id = 4;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Get(AggregationRequest)
returns (AggregationResponse);
}
message AggregationRequest {
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Get(AggregationRequest)
returns (AggregationResponse);
}
message AggregationRequest {
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Get(AggregationRequest)
returns (stream AggregationResponse);
}
message AggregationRequest {
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Subscribe(AggregationRequest)
returns (stream AggregationResponse);
}
message AggregationRequest {
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Service Definition (aggregator.proto)
syntax = "proto3";
service AggregationService {
rpc Subscribe(AggregationRequest)
returns (stream AggregationResponse);
}
message AggregationRequest {
}
message AggregationResponse {
int32 id = 1;
ResponseType type = 2;
string content = 3;
}
enum ResponseType {
UNDEFINED = 0;
POKEMON = 1;
CRYPTO = 2;
}
@aiborisov
@mykyta_p
Sample Problem: Aggregator
Src
#2
Src
#1
Aggr
...
Src
#X
Client
aggregator.proto
@aiborisov
@mykyta_p
Sample Problem: Content
Src
#2
Src
#1
Aggr
...
Src
#X
Client
aggregator.proto
content.proto
@aiborisov
@mykyta_p
content.proto
syntax = "proto3";
service ContentService {
rpc Subscribe(ContentRequest)
returns (stream ContentResponse);
}
message ContentRequest {
}
message ContentResponse {
int32 id = 1;
string content = 2;
}
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
private final Collection<ContentServiceStub> contentStubs;
public AggregationService(Collection<ContentServiceStub> contentStubs) {
this.contentStubs = contentStubs;
}
...
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void subscribe(AggregationRequest request,StreamObserver<AggregationResponse> responseObserver) {
contentStubs.forEach(stub -> { stub.subscribe(ContentRequest.getDefaultInstance(),
new StreamObserver<ContentResponse>() {
@Override
public void onNext(ContentResponse response) {
...
}
@Override
public void onError(Throwable error) {
responseObserver.onError(error);
}
@Override
public void onCompleted() {}
});
});
}
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void subscribe(AggregationRequest request,StreamObserver<AggregationResponse> responseObserver) {
contentStubs.forEach(stub -> { stub.subscribe(ContentRequest.getDefaultInstance(),
new StreamObserver<ContentResponse>() {
@Override
public void onNext(ContentResponse response) {
...
}
@Override
public void onError(Throwable error) {
responseObserver.onError(error);
}
@Override
public void onCompleted() {}
});
});
}
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void subscribe(AggregationRequest request,StreamObserver<AggregationResponse> responseObserver) {
contentStubs.forEach(stub -> { stub.subscribe(ContentRequest.getDefaultInstance(),
new StreamObserver<ContentResponse>() {
@Override
public void onNext(ContentResponse response) {
...
}
@Override
public void onError(Throwable error) {
responseObserver.onError(error);
}
@Override
public void onCompleted() {}
});
});
}
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void subscribe(AggregationRequest request,StreamObserver<AggregationResponse> responseObserver) {
contentStubs.forEach(stub -> { stub.subscribe(ContentRequest.getDefaultInstance(),
new StreamObserver<ContentResponse>() {
@Override
public void onNext(ContentResponse response) {
...
}
@Override
public void onError(Throwable error) {
responseObserver.onError(error);
}
@Override
public void onCompleted() {}
});
});
}
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void subscribe(AggregationRequest request,StreamObserver<AggregationResponse> responseObserver) {
contentStubs.forEach(stub -> { stub.subscribe(ContentRequest.getDefaultInstance(),
new StreamObserver<ContentResponse>() {
@Override
public void onNext(ContentResponse response) {
ResponseType type = typeForStub(stub);
int aggregationId = aggregationId(response.getId(), type);
AggregationResponse aggrResponse =
AggregationResponse.newBuilder()
.setContent(response.getContent()).setId(aggregationId).
.setType(type).build();
responseObserver.onNext(aggrResponse);
}
});
});
}
@aiborisov
@mykyta_p
Streaming gRPC Service
public class AggregationService extends AggregationServiceImplBase {
@Override
public void subscribe(AggregationRequest request,StreamObserver<AggregationResponse> responseObserver) {
contentStubs.forEach(stub -> { stub.subscribe(ContentRequest.getDefaultInstance(),
new StreamObserver<ContentResponse>() {
@Override
public void onNext(ContentResponse response) {
ResponseType type = typeForStub(stub);
int aggregationId = aggregationId(response.getId(), type);
AggregationResponse aggrResponse =
AggregationResponse.newBuilder()
.setContent(response.getContent()).setId(aggregationId).
.setType(type).build();
responseObserver.onNext(aggrResponse);
}
});
});
}
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client Subscribe()
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client Subscribe()
Subscribe()
Subscribe()
Subscribe()
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client
onNext()
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client
onNext()
onNext()
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client
onNext()
@aiborisov
@mykyta_p
Streaming gRPC Service
Src
#2
Src
#1
Aggr
...
Src
#X
Client onNext()
onNext()
@aiborisov
@mykyta_p
Start gRPC Server
ContentServiceStub cryptoClient = ...
ContentServiceStub pokemonClient = ...
Server grpcServer = NettyServerBuilder.forPort(8080)
.addService(new AggregationService(asList(cryptoClient, pokemonClient)))
.build().start();
@aiborisov
@mykyta_p
Start gRPC Server
ContentServiceStub cryptoClient = ...
ContentServiceStub pokemonClient = ...
Server grpcServer = NettyServerBuilder.forPort(8080)
.addService(new AggregationService(asList(cryptoClient, pokemonClient)))
.build().start();
@aiborisov
@mykyta_p
Create gRPC Client
String host = System.getenv("crypto_host");
int post = Integer.valueOf(System.getenv("crypto_port"));
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(host, port).build();
@aiborisov
@mykyta_p
Create gRPC Client
String host = System.getenv("crypto_host");
int post = Integer.valueOf(System.getenv("crypto_port"));
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(host, port).build();
ContentServiceStub cryptoClient = ContentServiceGrpc.newStub(cryptoChannel);
@aiborisov
@mykyta_p
Create gRPC Client
String host = System.getenv("crypto_host");
int port = Integer.valueOf(System.getenv("crypto_port"));
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(host, port).build();
ContentServiceStub cryptoClient = ContentServiceGrpc.newStub(cryptoChannel);
ContentServiceBlockingStub cryptoBlockingClient =
ContentServiceGrpc.newBlockingStub(cryptoChannel);
@aiborisov
@mykyta_p
Create gRPC Client
tring host = System.getenv("crypto_host");
int port = Integer.valueOf(System.getenv("crypto_port"));
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(host, port).build();
ContentServiceStub cryptoClient = ContentServiceGrpc.newStub(cryptoChannel);
ContentServiceBlockingStub cryptoBlockingClient =
ContentServiceGrpc.newBlockingStub(cryptoChannel);
ContentServiceFutureStub cryptoFutureClient =
ContentServiceGrpc.newFutureStub(cryptoChannel);
@aiborisov
@mykyta_p
Service Discovery & Load Balancing
String host = System.getenv("crypto_host");
int post = Integer.valueOf(System.getenv("crypto_port"));
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(host, port).build();
@aiborisov
@mykyta_p
Service Discovery & Load Balancing
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(host, port).build();
@aiborisov
@mykyta_p
Service Discovery & Load Balancing
ManagedChannel cryptoChannel = NettyChannelBuilder.forTarget("crypto")
.build();
@aiborisov
@mykyta_p
Service Discovery & Load Balancing
ManagedChannel cryptoChannel = NettyChannelBuilder.forTarget("crypto")
.nameResolverFactory(new DnsNameResolverProvider())
.loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance())
.build();
@aiborisov
@mykyta_p
Service Discovery & Load Balancing
ManagedChannel cryptoChannel = NettyChannelBuilder.forTarget("crypto")
.nameResolverFactory(new MyCustomNameResolverProviderFactory())
.loadBalancerFactory(new MyMoonPhaseLoadBalancerFactory())
.build();
@aiborisov
@mykyta_p
Netty
ManagedChannel cryptoChannel = NettyChannelBuilder.forTarget("crypto")
.nameResolverFactory(new MyCustomNameResolverProvider())
.loadBalancerFactory(new MyMoonPhaseLoadBalancerFactory())
.build();
@aiborisov
@mykyta_p
Netty + HTTP/2 + Protobuf
@aiborisov
@mykyta_p
Netty + HTTP/2 + Protobuf = Performance
http://www.grpc.io/docs/guides/benchmarking.html
@aiborisov
@mykyta_p
8 core VMs, streaming throughput
Netty + HTTP/2 + Protobuf = Performance
http://www.grpc.io/docs/guides/benchmarking.html
@aiborisov
@mykyta_p
32 core VMs, streaming throughput
Client Latency
...
900 ms!
@aiborisov
@mykyta_p
Caching
CDN
9 ms
...
@aiborisov
@mykyta_p
pay 24/7
Classic Cloud
VM
VM
LB
...
VM
pay as you go
@aiborisov
@mykyta_p
Serverless
pay as you go
Func
Funcinput
...
Func
input
...
input
@aiborisov
@mykyta_p
All about resources
IDL optional
Synchronous by default
Unary
Perfect fit for serverless
All about APIs
IDL centric
Asynchronous by nature
Streaming or Unary
Performance first
REST gRPC
@aiborisov
@mykyta_p
Sample Problem
Src
#2
Src
#1
...
Src
#X
Client Aggr
@aiborisov
@mykyta_p
Sample Problem: Voting
Src
#2
Src
#1
...
Src
#X
Client
Voting
Aggr
@aiborisov
@mykyta_p
Sample Problem: Voting
Src
#2
Src
#1
...
Src
#X
Client
Voting
Aggr
@aiborisov
@mykyta_p
Sample Problem: Voting
Src
#2
Src
#1
...
Src
#X
Client
Voting
Aggr
@aiborisov
@mykyta_p
Sample Problem: Voting & Leaderboard
Src
#2
Src
#1
...
Src
#X
Client
Voting
Aggr
L-board
@aiborisov
@mykyta_p
Sample Problem: Voting & Leaderboard
Src
#2
Src
#1
...
Src
#X
Client
Voting
Aggr
L-board
@aiborisov
@mykyta_p
Sample Problem: Voting & Leaderboard
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
Aggr
L-board
@aiborisov
@mykyta_p
Sample Problem
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Failing Leaderboard
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Cascading Failure
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Cascading Failure
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Cascading Failure
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Circuit Breaker
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Circuit Breaker
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Circuit Breaker
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Circuit Breaker
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Circuit Breaker
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Circuit Breaker
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Slow Services
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Timeouts?
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
200 ms
2 sec
@aiborisov
@mykyta_p
Large Timeouts
Gateway Voting L-Board
1,000 ms
timeout
1,000 ms
timeout
200 ms
client timeout
@aiborisov
@mykyta_p
Large Timeouts
Gateway Voting L-Board
1,000 ms
timeout
1,000 ms
timeout
200 ms
client timeout
50 ms
@aiborisov
@mykyta_p
Large Timeouts
Gateway Voting L-Board
1,000 ms
timeout
1,000 ms
timeout
200 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
Large Timeouts
Gateway Voting L-Board
1,000 ms
timeout
1,000 ms
timeout
200 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
Large Timeouts
Gateway Voting L-Board
1,000 ms
timeout
1,000 ms
timeout
200 ms
client timeout
50 ms
400 ms
300 ms
@aiborisov
@mykyta_p
Short Timeouts
Gateway Voting L-Board
100 ms
timeout
100 ms
timeout
@aiborisov
@mykyta_p
Short Timeouts
Gateway Voting L-Board
100 ms
timeout
100 ms
timeout
2,000 ms
client timeout
@aiborisov
@mykyta_p
Short Timeouts
Gateway Voting L-Board
100 ms
timeout
100 ms
timeout
2,000 ms
client timeout
50 ms
@aiborisov
@mykyta_p
Short Timeouts
Gateway Voting L-Board
100 ms
timeout
100 ms
timeout
2,000 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
Short Timeouts
Gateway Voting L-Board
100 ms
timeout
100 ms
timeout
2,000 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
Short Timeouts
Gateway Voting L-Board
100 ms
timeout
100 ms
timeout
2,000 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
gRPC Deadline Propagation
Gateway Voting L-Board
200 ms
client timeout
@aiborisov
@mykyta_p
gRPC Deadline Propagation
Gateway Voting L-Board
200 ms
client timeout
50 ms
@aiborisov
@mykyta_p
gRPC Deadline Propagation
Gateway Voting L-Board
200 - 50 ms
timeout
200 ms
client timeout
50 ms
@aiborisov
@mykyta_p
gRPC Deadline Propagation
Gateway Voting L-Board
200 - 50 ms
timeout
200 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
gRPC Deadline Propagation
Gateway Voting L-Board
200 - 50 - 400 ms
timeout
200 - 50 ms
timeout
200 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
gRPC Deadline Propagation (Short)
Gateway Voting L-Board
200 - 50 - 400 ms
timeout
200 - 50 ms
timeout
200 ms
client timeout
50 ms
400 ms
@aiborisov
@mykyta_p
gRPC Deadline Propagation (Large)
Gateway Voting L-Board
2,000 - 50 - 400 ms
timeout
2,000 - 50 ms
timeout
2,000 ms
client timeout
50 ms
400 ms
300 ms
@aiborisov
@mykyta_p
Investigation
Src
#2
Src
#1
...
Src
#X
Gateway
VotingL-board
Aggr
@aiborisov
@mykyta_p
Gateway
VotingL-board
Aggr
Investigation
Src
#2
Src
#1
...
Src
#X
@aiborisov
@mykyta_p
VotingL-board
Aggr
Investigation
Src
#2
Src
#1
...
Src
#X
Gateway
@aiborisov
@mykyta_p
L-board
Aggr
Investigation
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
@aiborisov
@mykyta_p
L-board
Aggr
Investigation
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
@aiborisov
@mykyta_p
Aggr
L-board
Investigation
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
@aiborisov
@mykyta_p
Aggr
L-board
Investigation
Src
#2
Src
#1
...
Src
#X
Gateway
Voting
@aiborisov
@mykyta_p
Zipkin: Traces and Latency
@aiborisov
@mykyta_p
Zipkin and gRPC
https://github.com/openzipkin/brave/tree/master/instrumentation/grpc
URLConnectionSender sender = ...
GrpcTracing grpcTracing = GrpcTracing.create(Tracing.newBuilder()
.sampler(ALWAYS_SAMPLE).spanReporter(AsyncReporter.create(sender)).build());
@aiborisov
@mykyta_p
Zipkin and gRPC
https://github.com/openzipkin/brave/tree/master/instrumentation/grpc
URLConnectionSender sender = ...
GrpcTracing grpcTracing = GrpcTracing.create(Tracing.newBuilder()
.sampler(ALWAYS_SAMPLE).spanReporter(AsyncReporter.create(sender)).build());
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(cryptoHost, cryptoPort)
.intercept(grpcTracing.newClientInterceptor())
.build();
Server grpcServer = NettyServerBuilder.forPort(8080)
.addService(new AggregationService(asList(cryptoClient, pokemonClient)))
.intercept(grpcTracing.newServerInterceptor())
.build().start();
@aiborisov
@mykyta_p
Zipkin and gRPC
https://github.com/openzipkin/brave/tree/master/instrumentation/grpc
URLConnectionSender sender = ...
GrpcTracing grpcTracing = GrpcTracing.create(Tracing.newBuilder()
.sampler(ALWAYS_SAMPLE).spanReporter(AsyncReporter.create(sender)).build());
ManagedChannel cryptoChannel = NettyChannelBuilder.forAddress(cryptoHost, cryptoPort)
.intercept(grpcTracing.newClientInterceptor())
.build();
Server grpcServer = NettyServerBuilder.forPort(8080)
.addService(new AggregationService(asList(cryptoClient, pokemonClient)))
.intercept(grpcTracing.newServerInterceptor())
.build().start();
@aiborisov
@mykyta_p
Zipkin and REST
build.gradle:
dependencies {
compile 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
compile 'org.springframework.cloud:spring-cloud-starter-sleuth'
...
application.properties:
spring.zipkin.baseUrl=http://zipkin:9411/
# sample 100%
spring.sleuth.sampler.percentage=1.0
...
@aiborisov
@mykyta_p
Proxy
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Proxy
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Proxy
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Proxy
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Proxy
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
Sidecar Proxies
Gateway
Voting
Aggr
@aiborisov
@mykyta_p
No code changes
Implementation neutral
Isolation
Cross-cutting functionality
No additional calls
Deeper integration
Flexibility
Span Customization
Sidecar/proxy Instrumentation
@aiborisov
@mykyta_p
Zipkin : REST and gRPC
@aiborisov
@mykyta_p
http://GrpcRest.com
@aiborisov
@mykyta_p
Explore More?
Demo: https://github.com/grpcvsrest
@aiborisov
@mykyta_p
Explore More?
Demo: https://github.com/grpcvsrest
http://grpc.io
https://github.com/grpc
http://www.grpc.io/docs/quickstart/java.html
gRPC -Web: https://github.com/grpc/grpc-web
gRPC Google group: grpc-io@googlegroups.com
REST: http://google.com/search?q=rest
@aiborisov
@mykyta_p
Demo UI is written by
Yevgen Golubenko
Software Engineer @ Anomali
• Twitter: @HalloGene_
• github.com/HalloGene
• linkedin.com/in/yevgen-golubenko
@aiborisov
@mykyta_p
REST gRPC
@aiborisov
@mykyta_p
All about resources
Synchronous and unary
Simplicity first
External fault-tolerance
Production ready
All about APIs
Async and streaming
Performance first
Built-in fault-tolerance
Production ready
REST gRPC
@aiborisov
@mykyta_p
All about resources
Synchronous and unary
Simplicity first
External fault-tolerance
Production ready
All about APIs
Async and streaming
Performance first
Built-in fault-tolerance
Production ready
REST gRPC
Be pragmatic,
start with your problem!
@aiborisov
@mykyta_p
Questions?
@aiborisov
@mykyta_p

Mais conteúdo relacionado

Mais procurados

WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016
WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016
WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016
崇之 清水
 
Surviving in a Microservices Environment
Surviving in a Microservices EnvironmentSurviving in a Microservices Environment
Surviving in a Microservices Environment
Steve Pember
 
A Modest Introduction to Swift
A Modest Introduction to SwiftA Modest Introduction to Swift
A Modest Introduction to Swift
John Anderson
 

Mais procurados (16)

"gRPC-Web: It’s All About Communication": Devoxx Belgium 2019
"gRPC-Web: It’s All About Communication": Devoxx Belgium 2019"gRPC-Web: It’s All About Communication": Devoxx Belgium 2019
"gRPC-Web: It’s All About Communication": Devoxx Belgium 2019
 
"gRPC-Web: It’s All About Communication": Devoxx Ukraine 2019
"gRPC-Web: It’s All About Communication": Devoxx Ukraine 2019"gRPC-Web: It’s All About Communication": Devoxx Ukraine 2019
"gRPC-Web: It’s All About Communication": Devoxx Ukraine 2019
 
Break me if you can: practical guide to building fault-tolerant systems (with...
Break me if you can: practical guide to building fault-tolerant systems (with...Break me if you can: practical guide to building fault-tolerant systems (with...
Break me if you can: practical guide to building fault-tolerant systems (with...
 
"gRPC-Web: It’s All About Communication": Devoxx Ukraine 2019
"gRPC-Web:  It’s All About Communication": Devoxx Ukraine 2019"gRPC-Web:  It’s All About Communication": Devoxx Ukraine 2019
"gRPC-Web: It’s All About Communication": Devoxx Ukraine 2019
 
Cloud Expo Europe 2022 "Break me if you can: practical guide to building faul...
Cloud Expo Europe 2022 "Break me if you can: practical guide to building faul...Cloud Expo Europe 2022 "Break me if you can: practical guide to building faul...
Cloud Expo Europe 2022 "Break me if you can: practical guide to building faul...
 
"Enabling Googley microservices with gRPC" Riga DevDays 2018 edition
"Enabling Googley microservices with gRPC" Riga DevDays 2018 edition"Enabling Googley microservices with gRPC" Riga DevDays 2018 edition
"Enabling Googley microservices with gRPC" Riga DevDays 2018 edition
 
Curl with rust
Curl with rustCurl with rust
Curl with rust
 
WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016
WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016
WordPress RESTful API & Amazon API Gateway - WordCamp Kansai 2016
 
The spring ecosystem in 50 min
The spring ecosystem in 50 minThe spring ecosystem in 50 min
The spring ecosystem in 50 min
 
Surviving in a Microservices Environment
Surviving in a Microservices EnvironmentSurviving in a Microservices Environment
Surviving in a Microservices Environment
 
A Modest Introduction to Swift
A Modest Introduction to SwiftA Modest Introduction to Swift
A Modest Introduction to Swift
 
Re invent 2018 - The Evolution of AircraftML
Re invent 2018  - The Evolution of AircraftMLRe invent 2018  - The Evolution of AircraftML
Re invent 2018 - The Evolution of AircraftML
 
Docker Docker - Docker Security - Docker
Docker Docker - Docker Security - DockerDocker Docker - Docker Security - Docker
Docker Docker - Docker Security - Docker
 
Google Machine Learning APIs - puppies or muffins?
Google Machine Learning APIs - puppies or muffins?Google Machine Learning APIs - puppies or muffins?
Google Machine Learning APIs - puppies or muffins?
 
Building Serverless applications with Python
Building Serverless applications with PythonBuilding Serverless applications with Python
Building Serverless applications with Python
 
3h à l'assaut d'une application réactive - Devoxx 2015
3h à l'assaut d'une application réactive - Devoxx 20153h à l'assaut d'une application réactive - Devoxx 2015
3h à l'assaut d'une application réactive - Devoxx 2015
 

Semelhante a "gRPC vs REST: let the battle begin!" GeeCON Krakow 2018 edition

In graph we trust: Microservices, GraphQL and security challenges
In graph we trust: Microservices, GraphQL and security challengesIn graph we trust: Microservices, GraphQL and security challenges
In graph we trust: Microservices, GraphQL and security challenges
Mohammed A. Imran
 

Semelhante a "gRPC vs REST: let the battle begin!" GeeCON Krakow 2018 edition (20)

Ibm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshopIbm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshop
 
Guillotina: The Asyncio REST Resource API
Guillotina: The Asyncio REST Resource APIGuillotina: The Asyncio REST Resource API
Guillotina: The Asyncio REST Resource API
 
Devoxx Belgium 2022 gRPC Cornerstone: HTTP/2… or HTTP/3?
Devoxx Belgium 2022 gRPC Cornerstone: HTTP/2… or HTTP/3?Devoxx Belgium 2022 gRPC Cornerstone: HTTP/2… or HTTP/3?
Devoxx Belgium 2022 gRPC Cornerstone: HTTP/2… or HTTP/3?
 
Managing microservices with istio on OpenShift - Meetup
Managing microservices with istio on OpenShift - MeetupManaging microservices with istio on OpenShift - Meetup
Managing microservices with istio on OpenShift - Meetup
 
HowYourAPIBeMyAPI
HowYourAPIBeMyAPIHowYourAPIBeMyAPI
HowYourAPIBeMyAPI
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
DevSecCon Singapore 2018 - in graph we trust By Imran Mohammed
DevSecCon Singapore 2018 - in graph we trust By Imran MohammedDevSecCon Singapore 2018 - in graph we trust By Imran Mohammed
DevSecCon Singapore 2018 - in graph we trust By Imran Mohammed
 
In graph we trust: Microservices, GraphQL and security challenges
In graph we trust: Microservices, GraphQL and security challengesIn graph we trust: Microservices, GraphQL and security challenges
In graph we trust: Microservices, GraphQL and security challenges
 
OWASPAPISecurity
OWASPAPISecurityOWASPAPISecurity
OWASPAPISecurity
 
Free The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainFree The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own Domain
 
JSON Web Tokens Will Improve Your Life
JSON Web Tokens Will Improve Your LifeJSON Web Tokens Will Improve Your Life
JSON Web Tokens Will Improve Your Life
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
 
Day 2 Kubernetes - Tools for Operability (HashiConf)
Day 2 Kubernetes - Tools for Operability (HashiConf)Day 2 Kubernetes - Tools for Operability (HashiConf)
Day 2 Kubernetes - Tools for Operability (HashiConf)
 
Developing with the Modern App Stack: MEAN and MERN (with Angular2 and ReactJS)
Developing with the Modern App Stack: MEAN and MERN (with Angular2 and ReactJS)Developing with the Modern App Stack: MEAN and MERN (with Angular2 and ReactJS)
Developing with the Modern App Stack: MEAN and MERN (with Angular2 and ReactJS)
 
Origins of Serverless
Origins of ServerlessOrigins of Serverless
Origins of Serverless
 
The 7 Deadly Sins of API Design
The 7 Deadly Sins of API DesignThe 7 Deadly Sins of API Design
The 7 Deadly Sins of API Design
 
KazooCon 2014 - Introduction to Kazoo APIs!
KazooCon 2014 - Introduction to Kazoo APIs!KazooCon 2014 - Introduction to Kazoo APIs!
KazooCon 2014 - Introduction to Kazoo APIs!
 
Building Beautiful REST APIs with ASP.NET Core
Building Beautiful REST APIs with ASP.NET CoreBuilding Beautiful REST APIs with ASP.NET Core
Building Beautiful REST APIs with ASP.NET Core
 

Último

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 

"gRPC vs REST: let the battle begin!" GeeCON Krakow 2018 edition