first commit

This commit is contained in:
JasterV 2025-06-10 18:48:58 +02:00
commit 4a146513f4
11 changed files with 950 additions and 0 deletions

6
.github/dependabot vendored Normal file
View file

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"

32
.github/workflows/publish.yml vendored Normal file
View file

@ -0,0 +1,32 @@
on:
push:
branches:
- main
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install mkslides
- run: mkslides build docs/
- uses: actions/upload-pages-artifact@v3
with:
path: ./site
- id: deployment
uses: actions/deploy-pages@v4

BIN
docs/assets/grpc-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

134
docs/assets/rpc_types.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 41 KiB

47
docs/assets/rust.svg Normal file
View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 1200 800" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<g id="Layer-1" serif:id="Layer 1">
<g transform="matrix(1,0,0,1,597.344,637.02)">
<path d="M0,-279.559C-121.238,-279.559 -231.39,-264.983 -312.939,-241.23L-312.939,-38.329C-231.39,-14.575 -121.238,0 0,0C138.76,0 262.987,-19.092 346.431,-49.186L346.431,-230.37C262.987,-260.465 138.76,-279.559 0,-279.559" style="fill:rgb(165,43,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,1068.75,575.642)">
<path d="M0,-53.32L-14.211,-82.761C-14.138,-83.879 -14.08,-84.998 -14.08,-86.121C-14.08,-119.496 -48.786,-150.256 -107.177,-174.883L-107.177,2.643C-79.932,-8.849 -57.829,-21.674 -42.021,-35.482C-46.673,-16.775 -62.585,21.071 -75.271,47.686C-96.121,85.752 -103.671,118.889 -102.703,120.53C-102.086,121.563 -94.973,110.59 -84.484,92.809C-60.074,58.028 -13.82,-8.373 -4.575,-25.287C5.897,-44.461 0,-53.32 0,-53.32" style="fill:rgb(165,43,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,149.064,591.421)">
<path d="M0,-99.954C0,-93.526 1.293,-87.194 3.788,-80.985L-4.723,-65.835C-4.723,-65.835 -11.541,-56.989 0.465,-38.327C11.055,-21.872 64.1,42.54 92.097,76.271C104.123,93.564 112.276,104.216 112.99,103.187C114.114,101.554 105.514,69.087 81.631,32.046C70.487,12.151 57.177,-14.206 49.189,-33.675C71.492,-19.559 100.672,-6.755 135.341,4.265L135.341,-204.17C51.797,-177.622 0,-140.737 0,-99.954" style="fill:rgb(165,43,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(-65.8097,-752.207,-752.207,65.8097,621.707,796.312)">
<path d="M0.991,-0.034L0.933,0.008C0.933,0.014 0.933,0.02 0.933,0.026L0.99,0.069C0.996,0.073 0.999,0.08 0.998,0.087C0.997,0.094 0.992,0.1 0.986,0.103L0.92,0.133C0.919,0.139 0.918,0.145 0.916,0.15L0.964,0.203C0.968,0.208 0.97,0.216 0.968,0.222C0.965,0.229 0.96,0.234 0.953,0.236L0.882,0.254C0.88,0.259 0.877,0.264 0.875,0.27L0.91,0.33C0.914,0.336 0.914,0.344 0.91,0.35C0.907,0.356 0.9,0.36 0.893,0.361L0.82,0.365C0.817,0.369 0.813,0.374 0.81,0.379L0.832,0.445C0.835,0.452 0.833,0.459 0.828,0.465C0.824,0.47 0.816,0.473 0.809,0.472L0.737,0.462C0.733,0.466 0.729,0.47 0.724,0.474L0.733,0.544C0.734,0.551 0.731,0.558 0.725,0.562C0.719,0.566 0.711,0.568 0.704,0.565L0.636,0.542C0.631,0.546 0.626,0.549 0.621,0.552L0.615,0.621C0.615,0.629 0.61,0.635 0.604,0.638C0.597,0.641 0.589,0.641 0.583,0.638L0.521,0.602C0.52,0.603 0.519,0.603 0.518,0.603L0.406,0.729C0.406,0.729 0.394,0.747 0.359,0.725C0.329,0.705 0.206,0.599 0.141,0.543C0.109,0.52 0.089,0.504 0.09,0.502C0.093,0.499 0.149,0.509 0.217,0.554C0.278,0.588 0.371,0.631 0.38,0.619C0.38,0.619 0.396,0.604 0.406,0.575C0.406,0.575 0.406,0.575 0.406,0.575C0.407,0.576 0.407,0.576 0.406,0.575C0.406,0.575 0.091,0.024 0.305,-0.531C0.311,-0.593 0.275,-0.627 0.275,-0.627C0.266,-0.639 0.178,-0.598 0.12,-0.566C0.055,-0.523 0.002,-0.513 0,-0.516C-0.001,-0.518 0.018,-0.533 0.049,-0.555C0.11,-0.608 0.227,-0.707 0.256,-0.726C0.289,-0.748 0.301,-0.73 0.301,-0.73L0.402,-0.615C0.406,-0.614 0.41,-0.613 0.415,-0.613L0.47,-0.658C0.475,-0.663 0.483,-0.664 0.49,-0.662C0.497,-0.66 0.502,-0.655 0.504,-0.648L0.522,-0.58C0.527,-0.578 0.533,-0.576 0.538,-0.574L0.602,-0.608C0.608,-0.612 0.616,-0.612 0.623,-0.608C0.629,-0.605 0.633,-0.599 0.633,-0.592L0.637,-0.522C0.642,-0.519 0.647,-0.515 0.652,-0.512L0.721,-0.534C0.728,-0.536 0.736,-0.535 0.741,-0.531C0.747,-0.526 0.75,-0.519 0.749,-0.512L0.738,-0.443C0.742,-0.439 0.746,-0.435 0.751,-0.431L0.823,-0.439C0.83,-0.44 0.837,-0.437 0.842,-0.432C0.847,-0.426 0.848,-0.419 0.845,-0.412L0.821,-0.347C0.824,-0.342 0.828,-0.337 0.831,-0.332L0.903,-0.327C0.911,-0.327 0.917,-0.322 0.92,-0.316C0.924,-0.31 0.924,-0.302 0.92,-0.296L0.883,-0.236C0.885,-0.231 0.887,-0.226 0.889,-0.22L0.959,-0.202C0.966,-0.2 0.972,-0.195 0.974,-0.188C0.976,-0.181 0.974,-0.174 0.969,-0.168L0.92,-0.116C0.921,-0.111 0.923,-0.105 0.924,-0.099L0.988,-0.068C0.995,-0.065 0.999,-0.059 1,-0.052C1.001,-0.045 0.997,-0.038 0.991,-0.034ZM0.406,0.575C0.406,0.575 0.406,0.575 0.406,0.575C0.406,0.575 0.406,0.575 0.406,0.575Z" style="fill:url(#_Linear1);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,450.328,483.629)">
<path d="M0,167.33C-1.664,165.91 -2.536,165.068 -2.536,165.068L140.006,153.391C23.733,0 -69.418,122.193 -79.333,135.855L-79.333,167.33L0,167.33Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,747.12,477.333)">
<path d="M0,171.974C1.663,170.554 2.536,169.71 2.536,169.71L-134.448,159.687C-18.12,0 69.421,126.835 79.335,140.497L79.335,171.974L0,171.974Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(-1.53e-05,-267.211,-267.211,1.53e-05,809.465,764.23)">
<path d="M1,-0.586C1,-0.586 0.768,-0.528 0.524,-0.165L0.5,-0.064C0.5,-0.064 1.1,0.265 0.424,0.731C0.424,0.731 0.508,0.586 0.405,0.197C0.405,0.197 0.131,0.376 0.14,0.736C0.14,0.736 -0.275,0.391 0.324,-0.135C0.324,-0.135 0.539,-0.691 1,-0.736L1,-0.586Z" style="fill:url(#_Linear2);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,677.392,509.61)">
<path d="M0,-92.063C0,-92.063 43.486,-139.678 86.974,-92.063C86.974,-92.063 121.144,-28.571 86.974,3.171C86.974,3.171 31.062,47.615 0,3.171C0,3.171 -37.275,-31.75 0,-92.063" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,727.738,435.209)">
<path d="M0,0.002C0,18.543 -10.93,33.574 -24.408,33.574C-37.885,33.574 -48.814,18.543 -48.814,0.002C-48.814,-18.539 -37.885,-33.572 -24.408,-33.572C-10.93,-33.572 0,-18.539 0,0.002" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,483.3,502.984)">
<path d="M0,-98.439C0,-98.439 74.596,-131.467 94.956,-57.748C94.956,-57.748 116.283,28.178 33.697,33.028C33.697,33.028 -71.613,12.745 0,-98.439" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,520.766,436.428)">
<path d="M0,0C0,19.119 -11.27,34.627 -25.173,34.627C-39.071,34.627 -50.344,19.119 -50.344,0C-50.344,-19.124 -39.071,-34.627 -25.173,-34.627C-11.27,-34.627 0,-19.124 0,0" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(-1.53e-05,-239.021,-239.021,1.53e-05,402.161,775.388)">
<path d="M0.367,0.129C-0.364,-0.441 0.223,-0.711 0.223,-0.711C0.259,-0.391 0.472,-0.164 0.472,-0.164C0.521,-0.548 0.525,-0.77 0.525,-0.77C1.203,-0.256 0.589,0.161 0.589,0.161C0.627,0.265 0.772,0.372 0.906,0.451L1,0.77C0.376,0.403 0.367,0.129 0.367,0.129Z" style="fill:url(#_Linear3);fill-rule:nonzero;"/>
</g>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,1.38778e-17,-1,0,-0.000650515)"><stop offset="0" style="stop-color:rgb(247,76,0);stop-opacity:1"/><stop offset="0.33" style="stop-color:rgb(247,76,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(244,150,0);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,-1,0,1.23438e-06)"><stop offset="0" style="stop-color:rgb(204,58,0);stop-opacity:1"/><stop offset="0.15" style="stop-color:rgb(204,58,0);stop-opacity:1"/><stop offset="0.74" style="stop-color:rgb(247,76,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(247,76,0);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,1.32349e-23,1.32349e-23,-1,0,-9.1568e-07)"><stop offset="0" style="stop-color:rgb(204,58,0);stop-opacity:1"/><stop offset="0.15" style="stop-color:rgb(204,58,0);stop-opacity:1"/><stop offset="0.74" style="stop-color:rgb(247,76,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(247,76,0);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

4
docs/assets/tonic.svg Normal file
View file

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.59961 14.1C4.59961 17.7 7.49961 20.6 11.0996 20.6C11.7996 20.6 12.4996 20.5 13.0996 20.3C12.9996 21.1 12.8996 21.9 12.8996 22.7C12.8996 29.2 18.1996 34.4 24.5996 34.4C31.0996 34.4 36.2996 29.1 36.2996 22.7C36.2996 16.3 31.0996 11.1 24.5996 11.1C23.9996 11.1 23.4996 11.2 22.8996 11.3C23.0996 10.8 23.1996 10.3 23.1996 9.8C23.1996 7.4 21.2996 5.5 18.8996 5.5C16.7996 5.5 15.0996 7 14.6996 8.9C13.6996 8.2 12.4996 7.8 11.1996 7.8C7.79961 7.9 4.59961 10.5 4.59961 14.1ZM20.7996 9.9C20.7996 10.8 19.9996 11.6 19.0996 11.6C18.1996 11.6 17.3996 10.8 17.3996 9.9C17.3996 9 18.1996 8.2 19.0996 8.2C19.9996 8.2 20.5996 8.9 20.7996 9.9ZM15.3996 22.8C15.3996 17.7 19.4996 13.6 24.5996 13.6C29.6996 13.6 33.7996 17.7 33.7996 22.8C33.7996 27.9 29.7996 32 24.5996 32C19.5996 32 15.3996 27.9 15.3996 22.8ZM7.39961 14.2C7.39961 12 9.09961 10.3 11.2996 10.3C13.4996 10.3 15.1996 12 15.1996 14.2C15.1996 16.4 13.3996 18.1 11.2996 18.1C9.19961 18.1 7.39961 16.5 7.39961 14.2Z" fill="#E2B619"/>
<path d="M24.5994 24.4996C23.5994 24.4996 22.8994 23.6996 22.8994 22.7996C22.8994 21.7996 23.6994 21.0996 24.5994 21.0996C25.5994 21.0996 26.2994 21.8996 26.2994 22.7996C26.4994 23.5996 25.5994 24.4996 24.5994 24.4996Z" fill="#E2B619"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 79 KiB

BIN
docs/assets/tower.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

597
docs/learning_grpc.md Normal file
View file

@ -0,0 +1,597 @@
---
---
# Learning gRPC
Victor Martinez
---
## First, what is RPC?
An idea to replicate to extend transfer of control and transmission of data from one machine to another.
<a style="font-size: 20px;" href="http://birrell.org/andrew/papers/ImplementingRPC.pdf">
http://birrell.org/andrew/papers/ImplementingRPC.pdf
</a>
note:
At the time, building applications that required communicating with a separate machine was difficult and required big expertise, so much that only a few network experts were designated to.
One of the aims of this RPC implementation was to make it highly efficient (network-wise) as well as as simple to use as non-remote procedures.
They believed that by providing a simple interface and tool for machine to machine communications, it would make it more accessible for less expert people to implement distributed applications.
Also, they aimed to provide secure communications with RPC. At the time, none of the implemented protocols inside their network had no security at all to the point where passwords were being sent as plain text.
The concept dates back to 1976 [1]
[1] WHITE, J. E. A high-level framework for network-based resource sharing. In Proc. National Computer Conference, (June 1976).
---
![image](assets/rpc_architecture.png)
<a style="font-size: 20px;" href="http://birrell.org/andrew/papers/ImplementingRPC.pdf">
http://birrell.org/andrew/papers/ImplementingRPC.pdf
</a>
note:
Back in the time they already used a tool to auto-generate the client and server stubs:
`But the user-stub and server-stub are automatically generated, by a program called Lupine.`
---
### Interface Definition Language
```protobuf
struct Phone {
1: i32 id,
2: string number,
}
service PhoneService {
Phone findById(1: i32 id),
list<Phone> findAll()
}
```
<p style="font-size: 26px;">
An example of Thrift, an IDL used in Facebook's RPC framework
</p>
<a style="font-size: 20px;" href="https://github.com/facebook/fbthrift">
https://github.com/facebook/fbthrift
</a>
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
---
<img alt="grpc" src="assets/grpc-logo.png" style="width: 600px;" />
*gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment.*
<a style="font-size: 26px;" href="https://grpc.io/">
https://grpc.io/
</a>
note: google Remote procedure calls
"gRPC was initially created by Google, which has used a single general-purpose RPC infrastructure called **Stubby** to connect the large number of microservices running within and across its data centers. In March 2015, Google decided to build the next version of Stubby and make it open source. The result was **gRPC**"
---
### Why a framework?
gRPC dictates how you will build your network interface.
Code is generated for you batteries included, you must only fill the gaps.
note: All the underlying details about networking, encoding & more is handled for you.
It is more a framework in the sense of servers. They must use the generated Server Stub, with the only need of implementing the Service interfaces.
Clients will use the generated client Stub. For them the gRPC code will be less intrusive and will feel more like a library
Some implementations wrap the original C library, some don't.
---
### Built on top of HTTP2
So we get for free
- **Multiplexing**
- Header **compression**
- **Server push**
- **TLS**
note: Explain multiplexing and server push
---
### 4 types of RPC supported
![image](assets/rpc_types.svg)
note: Explain that each of these RPC types can be specified on the protobuffers IDL
---
### Metadata
Key-value pairs of data used to provide additional information about a call.
Implemented using HTTP/2 headers.
<a style="font-size: 20px;" href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
</a>
note: gRPC metadata can be sent and received by both the client and the server. Headers are sent from the client to the server before the initial request and from the server to the client before the initial response of an RPC call.
On the link I show, they document the supported values for metadata
Can be useful for: Authentication & tracing
---
### And many more features
- **Flow control** for streaming
- RPC automatic & manual **cancellations**
- **Reflection** (Service discoverability & ease debugging)
- **Load balancing** (Client requests can be load balanced between multiple servers)
- Call **retries**
- **Health checking** (Service-specific health checking)
- **Interceptors** (Middleware for RPCs)
note: It is important to explain that these features might differ from language to language, since it depends completely on how each of them implements gRPC
- **Flow control** is a mechanism to ensure that a receiver of messages does not get overwhelmed by a fast sender. Flow control prevents data loss, improves performance and increases reliability.
- **Reflection**: Explain that we won't go in detail about reflection but that I believe we should research more about it since it can be useful for better developer experience
- **Health check**: gRPC specifies a standard service API ([health/v1](https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto)) for performing health check calls against gRPC servers. An implementation of this service is provided, but you are responsible for updating the health status of your services. It is pluggable, and some languages might not provide it.
---
### Protocol buffers
*Protocol Buffers are language-neutral, platform-neutral extensible mechanisms for serializing structured data.*
https://protobuf.dev/
note: Explain that it is the default binary serialization format supported by gRPC
It is also developed by google.
---
### They are a combination of
- The **Interface Definition Language**
- The compiler that **generates code** from IDL files
- Language-specific **runtimes**
- The **serialization format**
note: Here we will focus on the IDL and the tooling, we won't focus on the serialization format.
---
### Protobufs as an Interface Definition Language
---
### Defining a service
```protobuf
// service/v1/service.proto
syntax = "proto3";
package service.v1;
import "amend_termination/request/v1/request.proto";
import "amend_termination/response/v1/response.proto";
service PolicyManagementService {
rpc AmendTermination(amend_termination.request.v1.AmendTerminationRequest) returns (amend_termination.response.v1.AmendTerminationResponse);
}
```
---
### Defining messages
```protobuf
// amend_termination/request/v1/request.proto
syntax = "proto3";
package amend_termination.request.v1;
import "terminate_policy/request/v1/request.proto";
import "google/protobuf/timestamp.proto";
message AmendTerminationRequest {
string policy_id = 1;
google.protobuf.Timestamp requested_at = 2;
google.protobuf.Timestamp interruption_at = 3;
optional string description = 4;
oneof reason {
terminate_policy.request.v1.CustomerTerminateReason customer = 5;
terminate_policy.request.v1.PrimaTerminateReason prima = 6;
}
}
```
---
### The protoc compiler
Compiles `.proto` files into code.
Supports plugins for different languages.
```bash
protoc --proto_path=src --python_out=build/gen src/foo.proto
```
note: `--proto_path` specifies the source directory, `--*_out` the destination directory, and the rest is the path to your `.proto`
---
### Buf CLI
- A **linter** for proto files
- A **formatter** for proto files
- A system to organize your proto files by **workspaces**
- A feature to check for **breaking changes** in your definitions
- A **plugin system** to compile proto files into multiple formats
- **Editor integration**
- And more!
<a style="font-size: 20px;" href="https://buf.build/product/cli">
https://buf.build/product/cli
</a>
note: Explain that it builds on top of protoc. Be very short here, just mention the tool briefly. It is important because we use it.
---
### Buf CLI
```bash
buf format
```
```bash
buf lint
```
```bash
buf breaking --against ".git#branch=master"
```
---
### Remarkable features of Protocol buffers
- **Strongly typed** data
- **Language** and **platform neutral**
- **Compact binary format**
- **Backward and Forward compatibility**
- Support for **RPC service definition**
note: Give a short example of why it is backward and forward compatible. Mention tags.
---
## gRPC in the Rust ecosystem
<img alt="grpc" src="assets/grpc-logo.png" style="width: 200px;" />
:heart:
<img alt="rust logo" src="assets/rust.svg" style="width: 100px;" />
---
# Tonic
<img alt="tonic logo" src="assets/tonic.svg" style="width: 200px;" />
<br />
<a style="font-size: 24px;" href="https://github.com/hyperium/tonic">
https://github.com/hyperium/tonic
</a>
note: Built on top of Tower, Tonic is a gRPC over HTTP/2 implementation focused on **high performance**, **interoperability**, and **flexibility**.
It has first class support for async/await.
The main goal of tonic is to provide a generic gRPC implementation over HTTP/2 framing.
Codegen tools need to be used to generate the client and server stubs that will encode and decode the binary data and deal with other gRPC features such as streaming.
---
### Features
- **TLS**
- **Load balancing**
- RPC cancellation via **timeouts**
- Request/Response **compression**
- Bidirectional **streaming**
- **Health check** of services
- **Interceptors**
- **Reflection**
- Client & Server **stub generation**
- Extensible via **Tower** services
note: These are only a few notable features, it provides more for sure
---
### Generate code from Proto definitions :gear:
```rust
// build.rs
let mut prost_build = prost_build::Config::new();
prost_build.compile_protos(
&["<path_to_proto_messages>"],
&["proto"],
)?;
tonic_build::configure()
.compile_protos(
&["proto/es_policy_grpc/service/v1/service.proto"],
&["proto"],
)?;
```
note: First we need to talk about how do we generate code from our protobuf definitions.
---
### Expose the generated code as a library
```rust
// lib.rs
pub mod policy_service {
pub mod v1 {
include!(concat!(env!("OUT_DIR"), "/es_policy_grpc.service.v1.rs"));
}
}
```
note: We need to expose the generated code through our lib.rs
---
### Auto generated services
```rust
pub trait PolicyManagementService {
async fn withdraw_policy(
&self,
request: Request<WithdrawPolicyRequest>,
) -> Result<Response<WithdrawPolicyResponse>, Status>
// ...
}
```
note: We get a trait generated from the Protobuf Service definition
---
### Building a server
```rust
// main.rs
let server =
// gRPC server implemented on top of HTTP2
Server::builder()
.add_service(
// Policy Management Server Stub
PolicyManagementServiceServer::new(
// Implementation of the service
PolicyManagementServiceImpl::new(application)
)
);
let listener = TcpListener::bind(("0.0.0.0", grpc_port)).await?;
server.serve(listener).await?;
```
note: Simple build of a Tonic Server. We will dive into how to add middleware later.
Highlight the fact that at the end of the day the gRPC server will be listening to a TCP port like any other HTTP2 server.
---
### Building a client
```rust
let mut client =
// Auto-generated client stub
PolicyManagementServiceClient::connect("http://[::1]:50051").await?;
let mut request = tonic::Request::new(GenerateContractRequest {
// ..
});
let token: MetadataValue<_> = "Bearer some-auth-token".parse()?;
request.metadata_mut.insert("authentication", token);
let _response = client.generate_contract(request).await?;
```
note: 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
fn check_auth(req: Request<()>) -> Result<Request<()>, Status> {
match req.metadata().get("authorization") {
Some(t) if is_valid(t) => Ok(req),
_ => Err(Status::unauthenticated("No valid auth token")),
}
}
let svc = PolicyManagementServiceServer::with_interceptor(
PolicyManagementServiceImpl::new(application),
check_auth
);
```
---
### Health checking gRPC services
Tonic provides a health check service implementing a standard gRPC health checking protocol.
<a style="font-size: 20px;" href="https://github.com/grpc/grpc/blob/master/doc/health-checking.md">
https://github.com/grpc/grpc/blob/master/doc/health-checking.md
</a>
note: A GRPC service is used as the health checking mechanism.
Since it is a GRPC service itself, doing a health check is in the same format as a normal rpc.
It has rich semantics such as per-service health status.
The server has full control over the access of the health checking service.
---
### Health service definition
```protobuf
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
```
<p style="font-size: 28px;">
This definition is provided by the official gRPC docs, each language runtime might implement it or not.
</p>
<a style="font-size: 20px;" href="https://github.com/grpc/grpc/blob/master/doc/health-checking.md">
https://github.com/grpc/grpc/blob/master/doc/health-checking.md
</a>
---
### Enabling the health service
```rust
let (health_reporter, health_service) = health_reporter();
health_reporter
.set_serving::<PolicyManagementServiceServer<PolicyManagementServiceImpl>>()
.await;
Server::builder()
// Add other layers
.layer(..)
.add_service(health_service)
.serve(addr)
.await?;
```
note: 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
---
# Tower
<img alt="tower" src="assets/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: Towers 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; // This can be a middleware
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
---
<img alt="tower" src="assets/tower-layers-diagram.svg" style="max-width: 50%;" />
---
Now let's dive into real middleware implementations
---
### Authentication Layer
TODO
---
### Tracing Layer
TODO

6
mkslides.yml Normal file
View file

@ -0,0 +1,6 @@
slides:
theme: league
highlight_theme: vs
revealjs:
history: true
slideNumber: c/t