gRPC Protocol

Learn about gRPC protocol settings, TLS, and load balancing

Bootstrapping

The Gatling gRPC DSL is not imported by default.

You have to manually add the following imports:

     
import io.gatling.javaapi.grpc.*;

import static io.gatling.javaapi.grpc.GrpcDsl.*;
import io.gatling.javaapi.grpc.*

import io.gatling.javaapi.grpc.GrpcDsl.*
import io.gatling.grpc.Predef._

Protocol

Use the grpc object in order to create a gRPC protocol.

As with every protocol in Gatling, the gRPC protocol can be configured for a scenario. This is done thanks to the following statements:

     
GrpcProtocolBuilder grpcProtocol = grpc
  .forAddress("host", 50051);

ScenarioBuilder scn = scenario("Scenario"); // etc.

setUp(
  scn.injectOpen(atOnceUsers(1))
    .protocols(grpcProtocol)
);
val grpcProtocol = grpc
  .forAddress("host", 50051)

val scn = scenario("Scenario") // etc.

setUp(
  scn.injectOpen(atOnceUsers(1))
    .protocols(grpcProtocol)
)
val grpcProtocol = grpc
  .forAddress("host", 50051)

val scn = scenario("Scenario") // etc.

setUp(
  scn.inject(atOnceUsers(1))
    .protocols(grpcProtocol)
)

Target required

The first and only mandatory step is to configure the remote service address and port.

forAddress

It can be done with either the address as host and port.

     
grpc.forAddress("host", 50051);
grpc.forAddress("host", 50051)
grpc.forAddress("host", 50051)
forTarget

Or by using a URL or FDQN with both host and port directly:

     
grpc.forTarget("dns:///host:50051");
grpc.forTarget("dns:///host:50051")
grpc.forTarget("dns:///host:50051")

Channel options

By default, every user will use their own gRPC channel to connect to the remote service.

shareChannel

It is possible to share the same channel for all users by using:

     
grpc.shareChannel();
grpc.shareChannel()
grpc.shareChannel

Be aware that even though the same channel is used for all users, the number of underlying connections used doesn’t scale automatically.

useChannelPool

Use a pool of gRPC channels, instead of a single channel. This allows opening more underlying HTTP/2 connections. Useful when using shareChannel and when performance is limited by the maximum number of concurrent gRPC streams open on each connection.

     
grpc.useChannelPool(4);
grpc.useChannelPool(4)
grpc.useChannelPool(4)

Encryption

It is possible to use either unencrypted or encrypted connections to a remote service.

usePlaintext

If you don’t want the connection to be encrypted:

     
grpc.usePlaintext();
grpc.usePlaintext()
grpc.usePlaintext
useInsecureTrustManager default

If you want to trust all certificates without any verification, you can use an insecure trust manager. A useful option for self-signed certificates:

     
grpc.useInsecureTrustManager();
grpc.useInsecureTrustManager()
grpc.useInsecureTrustManager

This is the default option as it is more performant and validating certificates typically isn’t important for load tests.

useStandardTrustManager

Finally, you can use the standard trust manager that comes with the JVM:

     
grpc.useStandardTrustManager();
grpc.useStandardTrustManager()
grpc.useStandardTrustManager
useCustomCertificateTrustManager

Or use your own certificate:

     
grpc.useCustomCertificateTrustManager("certificatePath");
grpc.useCustomCertificateTrustManager("certificatePath")
grpc.useCustomCertificateTrustManager("certificatePath")
shareSslContext

TLS handshake will be performed only once and the TLS sessions will be shared between all the users. Use this option if you want to avoid the overhead of TLS while still having per-user channels.

     
grpc.shareSslContext();
grpc.shareSslContext()
grpc.shareSslContext

Headers

Define gRPC headers to be set on all requests.

     
grpc.header(
  Metadata.Key.of("key", Metadata.ASCII_STRING_MARSHALLER),
  "value"
);
grpc.header(
  Metadata.Key.of("key", Metadata.ASCII_STRING_MARSHALLER),
  "value"
)
grpc.header(
  Metadata.Key.of("key", Metadata.ASCII_STRING_MARSHALLER),
  "value"
)
asciiHeader

Shortcut for a single header with the default ASCII marshaller, i.e. io.grpc.Metadata#ASCII_STRING_MARSHALLER:

     
grpc.asciiHeader("key", "value");
grpc.asciiHeader("key", "value")
grpc.asciiHeader("key", "value")
asciiHeaders

Shortcut for multiple headers with the default ASCII marshaller as a map of multiple key and value pairs, i.e. io.grpc.Metadata#ASCII_STRING_MARSHALLER:

     
grpc.asciiHeaders(Map.of("key", "value"));
grpc.asciiHeaders(
  mapOf("key" to "value")
)
grpc.asciiHeaders(
  Map("key" -> "value")
)
binaryHeader

Shortcut for a single header with the default binary marshaller, i.e. io.grpc.Metadata#BINARY_BYTE_MARSHALLER:

     
grpc.binaryHeader("key", "value".getBytes(UTF_8));
grpc.binaryHeader("key", "value".toByteArray(UTF_8))
grpc.binaryHeader("key", "value".getBytes(UTF_8))
binaryHeaders

Shortcut for multiple headers with the default binary marshaller as a map of multiple key and pairs, i.e. io.grpc.Metadata#BINARY_BYTE_MARSHALLER:

     
grpc.binaryHeaders(Map.of("key", "value".getBytes(UTF_8)));
grpc.binaryHeaders(
  mapOf("key" to "value".toByteArray(UTF_8))
)
grpc.binaryHeaders(
  Map("key" -> "value".getBytes(UTF_8))
)

Loading balancing

When the name resolver returns a list of several service IP addresses, you probably want to configure a load balancing policy. The policy is responsible for maintaining connections to the services and picking a connection to use each time a request is sent.

useCustomLoadBalancingPolicy

Use a custom load balancing by name:

     
grpc.useCustomLoadBalancingPolicy("pick_first");
grpc.useCustomLoadBalancingPolicy("pick_first")
grpc.useCustomLoadBalancingPolicy("pick_first")

Or with JSON configuration:

     
grpc.useCustomLoadBalancingPolicy("pick_first", "{}");
grpc.useCustomLoadBalancingPolicy("pick_first", "{}")
grpc.useCustomLoadBalancingPolicy("pick_first", "{}")

Check the gRPC documentation for more details.

usePickFirstLoadBalancingPolicy

This policy actually does no load balancing but just tries each address it gets from the name resolver and uses the first one it can connect to:

     
grpc.usePickFirstLoadBalancingPolicy();
grpc.usePickFirstLoadBalancingPolicy()
grpc.usePickFirstLoadBalancingPolicy
usePickRandomLoadBalancingPolicy

Randomly pick an address from the name resolver:

     
grpc.usePickRandomLoadBalancingPolicy();
grpc.usePickRandomLoadBalancingPolicy()
grpc.usePickRandomLoadBalancingPolicy

This load balancing policy is bundled with Gatling gRPC but not a standard of gRPC.

useRoundRobinLoadBalancingPolicy

Round-robin load balancing over the addresses returned by the name resolver:

     
grpc.useRoundRobinLoadBalancingPolicy();
grpc.useRoundRobinLoadBalancingPolicy()
grpc.useRoundRobinLoadBalancingPolicy

Edit this page on GitHub