ballerina/grpc

Overview

This module provides APIs for connecting and interacting with gRPC endpoints.

gRPC is an inter-process communication technology that allows you to connect, invoke, and operate distributed, heterogeneous applications as easily as making a local function call. The gRPC protocol is layered over HTTP/2 and uses Protocol Buffers for marshaling/unmarshaling messages. This makes gRPC highly efficient on wire and a simple service definition framework.

When you develop a gRPC application, the first thing you do is define a service definition using Protocol Buffers.

Protocol Buffers

This is a mechanism to serialize the structured data introduced by Google and used by the gRPC framework. Defining the service using Protocol Buffers includes defining remote methods in the service and defining message types that are sent across the network. A sample service definition is shown below.

1syntax = "proto3";
2
3service Helloworld {
4 rpc hello(HelloRequest) returns (HelloResponse);
5}
6
7message HelloRequest {
8 string name = 1;
9}
10
11message HelloResponse {
12 string message = 1;
13}

gRPC allows client applications to directly call the server-side methods using the auto-generated stubs. Protocol Buffer compiler is used to generate the stubs for the specified language. In Ballerina, the stubs are generated using the built-in 'Protocol Buffers to Ballerina' tool.

For information on how to generate Ballerina code for Protocol Buffers definition, see gRPC.

gRPC Communication Patterns

The common communication pattern between a client and server is simple request-response style communication. However, with gRPC, you can leverage different inter-process communication patterns other than the simple request-response pattern. This module supports four fundamental communication patterns used in gRPC-based applications: simple RPC(unary RPC), server streaming RPC, client streaming RPC, and bidirectional streaming RPC.

Simple RPC (Unary RPC)

In this pattern, the client invokes a remote function of a server and sends a single request to the server. The server sends a single response in return to the client along with status details.

1service HelloWorld {
2 rpc hello (google.protobuf.StringValue)
3 returns (google.protobuf.StringValue);
4}
Creating the Server

The code snippet given below contains a service that sends a response to each request.

1// The gRPC service is attached to the listener.
2service HelloWorld on new grpc:Listener(9090) {
3 // The function accepts a string message.
4 remote function hello(string name) returns string|error {
5 // Send the response to the client.
6 return "Hi " + name + "! Greetings from gRPC service!");
7 }
8}
Creating the Client

The code snippet given below calls the above service in a synchronized manner using an auto-generated Ballerina stub.

1// Use ‘HelloWorldClient’ to execute the call in the synchronized mode.
2HelloWorldClient helloClient = check new("http://localhost:9090");
3
4// Call the service remote function using a client stub.
5string responseFromServer = check helloClient->hello("Ballerina");

Server streaming RPC

In server-side streaming RPC, the server sends back a sequence of responses after getting the client's request message. After sending all the server responses, the server marks the end of the stream by sending the server status details. You can invoke this in a non-blocking manner.

1service HelloWorld {
2 rpc lotsOfReplies (google.protobuf.StringValue)
3 returns (stream google.protobuf.StringValue);
4}
Creating the Server

The code snippet given below contains a service that sends a sequence of responses to each request.

1// The gRPC service is attached to the listener.
2service HelloWorld on new grpc:Listener(9090) {
3 remote function lotsOfReplies(string name) returns stream<string, grpc:Error?> {
4 string[] greets = ["Hi " + name, "Welcome " + name];
5 // Send multiple responses to the client.
6 return greets.toStream();
7 }
8}
Creating the Client

The code snippet given below calls the above service using the auto-generated Ballerina client stub and reads multiple server responses using a stream. Here, the message stream is ended with a () value.

1 // Client endpoint configurations.
2 HelloWorldClient helloworldClient = check new("http://localhost:9090");
3
4 // Execute the service streaming call by registering a message listener.
5 stream<string, grpc:Error?> result =
6 check helloworldClient->lotsOfReplies("Ballerina");

Client streaming RPC

In client streaming RPC, the client sends multiple messages to the server instead of a single request. The server sends back a single response to the client.

1service HelloWorld {
2 rpc lotsOfGreetings (stream google.protobuf.StringValue)
3 returns (google.protobuf.StringValue);
4}
Creating the Server

The code snippet given below contains a service that receives a sequence of requests from the client and sends a single response in return.

