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 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
.