gRPC Elixir Documentation

repository·master·Indexed 23 days ago

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

A full-featured Elixir implementation of the gRPC protocol supporting unary and streaming RPCs, interceptors, HTTP transcoding, and TLS. The project consists of specialized packages: `grpc` for client-only applications, `grpc_server` for server-only applications, and `grpc_core` providing foundational components like codecs (Protobuf, JSON, WebText, Erlpack), Gzip compression, and HTTP/2 utilities. It features a unified stream-based model for all call types and supports multiple connection schemes including DNS, IPv4, Unix domain sockets, and xDS.

Tokens
18K
Snippets
65
Records
102
Agent score
75%

What's inside gRPC Elixir

  1. Overview of grpc_core capabilities

    master

    The grpc_core package provides the foundational components used by both grpc_server and grpc. Its core features include:

    • Codecs: Support for Protocol Buffers, JSON, WebText, and Erlpack.
    • Compressors: Gzip compression support.
    • Transport: HTTP/2 utilities.
    • Core Types: Status codes, errors, credentials, and telemetry.
    • Protoc Plugin: Tooling for code generation.
  2. Manage gRPC connections using Mint adapter request counts

    master
    If you are using the Mint adapter for HTTP/2 connections, you can implement your own connection selection logic by monitoring the load on each connection. You can check how many requests are currently active on a specific connection using the open_request_count/1 function. This allows you to implement custom pooling or load-balancing strategies by choosing connections with lower request counts.
  3. Configure Load Balancing via Target Schemes

    master
    The GRPC.Stub.connect/2 function supports URI-like target strings that allow the client to dynamically resolve multiple backend endpoints. This enables automatic traffic distribution across services using different schemes like DNS or Unix domain sockets. Once the scheme is defined in the connection string, the load-balancing strategy is handled by the internal gRPC Resolver without requiring additional application code.
  4. How unified error propagation works in gRPC Elixir

    master

    In gRPC Elixir, all stream operators participate in a unified error propagation model. This model ensures that failures—whether they are returned as {:error, reason} tuples or raised as unexpected exceptions—are captured and translated consistently throughout the dataflow.

    Because the model normalizes outcomes, user-defined functions (transformations, side effects, or external calls) can raise, throw, or return error tuples without breaking the entire pipeline's execution flow. This allows developers to build composable, fault-tolerant streaming pipelines that can recover from both domain-specific errors and runtime faults.

  5. Limitation: Custom codecs and HTTP transcoding

    master

    Custom codecs are NOT supported when http_transcode: true is enabled.

    When HTTP transcoding is active, the library ignores any custom codecs in your configuration and always uses GRPC.Codec.JSON for both encoding and decoding HTTP/JSON requests and responses. This is to maintain compliance with the standard Google HTTP/JSON transcoding specification.

    Workarounds

    If you require custom encoding for HTTP endpoints:

    1. Disable HTTP transcoding and use standard gRPC with your custom codec.
    2. Create a separate HTTP endpoint (e.g., using Phoenix) that acts as a proxy to your gRPC service.
  6. Optimize Load Balancing Performance

    master

    The default round-robin balancing strategy makes a routing decision on every RPC, adding approximately ~290 ns of overhead per pick. This process is lock-free (using ETS reads and :atomics counters) and scales well with high concurrency.

    If your workload only ever communicates with a single endpoint and you wish to avoid the rotation cost, you can use the :pick_first strategy.

  7. Understand custom codec limitations with HTTP transcoding

    master

    ⚠️ IMPORTANT LIMITATION: Custom codecs are NOT supported when http_transcode: true is enabled.

    When using HTTP transcoding, the library always uses GRPC.Codec.JSON for encoding and decoding HTTP/JSON requests and responses, regardless of any custom codecs you have configured in the codecs list. This is because the library adheres to the standard HTTP/JSON transcoding specification which mandates JSON.

  8. Establish a basic gRPC client connection and perform RPC

    master

    To connect to a gRPC server, use GRPC.Stub.connect/1 with the server address. Once connected, you can pipe the resulting channel into a generated Stub module's method to perform an RPC call. The Stub methods typically follow the pattern Stub.method_name(channel, request).

    iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051")
    iex> request = Helloworld.HelloRequest.new(name: "grpc-elixir")
    iex> {:ok, reply} = channel |> Helloworld.GreetingServer.Stub.say_unary_hello(request)
  9. Establish a basic gRPC connection and perform RPCs

    master

    First, start the GRPC.Client.Supervisor in your application's supervision tree or manually via DynamicSupervisor. Then, use GRPC.Stub.connect/2 to create a channel and call methods on the generated Stub module.

    # 1. Start the supervisor
    children = [
      {GRPC.Client.Supervisor, []}
    ]
    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
    
    # 2. Connect and call RPC
    {:ok, channel} = GRPC.Stub.connect("localhost:50051")
    request = Helloworld.HelloRequest.new(name: "grpc-elixir")
    {:ok, reply} = channel |> Helloworld.GreetingServer.Stub.say_unary_hello(request)
  10. Enable automatic reconnection with Mint adapter

    master

    The Mint adapter supports automatic reconnection using exponential backoff with jitter. To enable this, pass the :retry option via adapter_opts in GRPC.Stub.connect/2.

    • Option: adapter_opts: [retry: N] where N is the number of attempts.
    • Behavior: Starts at ~1s delay, grows up to 120s max.
    • Failure: If all attempts fail, the parent process receives {:elixir_grpc, :connection_down, pid}.
    • Limitation: Reconnection only re-establishes the transport; it does not replay in-flight requests which will fail immediately upon connection drop.
    {:ok, channel} = GRPC.Stub.connect("localhost:50051",
      adapter: GRPC.Client.Adapters.Mint,
      adapter_opts: [retry: 5]
    )
  11. Implement custom gRPC connection pooling

    master

    As of the current version, elixir-grpc does not provide built-in pooling functionality. To manage large numbers of gRPC HTTP/2 connections, you can:

    1. Build your own pool: Use Elixir's Registry module to create a resource pool.
    2. Use an existing library: Use the conn_grpc package available on Hex, which provides a dedicated pool implementation.
  12. Start a gRPC Server in an Application

    master

    To run a gRPC server, add GRPC.Server.Supervisor to your application's supervision tree. You must provide an endpoint, a port, and set start_server: true.

    defmodule Helloworld.Application do
      @moduledoc false
      use Application
    
      @impl true
      def start(_type, _args) do
        children = [
          GrpcReflection,
          {
            GRPC.Server.Supervisor, [
              endpoint: Helloworld.Endpoint,
              port: 50051,
              start_server: true,
              # adapter_opts: [# any adapter-specific options like tls configuration....]
            ]
          }
        ]
    
        opts = [strategy: :one_for_one, name: Helloworld.Supervisor]
        Supervisor.start_link(children, opts)
      end
    end