Configuration

A gRPC client is configured with a GrpcClientSettings instance. There are a number of ways of creating one and the API docs are the best reference. An ActorSystem is always required as it is used for default configuration and service discovery.

By Code

The simplest way to create a client is to provide a static host and port.

Scala
GrpcClientSettings.connectToServiceAt("localhost", 443)
Java
GrpcClientSettings.connectToServiceAt("localhost", 443, actorSystem);

Further settings can be added via the with methods

Scala
GrpcClientSettings.connectToServiceAt("localhost", 443).withDeadline(1.second).withTls(false)
Java
GrpcClientSettings.connectToServiceAt("localhost", 443, actorSystem)
        .withDeadline(Duration.ofSeconds(1))
        .withTls(false);

By Configuration

Instead a client can be defined in configuration. All client configurations need to be under akka.grpc.client

Scala
akka.grpc.client {
  "project.WithSpecificConfiguration" {
    service-discovery {
      service-name = "my-service"
    }
    host = "my-host"
    port = 42
    override-authority = "google.fr"
    deadline = 10m
    user-agent = "Akka-gRPC"
  }
}
Java
akka.grpc.client {
  "project.WithSpecificConfiguration" {
    service-discovery {
      service-name = "my-service"
    }
    host = "my-host"
    port = 42
    override-authority = "google.fr"
    deadline = 10m
    user-agent = "Akka-gRPC"
  }
}

Clients defined in configuration pick up defaults from reference.conf:

Scala
akka.grpc.client."*" {

  # Host to use if service-discovery-mechanism is set to static
  host = ""

  service-discovery {
    mechanism = "static"
    # Service name to use if a service-discovery.mechanism other than static
    service-name = ""
    # See https://developer.lightbend.com/docs/akka-management/current/discovery/index.html for meanings for each mechanism
    # if blank then not passed to the lookup
    port-name = ""
    protocol = ""

    # timeout for service discovery resolving
    resolve-timeout = 1s
  }

  # port to use if service-discovery-mechism is static or service discovery does not return a port
  port = 0

  # pick_first or round_robin
  # TODO: test more policies, add support by using io.grpc.internal.AbstractManagedChannelImplBuilder.defaultServiceConfig
  grpc-load-balancing = ""

  deadline = infinite
  override-authority = ""
  user-agent = ""
  # Pulls default configuration from ssl-config-core's reference.conf
  ssl-config = ${ssl-config}
  use-tls = true

  # TODO: Enforce HTTP/2 TLS restrictions: https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-9.2

  creation {
    # How many times to retry client creation before giving up
    attempts = 1000

    # How long to wait between client creation attempts
    delay = 400ms
  }

  connection-attempts = -1

  # Service discovery mechamism to use. The default is to use a static host
  # and port that will be resolved via DNS.
  # Any of the mechanisms described [here](https://developer.lightbend.com/docs/akka-management/current/discovery/index.html) can be used
  # including Kubernetes, Consul, AWS API
}
Java
akka.grpc.client."*" {

  # Host to use if service-discovery-mechanism is set to static
  host = ""

  service-discovery {
    mechanism = "static"
    # Service name to use if a service-discovery.mechanism other than static
    service-name = ""
    # See https://developer.lightbend.com/docs/akka-management/current/discovery/index.html for meanings for each mechanism
    # if blank then not passed to the lookup
    port-name = ""
    protocol = ""

    # timeout for service discovery resolving
    resolve-timeout = 1s
  }

  # port to use if service-discovery-mechism is static or service discovery does not return a port
  port = 0

  # pick_first or round_robin
  # TODO: test more policies, add support by using io.grpc.internal.AbstractManagedChannelImplBuilder.defaultServiceConfig
  grpc-load-balancing = ""

  deadline = infinite
  override-authority = ""
  user-agent = ""
  # Pulls default configuration from ssl-config-core's reference.conf
  ssl-config = ${ssl-config}
  use-tls = true

  # TODO: Enforce HTTP/2 TLS restrictions: https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-9.2

  creation {
    # How many times to retry client creation before giving up
    attempts = 1000

    # How long to wait between client creation attempts
    delay = 400ms
  }

  connection-attempts = -1

  # Service discovery mechamism to use. The default is to use a static host
  # and port that will be resolved via DNS.
  # Any of the mechanisms described [here](https://developer.lightbend.com/docs/akka-management/current/discovery/index.html) can be used
  # including Kubernetes, Consul, AWS API
}

Using Akka Discovery for Endpoint Discovery

The examples above all use a hard coded host and port for the location of the gRPC service which is the default if you do not configure a service-discovery-mechanism. Alternatively Akka Discovery can be used. This allows a gRPC client to switch between discovering services via DNS, config, Kubernetes and Consul and others by just changing the configuration.

To see how to config a particular service discovery mechanism see the Akka Discovery docs. Once it is configured a service discovery mechanism name can either be passed into settings or put in the client’s configuration.

Scala
akka.grpc.client {
  "project.WithConfigServiceDiscovery" {
    service-discovery {
      mechanism = "config"
      service-name = "from-config"
      # optional for discovery
      protocol = "tcp"
      port-name = "http"
    }
    port = 43
  }
}
Java
akka.grpc.client {
  "project.WithConfigServiceDiscovery" {
    service-discovery {
      mechanism = "config"
      service-name = "from-config"
      # optional for discovery
      protocol = "tcp"
      port-name = "http"
    }
    port = 43
  }
}

The above example configures the client project.WithConfigServiceDiscovery to use config based service discovery.

Then to create the GrpcClientSettings:

Scala
// sys is an ActorSystem which is required for service discovery
val settings = GrpcClientSettings.fromConfig(clientName = "project.WithConfigServiceDiscovery")
Java
// sys is an ActorSystem which is required for service discovery
GrpcClientSettings.fromConfig(
        "project.WithConfigServiceDiscovery", actorSystem
);

Alternatively if a SimpleServiceDiscovery instance is available elsewhere in your system it can be passed in:

Scala
// An ActorSystem's default service discovery mechanism
GrpcClientSettings
  .usingServiceDiscovery(serviceName = "my-service")
  .withServicePortName("https") // (optional) refine the lookup operation to only https ports
Java
// An ActorSystem's default service discovery mechanism
GrpcClientSettings
        .usingServiceDiscovery("my-service", actorSystem)
        .withServicePortName("https"); // (optional) refine the lookup operation to only https ports

Currently service discovery is only queried on creation of the client. A client can be automatically re-created, and go via service discovery again, if a connection can’t be established, see the lifecycle section.

Debug logging

To enable fine grained debug running the following logging configuration can be used.

Put this in a file grpc-debug-logging.properties:

handlers=java.util.logging.ConsoleHandler
io.grpc.netty.level=FINE
java.util.logging.ConsoleHandler.level=FINE
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

Run with -Djava.util.logging.config.file=/path/to/grpc-debug-logging.properties.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.