gRPC Messages

Learn how to handle gRPC request and response messages in Gatling simulations

Gatling gRPC requests are constructed based on a MethodDescriptor which describes all information required to call the gRPC method, including the marshalling/unmarshalling of the messages sent to and received from the server.

In the most common use case, gRPC services and messages are described in .proto files, messages are serialized using Protocol Buffers (protobuf), and the MethodDescriptor is available in Java code generated from the .proto file with the Protocol Buffer Compiler (protoc). You can find such examples in our samples projects.

However, Gatling gRPC will function with any valid instance of the io.grpc.MethodDescriptor class. The method descriptor includes everything needed to call the gRPC method, including the marshallers used to serialize request messages and response messages.

This allows, for instance:

  • Using different code generators (such as ScalaPB for Scala code, or Pbandk for a pure Kotlin alternative to the official Kotlin support built into protoc).
  • Using other serialization formats than protobuf (e.g. JSON), although other formats are less commonly used with gRPC.
  • Manually instantiating a method descriptor in your code, instead of using a description file and a code generator.
  • Transforming a method descriptor.

Using protoc-generated Java

You can check out our sample projects for configuration examples using Maven or using Gradle.

If we consider the following .proto service definition:

syntax = "proto3";

package greeting;

option java_package = "io.gatling.grpc.demo.greeting";
option java_multiple_files = true;

message Greeting {
  string first_name = 1;
  string last_name = 2;
}

message GreetRequest {
  Greeting greeting = 1;
}

message GreetResponse {
  string result = 1;
}

service GreetingService {
  rpc Greet(GreetRequest) returns (GreetResponse) {};
  rpc GreetWithDeadline(GreetRequest) returns (GreetResponse) {};
}

Then protoc will generate:

  • The Java classes io.gatling.grpc.demo.greeting.Greeting, io.gatling.grpc.demo.greeting.GreetRequest, and io.gatling.grpc.demo.greeting.GreetResponse, to represent the messages. They each come with builders, used with the static method newBuilder().
  • The Java class io.gatling.grpc.demo.greeting.GreetingServiceGrpc, to represent the gRPC service. It notably exposes static getters for the method descriptors: getGreetMethod() and getGreetWithDeadlineMethod().

For example, here is how we can send a GreetRequest message to the Greet method, and validate the GreetResponse message received in response, using the generated code with the Gatling gRPC DSL:

grpc("John Doe's greet request")
  .unary(GreetingServiceGrpc.getGreetMethod())
  .send(
    GreetRequest.newBuilder()
      .setGreeting(
        Greeting.newBuilder()
          .setFirstName("John")
          .setLastName("Doe")
          .build()
      )
      .build()
  )
  .check(
    response(GreetResponse::getResult).is("Hello John Doe")
  );

Using JavaScript and TypeScript

You can check out our sample projects for JavaScript or TypeScript examples.

Type conversions

Gatling will handle conversions between JavaScript object and Protobuf messages automatically.

Scalar types follow this conversion table:

Protobuf JavaScript/TypeScript
double number
float number
int32 number
int64 number
uint32 number
uint64 number
sint32 number
sint64 number
fixed32 number
fixed64 number
sfixed32 number
sfixed64 number
bool boolean
string string
bytes number[]

In addition:

  • enum fields convert from/to JavaScript strings containing valid value names for the enumeration.
  • repeated fields convert from/to JavaScript arrays.
  • message fields convert from/to JavaScript objects with corresponding field names, and each field type is in turn converted according to the usual rules.

For instance, for this message definition:

syntax = "proto3";

enum BookType {
  NOVEL = 0;
  NON_FICTION = 1;
  COMICS = 2;
}

message Book {
  string title = 1;
  BookType type = 2;
  int32 publication_year = 3;
}

message Library {
  repeated Book books = 1;
}

This is a valid JavaScript value:

const library = {
  books: [
    { title: "Grpc: Up and Running", type: "NON_FICTION", publication_year: 2020 },
    { title: "The Lord of the Rings", type: "NOVEL", publication_year: 1954 }
  ]
}

Example

If we consider the following .proto service definition:

syntax = "proto3";

package greeting;

message Greeting {
  string first_name = 1;
  string last_name = 2;
}

message GreetRequest {
  Greeting greeting = 1;
}

