gRPC-Go

repository·master·Indexed 12 days ago

https://github.com/grpc/grpc-go

Go implementation of gRPC, a high-performance, open-source RPC framework designed for mobile and HTTP/2-first environments. Includes the protoc-gen-go-grpc plugin for generating Go language bindings from .proto files, as well as support for Advanced TLS, OAuth2 authentication, RBAC authorization via StaticInterceptor and FileWatcherInterceptor, and custom load balancing policies.

Tokens
49.1K
Snippets
167
Records
252
Agent score
96%

What's inside gRPC-Go

  1. Overview of Advanced TLS security configurations

    master

    The Advanced TLS examples demonstrate the following security setups:

    Server Configurations:

    • Port 8885: Uses certificate providers and CRL providers with a valid certificate.
    • Port 8884: Uses certificate providers and CRL providers with a revoked certificate.
    • Port 8883: Runs using InsecureCredentials.

    Client Configurations:

    • mTLS with certificate providers and CRLs.
    • mTLS with custom verification.
    • mTLS using credentials from credentials.NewTLS (directly utilizing a tls.Config).
    • Insecure Credentials.
  2. What is a name resolver in gRPC-Go

    master
    A name resolver acts as a mapping mechanism that translates a service name into a list of backend IP addresses (e.g., map[service-name][]backend-ip). This allows a ClientConn to resolve a logical service name to physical network addresses. A common implementation of a name resolver is DNS. In gRPC-Go, the specific resolver used is determined by the scheme prefix in the target connection string.
  3. What is ORCA Load Reporting

    master

    ORCA is a protocol designed for reporting load information between servers and clients. It allows servers to communicate their current load state to clients, enabling more intelligent load balancing decisions. This is implemented via two independent mechanisms:

    1. Out-of-band (OOB) Metrics: Metrics are reported regularly at specific intervals over a stream.
    2. Per-RPC Metrics: Metrics are reported alongside trailers at the end of an individual RPC call.

    For the full specification, refer to gRFC A51.

  4. Configure load balancing policies in gRPC-Go

    master

    You can control how a ClientConn selects backend addresses by specifying a load balancing policy. This is typically done on the client side using grpc.WithDefaultServiceConfig.

    Supported default policies include:

    • pick_first: Attempts to connect to the first address in the list. If successful, all RPCs are sent to that same backend. If the connection fails, it tries the next address until one succeeds.
    • round_robin: Connects to all available addresses and distributes RPCs across them in a rotating order (e.g., backend-1, then backend-2, then backend-1 again).

    Note that round_robin only picks connections that are currently in a 'ready' state. If a connection is not ready, the balancer will send RPCs to the available ready connections instead.

    // Example of configuring a client with a specific load balancing policy
    conn, err := grpc.Dial(
        target,
        grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`),
        // ... other options
    )
  5. Concurrency rules for gRPC-Go streams

    master

    When working with a grpc.Stream, you must follow specific concurrency rules to avoid race conditions:

    • Safe: One goroutine calling SendMsg while another goroutine calls RecvMsg on the same stream.
    • Unsafe: Multiple goroutines calling SendMsg on the same stream simultaneously.
    • Unsafe: Multiple goroutines calling RecvMsg on the same stream simultaneously.
  6. How gRPC Health Checking works

    master

    gRPC provides a health library that allows servers to communicate their operational status to clients using the health/v1 API. This enables clients to gracefully avoid servers that are experiencing issues.

    There are two primary ways clients interact with health services:

    1. Check(): A unary RPC used to probe a server's current health.
    2. Watch(): A streaming RPC used to observe real-time changes in health status.

    Servers manage their status by inspecting dependent systems and updating their state. A server can report one of four states:

    • UNKNOWN: The current state is not yet determined (common during startup).
    • SERVING: The system is healthy and ready to handle requests.
    • NOT_SERVING: The system is currently unable to service requests.
    • SERVICE_UNKNOWN: The specific serviceName requested by the client is not recognized by the server (reported via Watch()).
  7. How authentication works in gRPC-Go

    master

    Authentication in gRPC-Go is abstracted via the credentials.PerRPCCredentials interface. It allows users to attach credentials to RPC calls, which can be configured at two levels:

    1. Per-connection basis: Using grpc.WithPerRPCCredentials(PerRPCCredentials) during the Dial process. This applies the same credentials to all RPC calls made over that specific connection.
    2. Per-call basis: Using grpc.PerRPCCredentials(PerRPCCredentials) as a CallOption when invoking a specific RPC method. This allows different credentials for different calls.

    Note that for OAuth2, the underlying transport must be secure (e.g., TLS).

  8. Understand the stats.Handler lifecycle and events

    master

    The stats.Handler interface allows you to observe specific events in the RPC and connection lifecycles through two primary methods:

    RPC Events

    The HandleRPC(context.Context, RPCStats) method is called multiple times during a single request-response cycle. The RPCStats parameter will be one of the following concrete types:

    • *stats.Begin: The start of an RPC.
    • *stats.InHeader: Incoming headers.
    • *stats.InPayload: Incoming message payload.
    • *stats.InTrailer: Incoming trailers.
    • *stats.OutHeader: Outgoing headers.
    • *stats.OutPayload: Outgoing message payload.
    • *stats.OutTrailer: Outgoing trailers.
    • *stats.End: The end of an RPC.

    Note: The order of these events may differ between the client and the server.

    Connection Events

    The HandleConn(context.Context, ConnStats) method is called twice per connection:

    • Once with *stats.ConnBegin at the start of the connection.
    • Once with *stats.ConnEnd at the end of the connection.
  9. Understand the Dualstack example pattern

    master

    The Dualstack example demonstrates how to use a custom name resolver to handle both IPv4 and IPv6 endpoints. In this pattern, a name resolver provides multiple loopback addresses for server instances, allowing a client to connect to different address types (IPv4, IPv6, or both) using round-robin load balancing.

    In the provided example, three server instances are configured with different binding behaviors:

    1. [::]:50052: Listens on both IPv4 and IPv6 loopback addresses.
    2. 127.0.0.1:50050: Listens only on the IPv4 loopback address.
    3. [::1]:50051: Listens only on the IPv6 loopback address.

    The client uses a custom name resolver and round-robin load balancing to cycle through these servers. The server response includes its serving port and address type (IPv4, IPv6, or both) to verify the connection type.

  10. How to use different name resolver schemes

    master

    You can select a name resolver by specifying a scheme in the target string used during dialing.

    • passthrough:///<address>: The passthrough resolver takes the input address directly and uses it as the backend address without further resolution.
    • <custom-scheme>:///<service-name>: Uses a registered custom resolver to map the service name to backend addresses.

    In the provided example, the client dials example:///resolver.example.grpc.io, which triggers a custom example resolver to return localhost:50051 as the backend address.

  11. How Compressors work in gRPC-Go

    master

    A Compressor reduces the size of the serialized byte stream before transmission. Like Codecs, Compressors are registered in a global registry in the encoding package and must be symmetric (registered on both client and server).

    When a compressor is used, the content-coding header is set to the <compressor name>. If a server receives a message with a compression format it does not recognize, it will reject the request with a status code Unimplemented.

    package gzip
    
    import "google.golang.org/grpc/encoding"
    
    func init() {
        encoding.RegisterCompressor(compressor{})
    }
    
    // ... implementation of compressor ...