GRPC Server

This section describes core concepts that Spring gRPC uses on the server side. We recommend reading it closely to understand the ideas behind how Spring gRPC is implemented. You only need to provide one or more beans of type BindableService to create a gRPC server, provided the classpath contains an implementation of a Server. The BindableService is a gRPC service that can be bound to a server. The Server is the gRPC server that listens for incoming requests and routes them to the appropriate service implementation.

Create a gRPC Service

To create a gRPC server, you need to provide one or more beans of type BindableService. There are some BindableServices available off the shelf that you could include in your application (an example is the reflection service from the grpc-services artifact which allows clients to browse the metadata of your services and download the Portobuf files). Very commonly, you will create your own BindableService by extending the generated service implementation from your Protobuf file. The easiest way to activate it is to simply add a Spring @Service annotation to the implementation class and have it picked up by the @ComponentScan in your Spring Boot application.

Netty Server

If you use the spring-grpc-spring-boot-starter dependency on its own, the Server is a Netty-based implementation. You can configure common features of the server by using the grpc.server prefix in application.properties or application.yml. For instance, to set the port to listen on, use spring.grpc.server.port (defaults to 9090). For more specialized configuration, you can provide a ServerBuilderCustomizer bean to customize the ServerBuilder before it is used to create the server.

Shaded Netty

You can switch to a shaded Netty provided by the gRPC team by adding the grpc-netty-shaded dependency and excluding the grpc-netty dependency.

<dependency>
	<groupId>org.springframework.grpc</groupId>
	<artifactId>spring-grpc-spring-boot-starter</artifactId>
	<exclusions>
		<exclusion>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-netty</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>io.grpc</groupId>
	<artifactId>grpc-netty-shaded</artifactId>
</dependency>

For Gradle users

dependencies {
	implementation "org.springframework.grpc:spring-grpc-spring-boot-starter"
	implementation 'io.grpc:grpc-netty-shaded'
	modules {
		module("io.grpc:grpc-netty") {
			replacedBy("io.grpc:grpc-netty-shaded", "Use Netty shaded instead of regular Netty")
		}
	}
}

Servlet Server

Any servlet container can be used to run a gRPC server. Spring gRPC includes autoconfiguration that configures the server to use the servlet container if it detects that it is in a web application, so all you have to do is include spring-boot-starter-web in your application.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.grpc</groupId>
	<artifactId>spring-grpc-spring-boot-starter</artifactId>
</dependency>

For Gradle users

dependencies {
	implementation "org.springframework.boot:spring-boot-starter-web"
	implementation "org.springframework.grpc:spring-grpc-spring-boot-starter"
}

The spring.grpc.server. properties will be ignored in facour of the regular server. properties in this case (with the exception of spring.grpc.server.max-inbound-message-size). The servlet that is created is mapped to process HTTP POST requests to the paths defined by the registered services, as /<service-name>/*. Clients can connect to the server using that path, which is what any gRPC client library will do.

The gRPC server has fewer configuration options when running in a servlet container, as the servlet container is responsible for the network layer. You can still add ServerBuilderCustomizer beans to customize the server as it is built, but some features common in the "native" builders are not available and may throw exceptions at runtime.

Server Interceptors

Global

To add a server interceptor to be applied to all services you can simply register a server interceptor bean and then annotate it with @GlobalServerInterceptor. The interceptors are ordered according to their bean natural ordering (i.e. @Order).

@Bean
@Order(100)
@GlobalServerInterceptor
ServerInterceptor myGlobalLoggingInterceptor() {
    return new MyLoggingInterceptor();
}

Per-Service

To add a server interceptor to be applied to a single service you can simply register a server interceptor bean and then annotate your BindableService bean with @GrpcService, specifying the interceptor using either the interceptors or interceptorNames attribute.

The interceptors are ordered according to their position in the attribute list. When using both interceptors and interceptorNames, the former entries precede the latter.

In the following example, the myServerInterceptor will be applied to the myService service.

@Bean
MyServerInterceptor myServerInterceptor() {
    return new MyServerInterceptor();
}

@GrpcService(interceptors = MyServerInterceptor.class)
BindableService myService() {
	...
}

When a service is configured with both global and per-service interceptors, the global interceptors are first applied in their sorted order followed by the per-service interceptors in their sorted order.

However, by setting the blendWithGlobalInterceptors attribute on the @GrpcService annotation to "true" you can change this behavior so that the interceptors are all combined and then sorted according to their bean natural ordering (i.e. @Order).

You can use this option if you want to add a per-service interceptor between global interceptors.

Health

Spring gRPC autoconfigures the standard gRPC Health service for performing health check calls against gRPC servers. The health service is registered with the gRPC server and a HealthStatusManager bean is provided that can be used to update the health status of your services.

Actuator Health

When Spring Boot Actuator is added to your project and the Health endpoint is available, the framework will automatically periodically update the health status of a configured list of Spring Boot health indicators, including any (custom indicators). By default, the aggregate status of the individual indicators is also used to update the overall server status ("").

The following example uses application.yml to include the health status of the db and redis autoconfigured health indicators.

spring:
  grpc:
    server:
      health:
        actuator:
          health-indicator-paths:
            - db
            - redis
The items in the health-indicator-paths are the identifiers of the indicator which is typically the name of the indicator bean without the HealthIndicator suffix.

You can use the "spring.grpc.server.health.*" application properties to further configure the health feature.

Client-side

Spring gRPC can also autoconfigure the client-side health check feature to your gRPC clients. To enable health checks on a named channel, simply set the spring.grpc.client.channels.<channel-name>.health.enabled application property to true. To enable health checks for all channels, set the spring.grpc.client.default-channel.enabled application property to true.

By default, the health check will consult the overall status service (i.e. ""). To use a specific service, use the health.service-name application property on the desired channel.

The default-load-balancing-policy must be set to round_robin to participate in the health checking. This is the default used by Spring gRPC but if you change the setting you will not get health checks

The following example enables health checks for all unknown channels (using the overall server status) and for the channel named one (using the service service-one health check).

spring:
  grpc:
    client:
      default-channel:
      health:
        enabled: true
      channels:
        one:
          health:
            enabled: true
            service-name: service-one

Observability

Spring gRPC provides an autoconfigured interceptor that can be used to provide observability to your gRPC services. All you need to do is add Spring Boot actuators to your project, and optionally a bridge to your observability platform of choice (just like any other Spring Boot application). The grpc-tomcat sample in the Spring gRPC repository shows how to do it, and you should see trace logging and metrics when you connect to the server.

Exception Handling

Spring gRPC provides an autoconfigured exception handler that can be used to provide a consistent way to handle exceptions in your gRPC services. All you need to do is add @Beans of type GrpcExceptionHandler to your application context, and they will be used to handle exceptions thrown by your services. A GrpcExceptionHandler can be used to handle exceptions of a specific type, returning null for those it does not support, or to handle all exceptions.

Testing

If you include spring-grpc-test in your project, your gRPC server in a @SpringBootTest will be started in-process (i.e. not listening on a network port). All clients that connect to any server via the autoconfigured GrpcChannelFactory will be able to connect to it. You can switch the in-process server off by setting spring.grpc.in-process.enabled to false.