message GreetResponse {
  string result = 1;
}

service GreetingService {
  rpc Greet(GreetRequest) returns (GreetResponse) {};
  rpc GreetWithDeadline(GreetRequest) returns (GreetResponse) {};
}

It can be called with the following Gatling code:

grpc("John Doe's greet request")
  .unary("greeting.GreetingService/GreetMethod")
  .send({
    greeting: {
      first_name: "John",
      last_name: "Doe"
    }
  })
  .check(
    response((response) => response.result).is("Hello John Doe")
  );

Using protoc-generated Kotlin

The Kotlin support built into protoc relies on the same Java classes used with pure Java code. However, it adds Kotlin builders for the Java classes, to make them easier to use in your Kotlin code.

You can check out our sample projects for configuration examples using Maven or using Gradle.

If we consider the following .proto service definition:

syntax = "proto3";

package greeting;

option java_package = "io.gatling.grpc.demo.greeting";
option java_multiple_files = true;

message Greeting {
  string first_name = 1;
  string last_name = 2;
}

message GreetRequest {
  Greeting greeting = 1;
}

message GreetResponse {
  string result = 1;
}

service GreetingService {
  rpc Greet(GreetRequest) returns (GreetResponse) {};
  rpc GreetWithDeadline(GreetRequest) returns (GreetResponse) {};
}

Then protoc will generate:

  • The Java classes io.gatling.grpc.demo.greeting.Greeting, io.gatling.grpc.demo.greeting.GreetRequest, and io.gatling.grpc.demo.greeting.GreetResponse, to represent the messages. They each come with builders, used with the static method newBuilder().
  • The Kotlin builder methods io.gatling.grpc.demo.greeting.greeting(), io.gatling.grpc.demo.greeting.greetRequest(), and io.gatling.grpc.demo.greeting.greetResponse().
  • The Java class io.gatling.grpc.demo.greeting.GreetingServiceGrpc, to represent the gRPC service. It notably exposes static getters for the method descriptors: getGreetMethod() and getGreetWithDeadlineMethod().

For example, here is how we can send a GreetRequest message to the Greet method, and validate the GreetResponse message received in response, using the generated code with the Gatling gRPC DSL:

grpc("John Doe's greet request")
  .unary(GreetingServiceGrpc.getGreetMethod())
  .send(
    greetRequest {
      greeting = greeting {
        firstName = "John"
        lastName = "Doe"
      }
    }
  )
  .check(
    response(GreetResponse::getResult).shouldBe("Hello John Doe")
  )

Using scalapb-generated Scala

Generated Java code can also be used in Gatling Scala simulations. However, it’s possible to generate Scala code instead using ScalaPB. You can check out our sample project for a configuration example using sbt.

If we consider the following .proto service definition:

syntax = "proto3";

package greeting;

import "scalapb/scalapb.proto";
option (scalapb.options) = {
  flat_package: true
  package_name: "io.gatling.grpc.demo.greeting"
};

message Greeting {
  string first_name = 1;
  string last_name = 2;
}

message GreetRequest {
  Greeting greeting = 1;
}

message GreetResponse {
  string result = 1;
}

service GreetingService {
  rpc Greet(GreetRequest) returns (GreetResponse) {};
  rpc GreetWithDeadline(GreetRequest) returns (GreetResponse) {};
}

Then ScalaPB will generate:

  • The Scala case classes io.gatling.grpc.demo.greeting.Greeting, io.gatling.grpc.demo.greeting.GreetRequest, and io.gatling.grpc.demo.greeting.GreetResponse, to represent the messages.
  • The Scala object GreetingServiceGrpc, to represent the gRPC service. It notably exposes fields for the method descriptors: METHOD_GREET and METHOD_GREET_WITH_DEADLINE.

For example, here is how we can send a GreetRequest message to the Greet method, and validate the GreetResponse message received in response, using the generated code with the Gatling gRPC DSL:

grpc("John Doe's greet request")
  .unary(GreetingServiceGrpc.METHOD_GREET)
  .send(
    GreetRequest(
      greeting = Some(
        Greeting(
          firstName = "John",
          lastName = "Doe"
        )
      )
    )
  )
  .check(
    response((response: GreetResponse) => response.result)
      .is("Hello John Doe")
  )

Edit this page on GitHub