Reading Notes on https://time.geekbang.org/column/75
My Pre-read: Netty in Action it is fairly important to understand what is Netty before looking into gRPC internals.
01 | Introduction to gRPC & How gRPC server works
Existing RPC frameworks:
- Multi-language support: gRPC from Google, Thrift from Facebook
- Limited language support: Motan
- Distributed service framework: Dubbo
gRPC is a high performant, OSS and general purpose RPC framework based on HTTP/2.
- Language neutral: multi-language support
- IDL based. Code generation via proto3.
- Base on HTTP/2, support bidirectional flow, header compression, TCP multiplex, server push etc.
- Support for Protocol Buffer & JSON.
How gRPC server is created:
- gRPC init NettyServer (base on Netty 4.1 HTTP/2).
- Server registers API implementations generated from proto tool to its internal service registry and when requests come in, it invokes registered service instance by searching service name & method name instead of via reflection, which makes performance even better.
- gRPC server impl invokes NettyServer’s start method to start HTTP/2 server and receive user requests.
How gRPC server responds to user requests
- Netty 4.1 provides HTTP/2 support. gRPC implements Http2ConnectionHandler to manage messages from HTTP/2.
- gRPC uses NioEventLoopGroup to avoid resources overload.
02 | How gRPC Client Works
Creation of gRPC client
gRPC sits on top of HTTP/2 and is an application layer protocol. In client side, it creates HTTP/2 client based on Netty, provides load balance and is responsible for request handling.
- Client init a RPC invocation.
- Resolve host address via DnsNameResolver and use LoadBalancer to select one of the available gRPC server instance.
- Serialize PB and leverage HTTP/2 stream to send to gRPC server.
- Deserialize PB response.
- Invoke set(Response) method in GrpcFuture an invoke blocking client thread.
gRPC supports 3 ways of Protocol Negotiation
- Server supports HTTP/2, saves the cost of protocol upgrade.
- Use HTTP/1.1 for protocol negotiation and upgrade afterwards.
- TlsNegotiator. This is built directly on top of TLS and uses ALPN extension for negotiation. It uses ‘h2’ as protocol marker.
How Netty sets up connection for HTTP/2
Two types of load balancing
- Server side LB (external LB, delegation LB)
- Client side LB (internal LB & algo implemented in client side)
An example of external LB:
Pros of this architecture is client side doesn’t have to implement LB algorithms nor maintain server list. This also benefits network isolation.
Example of client side LB:
By default, gRPC uses client side LB and provides mechanisms to extend.
03 | gRPC Thread Model Analysis
This was discussed in the Netty In Action reading notes, this is a typical NIO Reactor pattern:
The performance of RPC framework depends on 3 key factors:
- I/O model. BIO/NIO or AIO.
- Protocol. Rest + JSON or binary TCP protocol.
- Thread model. Where are decoding/encoding performed.
Server Side Thread Model
HTTP/2 server creation, request handling are handled by netty and de/serialization is handled by gRPC’s SerializingExecutor thread pool.
Client Side Thread Model
04 | How gRPC Service Call Works
A couple common service call mechanisms:
- Synchronous call.
- Parallelized service call.
- Aynschronous service call.
gRPC provides 2 ways of RPC call
- Normal RPC call: request and respond.
- Streaming call base on HTTP/2. Make it possible that server(or client) can reply with multiple responses (like 1000 feed items, batch by batch).
05 | gRPC Security Design
Cross networking boundary communications should be transmitted through TLS/SSL.
If only a portion of the transmitted data has sensitive data, we can also only encrypt that portion of data:
This can be easy achieved with Netty Handler.
There are a couple ways of performing identity authentication: HTTP Basic Authentication, OAuth2, Token etc. An example of Token authentication:
Access Level Authentication
A common approach is OAuth 2.0 based authentication:
- Client request Resource Owner for authentication (w/ username, password, etc..)
- Resource Owner authenticate base on the information provided and assign auth token to the client.
- Client uses token from step 2 and request access token from Authorization Server.
- Authorization Server issues access token once validated.
- Client carries access token to its RPC call to backend resources.
- Backend services validate access token for acess.
- If access token passes validation, Resource server returns information to the client.
Data Integrity and Consistency
Use SHA & MAC.
gRPC Security Mechanisms
- Channel Auth. Default provides TLS based on HTTP/2.
- Invocation Auth. Credentials are added to the message headers for each RPC invocation.
- Combo Auth. 1 + 2.
- Google OAuth 2.0. When you access Google API with gRPC, it uses Service Accounts key to request for access token.
06 | gRPC Serialization
Common Serialization Framework
- can’t cross languages.
- not performant.
- Support tons of languages
- The IDL is super powerful
- Provides forward compatibility
- Changes in data structure requires editing IDL file, regenerate code.
An efficient binary protocol.
Mature, cross platform/language/effective/performant and forward compatibility.
Proto Buffers is supported in Netty. You just need to add Codec Handler to the ChannelPipeline.
How gRPC Serialization Works?
- Use builder pattern to set key-values based on ProtoBuf generated code and set up a message
- Serialize message in 1) and create a ProtoInputStream.
- Create NettyClientStream and gRPC HTTP/2 headers.
- Wrap serialized message into SendGrpcFrameCommand and send through Netty’s NIO thread.
- gRPC’s NettyClientHandler incepts the write request and uses Http2ConnectionEncoder to send it out through Netty’s HTTP/2 protocol stack.
End of Story