Configuration

A gRPC client is configured with a GrpcClientSettingsGrpcClientSettings 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
sourceGrpcClientSettings.connectToServiceAt("localhost", 443)
Java
sourceGrpcClientSettings.connectToServiceAt("localhost", 443, actorSystem);

Further settings can be added via the with methods

Scala
sourceGrpcClientSettings.connectToServiceAt("localhost", 443).withDeadline(1.second).withTls(false)
Java
sourceGrpcClientSettings.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 pekko.grpc.client

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

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

reference.conf
sourcepekko.grpc.client."*" {
  # netty or pekko-http (experimental)
  backend = "netty"

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

  service-discovery {
    mechanism = "static"
    # Service name to use if a service-discovery.mechanism other than static or grpc-dns
    service-name = ""
    # See https://pekko.apache.org/docs/pekko-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-mechanism is static or service discovery does not return a port
  port = 0

  # Experimental in grpc-java https://github.com/grpc/grpc-java/issues/1771
  # pick_first or round_robin
  load-balancing-policy = ""

  deadline = infinite
  override-authority = ""
  user-agent = ""
  # Location on the classpath of CA PEM to trust
  trusted = ""
  use-tls = true
  # SSL provider to use:
  # leave empty to auto-detect, or configure 'jdk' or 'openssl'.
  ssl-provider = ""

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

  # The number of times to try connecting before giving up.
  # '-1': means retry indefinitely, '0' is invalid, '1' means fail
  # after the first failed attempt.
  # When load balancing we don't count individual connection
  # failures, so in that case any value larger than '1' is also
  # interpreted as retrying 'indefinitely'.
  connection-attempts = 20

  # Service discovery mechanism to use. The default is to use a static host
  # and port that will be resolved via DNS.
  # Any of the mechanisms described in https://pekko.apache.org/docs/pekko-management/current/discovery/index.html can be used
  # including Kubernetes, Consul, AWS API
}

Using Pekko 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 Pekko 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 (see Discovery methods in Pekko Management).

To see how to config a particular service discovery mechanism see the Pekko 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
sourcepekko.grpc.client {
  "project.WithConfigServiceDiscovery" {
    service-discovery {
      mechanism = "config"
      service-name = "from-config"
      # optional for discovery
      protocol = "tcp"
      port-name = "http"
    }
    port = 43
  }
}
Java
sourcepekko.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
source// an implicit ActorSystem is required to be in scope for service discovery
val settings = GrpcClientSettings.fromConfig(clientName = "project.WithConfigServiceDiscovery")
Java
source// an ActorSystem is required for service discovery
GrpcClientSettings.fromConfig("project.WithConfigServiceDiscovery", actorSystem);

Alternatively if a default instance is available (configured by pekko.discovery.method) in your system it can be use like this:

Scala
source// An ActorSystem's default service discovery mechanism
GrpcClientSettings
  .usingServiceDiscovery(serviceName = "my-service")
  .withServicePortName("https") // (optional) refine the lookup operation to only https ports
Java
source// 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.