入门指南
Spring gRPC 1.1.x 支持 Spring Boot 4.1.x
本节提供了开始使用Spring gRPC的入门指导。在samples目录中有一个简单的示例项目(例如grpc-server)。你可以使用mvn spring-boot:run或gradle bootRun来运行它。在该示例项目中,你会看到以下代码。
想开始吗?让我们快速搭建一个可运行的服务吧。
访问Spring Initializr,然后选择gRPC依赖项。
生成项目并解压下载到的文件。
在您的集成开发环境(IDE)中以通常的方式打开它。例如,如果您使用的是IntelliJ IDEA:idea pom.xml;或者对于VSCode则是code .。
定义一个.proto服务定义文件src/main/proto/hello.proto,其内容如下:
请确保将java_package更改为你在Spring Initializr中选择的那个值。
syntax = "proto3";
option java_multiple_files = true;
option java_package = "<your-package-name-goes-here>.proto";
option java_outer_classname = "HelloWorldProto";
// The greeting service definition.
service Simple {
// Sends a greeting
rpc SayHello(HelloRequest) returns (HelloReply) {}
rpc StreamHello(HelloRequest) returns (stream HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
我们将根据这个定义来为Java服务定义存根(stubs):
./mvnw clean package
或者
./gradlew build
将生成两个新的文件夹,其中包含这些存根(stubs)的源代码。
对于Maven:target/generated-sources/protobuf/grpc-java 和 target/generated-sources/protobuf/java
对于Gradle:build/generated/source/proto/main grpc 和 build/generated/source/proto/main/java
你可能需要指示你的集成开发环境(IDE)将它们标记为源代码根目录。在IntelliJ IDEA中,右键点击该文件夹,选择“Mark Directory As” → “Generated Source Root”。Eclipse或VSCode会自动为你完成这个操作。
现在你可以基于生成的存根实现一个服务了:
@Service
class GrpcServerService extends SimpleGrpc.SimpleImplBase {
private static Log log = LogFactory.getLog(GrpcServerService.class);
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
log.info("Hello " + req.getName());
if (req.getName().startsWith("error")) {
throw new IllegalArgumentException("Bad name: " + req.getName());
}
if (req.getName().startsWith("internal")) {
throw new RuntimeException();
}
HelloReply reply = HelloReply.newBuilder().setMessage("Hello ==> " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
@Override
public void streamHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
log.info("Hello " + req.getName());
int count = 0;
while (count < 10) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello(" + count + ") ==> " + req.getName()).build();
responseObserver.onNext(reply);
count++;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
responseObserver.onError(e);
return;
}
}
responseObserver.onCompleted();
}
}
以通常的方式运行程序:
./mvnw spring-boot:run
或
./gradlew bootRun
你可以使用像grpcurl这样的gRPC客户端来尝试它:
grpcurl -d '{"name":"Hi"}' -plaintext localhost:9090 Simple.SayHello
你应该会收到这样的回复:
{
"message": "Hello ==\u003e Hi"
}
下一节将提供更多关于正在发生的事情的细节。
详细信息
您应根据自己的需求遵循以下每个部分中的步骤。
添加里程碑和快照仓库
如果您更喜欢手动添加依赖项代码片段,请按照以下各节中的说明进行操作。
要使用Milestone和Snapshot版本,你需要在构建文件中添加对Spring Milestone和/或Snapshot仓库的引用。
对于Maven,根据需要添加以下仓库定义(如果您使用的是快照或里程碑版本):
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
对于Gradle,根据需要添加以下仓库定义:
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
依赖管理
spring-grpc-dependencies 该依赖项声明了特定版本的 Spring gRPC 所使用的推荐依赖版本,但不包括那些已由 Spring Boot 依赖管理机制管理的依赖。
spring-grpc-build-dependencies 工件声明了给定版本的 Spring gRPC 所使用的所有依赖的推荐版本,包括那些已经由 Spring Boot 依赖管理机制管理的依赖。
如果你在Spring Boot应用程序中运行Spring gRPC,请使用spring-grpc-dependencies;否则,请使用spring-grpc-build-dependencies。
使用这些依赖模块之一可以避免您自己指定和维护依赖版本的需求。相反,您所使用的依赖模块的版本将决定所使用的依赖版本。这还确保了默认情况下您使用的是经过支持和测试的依赖版本,除非您选择覆盖它们。
以下示例假设您正在Spring Boot应用程序中运行,因此使用了spring-grpc-dependencies。
如果你是Maven用户,你可以通过在pom.xml文件中添加以下内容来使用这些依赖项:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.grpc</groupId>
<artifactId>spring-grpc-dependencies</artifactId>
<version>1.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Gradle用户还可以利用Gradle(5.0及以上版本)对Maven BOM声明依赖约束的原生支持来使用这些依赖。实现方法是在Gradle构建脚本的dependencies部分添加一个“platform”依赖处理方法。如下所示,之后就可以对想要使用的一个或多个spring-grpc模块(例如spring-grpc-openai)进行无版本号的声明了。
dependencies {
implementation platform("org.springframework.grpc:spring-grpc-dependencies:1.0.2")
}
你需要一个Protobuf文件来定义你的服务和消息,你还需要配置构建工具将其编译成Java源代码。这是gRPC开发的标准步骤(即与Spring无关)。现在我们来看看Spring gRPC的功能。
gPRC 服务器
创建一个类型为 BindableService 的 @Bean。例如:
@Service
public class GrpcServerService extends SimpleGrpc.SimpleImplBase {
...
}
(BindableService 是 gRPC 用于将服务绑定到服务器的接口,而 SimpleImplBase 是根据您的 Protobuf 文件为您生成的。)
然后,你只需运行你的应用程序,gRPC服务器就会在默认端口(9090)上启动。以下是一个简单的示例(标准的Spring Boot应用程序):
@SpringBootApplication
public class GrpcServerApplication {
public static void main(String[] args) {
SpringApplication.run(GrpcServerApplication.class, args);
}
}
从你的集成开发环境(IDE)中运行它,或者在命令行中使用 ./mvnw spring-boot:run 或 ./gradlew bootRun 来运行。
gRPC 客户端
要创建一个简单的gRPC客户端,可以使用Spring Boot启动器(如上所述——与服务器的配置相同)。然后你可以注入一个类型为GrpcChannelFactory的bean,并使用它来创建一个gRPC通道。通道最常见的用途是创建一个客户端,以便与某个服务进行通信,就像上面的例子一样。项目中由Protobuf生成的源代码会包含stub类,只需将这些stub类绑定到通道上即可。例如,要与本地服务器上的SimpleGrpc服务进行通信:
@Bean
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090"));
}
然后你可以注入这个存根(stub),并在你的应用程序中使用它。
默认的 GrpcChannelFactory 实现也可以创建一个“命名”的通道,然后你可以使用该通道来提取连接服务器所需的配置。例如:
@Bean
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
return SimpleGrpc.newBlockingStub(channels.createChannel("local"));
}
然后在 application.properties 中:
spring.grpc.client.channels.local.address=0.0.0.0:9090
有一个名为“default”的通道,你可以通过spring grpc.client.default-channel.*以相同的方式进行配置。如果在创建通道时没有指定名称的通道,那么默认会使用这个“default”通道。
原生图像
gRPC服务器和客户端支持原生图像(native images)。你可以使用常规的Spring Boot方法来构建你的构建工具(Maven或Gradle)。