1// The gRPC service is attached to the listener.
2service HelloWorld on new grpc:Listener(9090) {
3
4 // This function is triggered when a new client connection is initialized.
5 remote function lotsOfGreetings(stream<string, grpc:Error?> clientStream)
6 returns string|error {
7 // Iterate through the client stream
8 check clientStream.forEach(function(string name) {
9 // Handle the message sent from the stream here
10 });
11 // A nil value is returned once the client stream is ended
12 // Return server response to the client.
13 return "Ack";
14 }
15}
Creating the Client

The code snippet given below calls the above service using the auto-generated Ballerina client stub and sends multiple request messages from the server.

1 // Client endpoint configurations.
2 HelloWorldClient helloworldClient = check new("http://localhost:9090");
3
4 // Execute the service streaming call by registering a message listener.
5 LotsOfGreetingsStreamingClient streamingClient =
6 check helloworldClient->lotsOfGreetings();
7
8 // Send multiple messages to the server.
9 string[] greets = ["Hi", "Hey", "GM"];
10 foreach string greet in greets {
11 grpc:Error? connErr = streamingClient->sendstring(greet + " " + "Ballerina");
12 }
13
14 // Once all the messages are sent, the client notifies the server
15 // by closing the stream.
16 grpc:Error? result = streamingClient->complete();
17 // Receive the message from the server.
18 string|grpc:Error response = streamingClient->receiveString();
19...

Bidirectional Streaming RPC

In bidirectional streaming RPC, the client is sending a request to the server as a stream of messages. The server also responds with a stream of messages.

1service Chat {
2 rpc chat (stream ChatMessage)
3 returns (stream google.protobuf.StringValue);
4}
Creating the Server

The code snippet given below includes a service that handles bidirectional streaming.

1// The gRPC service is attached to the listener.
2service Chat on new grpc:Listener(9090) {
3
4 //This `resource` is triggered when a new caller connection is initialized.
5 remote function chat(ChatStringCaller caller,
6 stream<ChatMessage, grpc:Error?> clientStream) {
7 //Iterate through the client stream
8 check clientStream.forEach(function(ChatMessage chatMsg) {
9 // Handle the streamed messages sent from the client here
10 grpc:Error? err = caller->sendString(
11 string `${chatMsg.name}: ${chatMsg.message}`);
12 });
13 // A nil value is returned once the client stream is ended
14 // Handle once the client has completed streaming
15 caller->complete();
16 }
17}
Creating the Client

The code snippet given below calls the above service using the auto-generated Ballerina client stub and sends multiple request messages to the server and receives multiple responses from the server.

1 // Client endpoint configurations.
2 ChatClient chatClient = check new("http://localhost:9090");
3
4 // Execute the service streaming call by registering a message listener.
5 ChatStreamingClient streamingClient = check chatClient->chat();
6
7 // Send multiple messages to the server.
8 string[] greets = ["Hi", "Hey", "GM"];
9 foreach string greet in greets {
10 ChatMessage mes = {name: "Ballerina", message: greet};
11 grpc:Error? connErr = streamingClient->sendChatMessage(mes);
12 }
13
14 // Once all the messages are sent, the server notifies the caller
15 // with a `complete` message.
16 grpc:Error? result = streamingClient->complete();
17 ...
18
19 // Receive the server stream response iteratively.
20 string? result = check streamingClient->receiveString();
21 while !(result is ()) {
22 io:println(result);
23 result = streamingClient->receiveString();
24 }

Advanced Use cases

Using the TLS protocol

The Ballerina gRPC module allows the use of TLS in communication. This setting expects a secure socket to be set in the connection configuration as shown below.

Configuring TLS in Server Side
1// Server endpoint configuration with the SSL configurations.
2listener grpc:Listener ep = new (9090, {
3 host: "localhost",
4 secureSocket: {
5 key: {
6 certFile: "../resource/path/to/public.crt",
7 keyFile: "../resource/path/to/private.key"
8 }
9 }
10});
11
12service HelloWorld on ep {
13
14}
Configuring TLS in Client Side
1 // Client endpoint configuration with SSL configurations.
2 HelloWorldClient helloWorldClient = check new ("https://localhost:9090", {
3 secureSocket: {
4 cert: "../resource/path/to/public.crt"
5 }
6 });

Using Headers

The Ballerina gRPC module allows to send/receive headers with the request and response using the context record type. The context record type consists of two fields called headers and content. E.g: For the string message, a type generated context record type will be as follows.

