mirror of
https://codeberg.org/JasterV/grpc-slides.git
synced 2026-04-26 18:40:03 +00:00
Update slides
This commit is contained in:
parent
cfcbc30ce5
commit
14d7cbee49
1 changed files with 92 additions and 152 deletions
|
|
@ -6,10 +6,10 @@ Victor Martinez
|
||||||
|
|
||||||
# First, what is RPC?
|
# First, what is RPC?
|
||||||
|
|
||||||
It stands for Remote Procedure Calls.
|
|
||||||
|
|
||||||
An idea to extend transfer of control and transmission of data from one machine to another.
|
An idea to extend transfer of control and transmission of data from one machine to another.
|
||||||
|
|
||||||
|
<img alt="RPC implementation" src="assets/images/rpc_architecture.png" style="width: 60%;" />
|
||||||
|
|
||||||
[http://birrell.org/andrew/papers/ImplementingRPC.pdf](http://birrell.org/andrew/papers/ImplementingRPC.pdf)
|
[http://birrell.org/andrew/papers/ImplementingRPC.pdf](http://birrell.org/andrew/papers/ImplementingRPC.pdf)
|
||||||
|
|
||||||
note:
|
note:
|
||||||
|
|
@ -26,17 +26,6 @@ They aimed to provide secure communications with RPC.
|
||||||
|
|
||||||
Things were shared in plain non secured text.
|
Things were shared in plain non secured text.
|
||||||
|
|
||||||
|
|
||||||
[1] WHITE, J. E. A high-level framework for network-based resource sharing. In Proc. National Computer Conference, (June 1976).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<img alt="RPC implementation" src="assets/images/rpc_architecture.png" style="width: 60%;" />
|
|
||||||
|
|
||||||
[http://birrell.org/andrew/papers/ImplementingRPC.pdf](http://birrell.org/andrew/papers/ImplementingRPC.pdf)
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
The program structure would be based in the concept of Stubs.
|
The program structure would be based in the concept of Stubs.
|
||||||
|
|
||||||
Five pieces of program are involved when making an RPC call:
|
Five pieces of program are involved when making an RPC call:
|
||||||
|
|
@ -47,37 +36,7 @@ They auto-generated the client and server stubs:
|
||||||
|
|
||||||
`The user-stub and server-stub are automatically generated, by a program called Lupine.`
|
`The user-stub and server-stub are automatically generated, by a program called Lupine.`
|
||||||
|
|
||||||
---
|
[1] WHITE, J. E. A high-level framework for network-based resource sharing. In Proc. National Computer Conference, (June 1976).
|
||||||
## Interface Definition Language
|
|
||||||
|
|
||||||
```thrift
|
|
||||||
struct Phone {
|
|
||||||
1: i32 id,
|
|
||||||
2: string number,
|
|
||||||
}
|
|
||||||
|
|
||||||
service PhoneService {
|
|
||||||
Phone findById(1: i32 id),
|
|
||||||
list<Phone> findAll()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Codegen tools will generate gRPC stubs from IDL code
|
|
||||||
|
|
||||||
An example of Thrift, an IDL used in Facebook's RPC framework
|
|
||||||
|
|
||||||
[https://github.com/facebook/fbthrift](https://github.com/facebook/fbthrift)
|
|
||||||
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
Many IDLs have been developed over time. Mozilla, Microsoft, IBM... and more developed their own internal RPC frameworks with their own IDLs [2]
|
|
||||||
|
|
||||||
In the paper mentioned above, they wrote the interface using the Mesa interface modules feature:
|
|
||||||
|
|
||||||
`This generation is specified by use of Mesa interface modules. These are the basis of the Mesa (and Cedar) separate compilation and binding mechanism [9]. An interface module is mainly a list of procedure names, together with the types of their arguments and results`
|
|
||||||
|
|
||||||
[2] https://en.wikipedia.org/wiki/Interface_description_language
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -182,9 +141,13 @@ https://protobuf.dev/
|
||||||
|
|
||||||
note:
|
note:
|
||||||
|
|
||||||
|
It is also developed by google.
|
||||||
|
|
||||||
Explain that it is the default binary serialization format supported by gRPC
|
Explain that it is the default binary serialization format supported by gRPC
|
||||||
|
|
||||||
It is also developed by google.
|
Many IDLs have been developed over time. Mozilla, Microsoft, IBM... and more developed their own internal RPC frameworks with their own IDLs [2]
|
||||||
|
|
||||||
|
[2] https://en.wikipedia.org/wiki/Interface_description_language
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -197,6 +160,8 @@ It is also developed by google.
|
||||||
|
|
||||||
note:
|
note:
|
||||||
|
|
||||||
|
Explain what an IDL is
|
||||||
|
|
||||||
Here we will focus on the IDL and the tooling, we won't focus on the serialization format.
|
Here we will focus on the IDL and the tooling, we won't focus on the serialization format.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -333,6 +298,86 @@ Explain that it builds on top of protoc. Be very short here, just mention the to
|
||||||
|
|
||||||
<img alt="rust logo" src="assets/images/rust.svg" style="width: 300px;" />
|
<img alt="rust logo" src="assets/images/rust.svg" style="width: 300px;" />
|
||||||
|
|
||||||
|
---
|
||||||
|
# Tower
|
||||||
|
|
||||||
|
<img alt="tower" src="assets/images/tower.png" style="width: 200px;" />
|
||||||
|
|
||||||
|
note:
|
||||||
|
|
||||||
|
Tower is a library of modular and reusable components for building robust networking clients and servers.
|
||||||
|
|
||||||
|
Tonic is built on top of Tower
|
||||||
|
|
||||||
|
It's core abstraction is the Service, which we see in the next slide.
|
||||||
|
|
||||||
|
It exposes already a set of basic reusable services to solve common networking patterns such as timeouts and rate limiting.
|
||||||
|
|
||||||
|
---
|
||||||
|
## Tower service
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub trait Service<Request> {
|
||||||
|
type Response;
|
||||||
|
type Error;
|
||||||
|
type Future: Future<Output = Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
|
||||||
|
|
||||||
|
fn call(&mut self, req: Request) -> Self::Future;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
note:
|
||||||
|
|
||||||
|
Tower’s fundamental abstraction.
|
||||||
|
|
||||||
|
An asynchronous function from a `Request` to a `Response`.
|
||||||
|
|
||||||
|
The `Service` trait is a simplified interface making it easy to write network applications in a modular and reusable way, decoupled from the underlying protocol.
|
||||||
|
|
||||||
|
It immediately returns a `Future` representing the eventual completion of processing the request.
|
||||||
|
|
||||||
|
The processing may depend on calling other services. At some point in the future, the processing will complete, and the `Future` will resolve to a response or error.
|
||||||
|
|
||||||
|
---
|
||||||
|
## Layers
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub trait Layer<S> {
|
||||||
|
type Service;
|
||||||
|
|
||||||
|
fn layer(&self, inner: S) -> Self::Service;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
note:
|
||||||
|
|
||||||
|
Mechanism to layer services. It allows us to wrap a generic service with another one. It can be used to wrap a reusable service which is meant to act as a middleware around another service.
|
||||||
|
|
||||||
|
---
|
||||||
|
## Building a layered service
|
||||||
|
|
||||||
|
```rust
|
||||||
|
ServiceBuilder::new()
|
||||||
|
.timeout(Duration::from_secs(10))
|
||||||
|
.layer(OpenTelemetryServerTracingLayer::new_for_grpc())
|
||||||
|
.layer(JwtAuthLayer::new(jwks_client, "starsky"))
|
||||||
|
.named_layer(StarskyServer::new(starsky_service));
|
||||||
|
```
|
||||||
|
|
||||||
|
note:
|
||||||
|
|
||||||
|
A real example of a layered service from Starsky. Slightly simplified for the sake of the presentation.
|
||||||
|
The flow will be the following:
|
||||||
|
Timeout -> SSRHL -> Tracing -> SSRHL -> Auth -> Starsky service
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Building a layered service
|
||||||
|
|
||||||
|
<img alt="tower" src="assets/images/layers-diagram.svg" style="max-width: 35%;" />
|
||||||
|
|
||||||
---
|
---
|
||||||
# Tonic
|
# Tonic
|
||||||
|
|
||||||
|
|
@ -557,34 +602,7 @@ note:
|
||||||
What if we wanted to add those headers for every request? Now we talk about interceptors
|
What if we wanted to add those headers for every request? Now we talk about interceptors
|
||||||
|
|
||||||
---
|
---
|
||||||
## Interceptors
|
|
||||||
|
|
||||||
Interceptors are similar to middleware but with less flexibility.
|
|
||||||
They allow you to:
|
|
||||||
- Add/remove/check items in the metadata of each request.
|
|
||||||
- Cancel a request with a `Status`.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Interceptors in practice
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use es_policy_grpc::policy_service::v1::PolicyManagementServiceServer as PolicyManagementServerStub;
|
|
||||||
use tonic::{metadata::MetadataValue, Request, Response, Status};
|
|
||||||
|
|
||||||
fn check_auth(req: Request<()>) -> Result<Request<()>, Status> {
|
|
||||||
match req.metadata().get(http::AUTHORIZATION) {
|
|
||||||
Some(t) if is_valid(t) => Ok(req),
|
|
||||||
_ => Err(Status::unauthenticated("No valid auth token")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let svc = PolicyManagementServerStub::with_interceptor(
|
|
||||||
PolicyManagementServiceImpl::new(application),
|
|
||||||
check_auth
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
## Health checking gRPC services
|
## Health checking gRPC services
|
||||||
|
|
||||||
Tonic provides a health check service implementing a standard gRPC health checking protocol.
|
Tonic provides a health check service implementing a standard gRPC health checking protocol.
|
||||||
|
|
@ -659,91 +677,13 @@ note:
|
||||||
Make it clear that we are using the `tonic-health` crate which doesn't come by default with `tonic`.
|
Make it clear that we are using the `tonic-health` crate which doesn't come by default with `tonic`.
|
||||||
|
|
||||||
---
|
---
|
||||||
**What about more complex middleware? What if we need to also intercept responses?**
|
|
||||||
|
|
||||||
Let's dive into Tower
|
# Building middleware with Tower
|
||||||
|
|
||||||
---
|
So, how can we take advantage of Tower in gRPC?
|
||||||
# Tower
|
|
||||||
|
|
||||||
<img alt="tower" src="assets/images/tower.png" style="width: 200px;" />
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
Tower is a library of modular and reusable components for building robust networking clients and servers.
|
|
||||||
|
|
||||||
Tonic is built on top of Tower
|
|
||||||
|
|
||||||
It's core abstraction is the Service, which we see in the next slide.
|
|
||||||
|
|
||||||
It exposes already a set of basic reusable services to solve common networking patterns such as timeouts and rate limiting.
|
|
||||||
|
|
||||||
---
|
|
||||||
## Tower service
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub trait Service<Request> {
|
|
||||||
type Response;
|
|
||||||
type Error;
|
|
||||||
type Future: Future<Output = Result<Self::Response, Self::Error>>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
|
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
Tower’s fundamental abstraction.
|
|
||||||
|
|
||||||
An asynchronous function from a `Request` to a `Response`.
|
|
||||||
|
|
||||||
The `Service` trait is a simplified interface making it easy to write network applications in a modular and reusable way, decoupled from the underlying protocol.
|
|
||||||
|
|
||||||
It immediately returns a `Future` representing the eventual completion of processing the request.
|
|
||||||
|
|
||||||
The processing may depend on calling other services. At some point in the future, the processing will complete, and the `Future` will resolve to a response or error.
|
|
||||||
|
|
||||||
---
|
|
||||||
## Layers
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub trait Layer<S> {
|
|
||||||
type Service;
|
|
||||||
|
|
||||||
fn layer(&self, inner: S) -> Self::Service;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
Mechanism to layer services. It allows us to wrap a generic service with another one. It can be used to wrap a reusable service which is meant to act as a middleware around another service.
|
|
||||||
|
|
||||||
---
|
|
||||||
## Building a layered service
|
|
||||||
|
|
||||||
```rust
|
|
||||||
ServiceBuilder::new()
|
|
||||||
.timeout(Duration::from_secs(10))
|
|
||||||
.layer(OpenTelemetryServerTracingLayer::new_for_grpc())
|
|
||||||
.layer(JwtAuthLayer::new(jwks_client, "starsky"))
|
|
||||||
.named_layer(StarskyServer::new(starsky_service));
|
|
||||||
```
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
A real example of a layered service from Starsky. Slightly simplified for the sake of the presentation.
|
|
||||||
The flow will be the following:
|
|
||||||
Timeout -> SSRHL -> Tracing -> SSRHL -> Auth -> Starsky service
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Building a layered service
|
|
||||||
|
|
||||||
<img alt="tower" src="assets/images/layers-diagram.svg" style="max-width: 35%;" />
|
|
||||||
|
|
||||||
---
|
|
||||||
## Authorization middleware
|
## Authorization middleware
|
||||||
|
|
||||||
Auth0 M2M authorization
|
Auth0 M2M authorization
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue