From 6be591d54482189585da7bd95b9419a3fd839c22 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 25 Oct 2024 11:01:54 +0100 Subject: [PATCH] Add some basic docs --- .../src/main/antora/modules/ROOT/nav.adoc | 3 +- .../antora/modules/ROOT/pages/client.adoc | 101 ++++++++++++++++++ .../antora/modules/ROOT/pages/concepts.adoc | 4 - .../modules/ROOT/pages/getting-started.adoc | 2 - .../main/antora/modules/ROOT/pages/index.adoc | 6 +- .../antora/modules/ROOT/pages/server.adoc | 87 +++++++++++++++ 6 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc delete mode 100644 spring-grpc-docs/src/main/antora/modules/ROOT/pages/concepts.adoc create mode 100644 spring-grpc-docs/src/main/antora/modules/ROOT/pages/server.adoc diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc index 67b8ced..d35dc9a 100644 --- a/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc @@ -1,5 +1,6 @@ * xref:index.adoc[Overview] -* xref:concepts.adoc[GRPC Concepts] * xref:getting-started.adoc[Getting Started] +* xref:server.adoc[GRPC Server] +* xref:client.adoc[GRPC Clients] * xref:contribution-guidelines.adoc[Contribution Guidelines] * xref:appendix.adoc[] diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc new file mode 100644 index 0000000..db22af5 --- /dev/null +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc @@ -0,0 +1,101 @@ +[[client]] += GRPC Client + +This section describes core concepts that Spring gRPC uses on the client side. + +== Create a `Channel` + +You can inject a `GrpcChannelFactory` into your application configuration and use it to create a gRPC channel. +The most common usage of a channel is to create a client that binds to a service. +The Protobuf-generated sources in your project will contain the stub classes, and they just need to be bound to a channel. +The Protobuf files will be provided by the service you are connecting to. +For example, consider the `SimpleGrpc` service generated by the Protobuf tooling in your build. +To bind to this service on a local server: + +[source,java] +---- +@Bean +SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) { + return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090").build()); +} +---- + +The `GrpcChannelFactory` creates a `ChannelBuilder` that you can customize before building the channel if necessary. + +=== Shaded Netty Client + +The default client implementation uses the Netty client. +You can switch to a shaded Netty implementation provided by the gRPC team by adding the `grpc-netty-shaded` dependency and excluding the `grpc-netty` dependency. + +[source,xml] +---- + + org.springframework.grpc + spring-grpc-spring-boot-starter + + + io.grpc + grpc-netty + + + + + io.grpc + grpc-netty-shaded + +---- + +For Gradle users + +[source,gradle] +---- +dependencies { + implementation "org.springframework.grpc:spring-grpc-spring-boot-starter" + modules { + module("io.grpc:grpc-netty") { + replacedBy("io.grpc:grpc-netty-shaded", "Use Netty shaded instead of regular Netty") + } + } +} +---- + +== Channel Configuration + +The default `GrpcChannelFactory` implementation can also create a "named" channel, which you can then use to extract the configuration to connect to the server. +For example: + +[source,java] +---- +@Bean +SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) { + return SimpleGrpc.newBlockingStub(channels.createChannel("local").build()); +} +---- + +then in `application.properties`: + +[source,properties] +---- +spring.grpc.client.channels.local.address=0.0.0.0:9090 +---- + +There is a default named channel (named "default") that you can configure in the same way, and then it will be used by default if there is no channel with the name specified in the channel creation. + +Beans of type `GrpcChannelConfigurer` can be used to customize the `ChannelBuilder` before the channel is built. +This can be useful for setting up security, for example. + +== The Local Server Port + +If you are running a gRPC server locally as part of your application, you will often want to connect to it in an integration test. +It can be convenient in that case to use an ephemeral port for the server (`spring.grpc.server.port=0`) and then use the port that is allocated to connect to it. +You can discover the port that the server is running on by injecting the `@LocalGrpcPort` bean into your test. +The `@Bean` has to be marked as `@Lazy` to ensure that the port is available when the bean is created (it is only known when the server starts which is part of the startup process). + +[source,java] +---- +@Bean +@Lazy +SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort int port) { + return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:" + port).build()); +} +---- \ No newline at end of file diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/concepts.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/concepts.adoc deleted file mode 100644 index 9ec6ee3..0000000 --- a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/concepts.adoc +++ /dev/null @@ -1,4 +0,0 @@ -[[concepts]] -= GRPC Concepts - -This section describes core concepts that Spring gRPC uses. We recommend reading it closely to understand the ideas behind how Spring gRPC is implemented. diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/getting-started.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/getting-started.adoc index 265748e..499cfd4 100644 --- a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/getting-started.adoc +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/getting-started.adoc @@ -84,8 +84,6 @@ As shown in the snippet below this can then be followed by version-less declarat ---- dependencies { implementation platform("org.springframework.ai:spring-grpc-dependencies:1.0.0-SNAPSHOT") - // Replace the following with the starter dependencies of specific modules you wish to use - implementation 'org.springframework.ai:spring-grpc-openai' } ---- diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/index.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/index.adoc index 2d60bb0..8640cda 100644 --- a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/index.adoc +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/index.adoc @@ -3,7 +3,9 @@ The `Spring gRPC` project aims to streamline the development of gRPC applications. -The xref:concepts.adoc[concepts section] provides a high-level overview of gRPC concepts and their representation in Spring gRPC. - The xref:getting-started.adoc[Getting Started] section shows you how to create your first gRPC application. Subsequent sections delve into each component and common use cases with a code-focused approach. + +The xref:server.adoc[server section] provides a high-level overview of gRPC servers and their representation in Spring gRPC. + +The xref:server.adoc[client section] does the same for gRPC clients. A gRPC application can be a client and a server at the same time. diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/server.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/server.adoc new file mode 100644 index 0000000..2b058fe --- /dev/null +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/server.adoc @@ -0,0 +1,87 @@ +[[server]] += 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 `BindableService` + +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 do 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. + +[source,xml] +---- + + org.springframework.grpc + spring-grpc-spring-boot-starter + + + io.grpc + grpc-netty + + + + + io.grpc + grpc-netty-shaded + +---- + +For Gradle users + +[source,gradle] +---- +dependencies { + implementation "org.springframework.grpc:spring-grpc-spring-boot-starter" + 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. + +[source,xml] +---- + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.grpc + spring-grpc-spring-boot-starter + +---- + +For Gradle users + +[source,gradle] +---- +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. +The servlet that is created is mapped to process HTTP POST requests to the paths defined by the registered services, as `//*`. +Clients can connect to the server using that path, which is what any gRPC client library will do. \ No newline at end of file