1public type ContextString record {|
2 string content;
3 map<string|string[]> headers;
4|};
Using Headers in the Client Side
1 // Set the custom headers to the request.
2 ContextString requestMessage =
3 {content: "WSO2", headers: {client_header_key: "0987654321"}};
4 // Execute the remote call.
5 ContextString result = check ep->helloContext(requestMessage);
6 // Read Response content.
7 string content = result.content;
8 // Read Response header value.
9 string headerValue = check grpc:getHeader(result.headers,
10 "server_header_key");
Using Headers in the Server Side
1service "HelloWorld" on new grpc:Listener(9090) {
2 remote function hello(ContextString request) returns ContextString|error {
3 // Read the request content.
4 string message = "Hello " + request.content;
5
6 // Read custom headers in request message.
7 string reqHeader = check grpc:getHeader(request.headers,
8 "client_header_key");
9
10 // Send response with custom headers.
11 return {content: message,
12 headers: {server_header_key: "Response Header value"}};
13 }
14}

Using Deadlines

Deadlines allow gRPC clients to specify how long they are willing to wait for an RPC to complete before the RPC is terminated with the DEADLINE_EXCEEDED error. In Ballerina, a deadline value is set directly to the headers and it is sent via the request headers.

Setting a Deadline in the Request Headers
1 time:Utc current = time:utcNow();
2 time:Utc deadline = time:utcAddSeconds(current, 300);
3 map<string|string[]> headers = grpc:setDeadline(deadline);
Checking the Deadlines
1 boolean cancel = check grpc:isCancelled(request.headers);
2 if (cancel) {
3 return error DeadlineExceededError("Deadline exceeded");
4 }

Modules

[5]

grpc

This module provides APIs for connecting and interacting with gRPC endpoints.

grpc.types.duration
grpc.types.struct
grpc.types.timestamp
grpc.types.wrappers

Listeners

[1]

Listener

The server listener of which one or more services can be registered so that the Ballerina program can offer a service through this listener.

Clients

[6]

Caller

The base client used in the generated client code to provide remote functions for interacting with the caller.

Client

The base client used in the generated client code to provide the capability for initiating the contact and executing remote calls with a remote gRPC service.

ClientOAuth2Handler

Defines the OAuth2 handler for client authentication.

ListenerLdapUserStoreBasicAuthHandler

Defines the LDAP store Basic Auth handler for listener authentication.

ListenerOAuth2Handler

Defines the OAuth2 handler for listener authentication.

StreamingClient

The base client used in the generated client code to provide the gRPC streaming client actions for interacting with the gRPC server.

Functions

[7]

authenticateResource

Uses for declarative auth design, where the authentication/authorization decision is taken by reading the auth annotations provided in service/resource and the Authorization header of request.

getDeadline

Returns the deadline value as time:Utc.

getHeader

Returns the header value with the specified header name.

getHeaders

Gets all the transport headers with the specified header name.

isCancelled

Checks whether the deadline is already exceeded or not.

setCompression

Enables the compression support by adding the grpc-encoding header to the given headers.

setDeadline

Enables the deadline by adding the deadline header to the given headers.

Classes

[5]

ClientBasicAuthHandler

Defines the Basic Auth handler for client authentication.

ClientBearerTokenAuthHandler

Defines the Bearer token auth handler for client authentication.

ClientSelfSignedJwtAuthHandler

Defines the self signed JWT handler for client authentication.

ListenerFileUserStoreBasicAuthHandler

Defines the file store Basic Auth handler for listener authentication.

ListenerJwtAuthHandler

Defines the JWT auth handler for listener authentication.

Object Types

[2]

AbstractClientEndpoint

Represents the abstract gRPC client endpoint.

Service

The gRPC service type.

Records

[28]

AccessLogConfiguration

Represents gRPC access log configuration.

BearerTokenConfig

Represents token for Bearer token authentication.

CertKey

Represents combination of certificate, private key and private key password if encrypted.

ClientConfiguration

Configurations for managing the gRPC client endpoint.

ClientSecureSocket

Configurations for facilitating secure communication with a remote gRPC endpoint.

CredentialsConfig

Represents credentials for Basic Auth authentication.

FileUserStoreConfig

Represents file user store configurations for Basic Auth authentication.

FileUserStoreConfigWithScopes

Represents the auth annotation for file user store configurations with scopes.

GrpcServiceConfig

Contains the configurations for a gRPC service.

JwtIssuerConfig

Represents JWT issuer configurations for JWT authentication.

JwtValidatorConfig

Represents JWT validator configurations for JWT authentication.

JwtValidatorConfigWithScopes

Represents the auth annotation for JWT validator configurations with scopes.

LdapUserStoreConfig

Represents LDAP user store configurations for Basic Auth authentication.

LdapUserStoreConfigWithScopes

Represents the auth annotation for LDAP user store configurations with scopes.

ListenerConfiguration

Configurations for managing the gRPC server endpoint.

ListenerSecureSocket

Configurations for facilitating secure communication for the gRPC server endpoint.

Local

Presents a read-only view of the local address.

OAuth2ClientCredentialsGrantConfig

Represents OAuth2 client credentials grant configurations for OAuth2 authentication.

OAuth2IntrospectionConfig

Represents OAuth2 introspection server configurations for OAuth2 authentication.

OAuth2IntrospectionConfigWithScopes

Represents the auth annotation for OAuth2 introspection server configurations with scopes.

OAuth2JwtBearerGrantConfig

Represents OAuth2 JWT bearer grant configurations for OAuth2 authentication.

OAuth2PasswordGrantConfig

Represents OAuth2 password grant configurations for OAuth2 authentication.

OAuth2RefreshTokenGrantConfig

Represents OAuth2 refresh token grant configurations for OAuth2 authentication.

PoolConfiguration

Configurations for managing the gRPC client connection pool.

Remote

Presents a read-only view of the remote address.

RetryConfiguration

Configurations for facilitating the retry capability of the gRPC client.

ServiceDescriptorData

Service descriptor data generated at the compile time.

TraceLogAdvancedConfiguration

Represents gRPC trace log configuration.

Constants

[9]

AUTH_HEADER

Represents the Authorization header name.

AUTH_SCHEME_BASIC

The prefix used to denote the Basic authentication scheme.

AUTH_SCHEME_BEARER

The prefix used to denote the Bearer authentication scheme.

COMPRESSION_ALWAYS

Always set accept-encoding/content-encoding in outbound request/response.

COMPRESSION_AUTO

When service behaves as a HTTP gateway inbound request/response accept-encoding option is set as the outbound request/response accept-encoding/content-encoding option.

COMPRESSION_NEVER

Never set accept-encoding/content-encoding header in outbound request/response.

DEALINE_HEADER

Represents the deadline header name.

PERMISSION_DENIED_ERROR_MSG

The permission denied error message.

UNAUTHENTICATED_ERROR_MSG

The permission denied error message.

Enums

[4]

CertValidationType

Represents certification validation type options.

CompressionType

Compression types that are supported.

Protocol

Represents protocol options.

VerifyClient

Represents client verify options.

Annotations

[2]

ServiceConfig

The annotation which is used to configure a gRPC service.

ServiceDescriptor

Service descriptor annotation.

Types

[5]

ClientAuthConfig

Defines the authentication configurations for the HTTP client.

Compression

Represents compression options.

ErrorType

Represents gRPC related error types.

ListenerAuthConfig

Defines the authentication configurations for the gRPC listener.

OAuth2GrantConfig

Represents OAuth2 grant configurations for OAuth2 authentication.

Errors

[22]

AbortedError

Represents error occur when operation is aborted.

AllRetryAttemptsFailed

Represents error scenario where the maximum retry attempts are done and still received an error.

AlreadyExistsError

Represents error occur when attempt to create an entity which already exists.

CancelledError

Represents the operation canceled(typically by the caller) error.

ClientAuthError

Represents an error when client authentication error occured.

DataLossError

Represents unrecoverable data loss or corruption erros.

DataMismatchError

Represents an error when expected data type is not available.

DeadlineExceededError

Represents operation expired before completion error.

Error

Represents gRPC related errors.

FailedPreconditionError

Represents error occur when operation is rejected because the system is not in a state required for the operation's execution.

InternalError

Represents internal error.

InvalidArgumentError

Represents client specified an invalid argument error.

NotFoundError

Represents requested entity (e.g., file or directory) not found error.

OutOfRangeError

Represents error occur when specified value is out of range.

PermissionDeniedError

Represents error occur when the caller does not have permission to execute the specified operation.

ResiliencyError

Represents all the resiliency-related errors.

ResourceExhaustedError

Represents error occur when the resource is exhausted.

StreamClosedError

Represents an error when calling next when the stream has closed.

UnauthenticatedError

Represents error occur when the request does not have valid authentication credentials for the operation.

UnavailableError

Represents error occur when the service is currently unavailable.

UnimplementedError

Represents error occur when operation is not implemented or not supported/enabled in this service.

UnKnownError

Represents unknown error(e.g., Status value received is unknown).