(1). 概述
在这一小篇学习GRPC与SpringBoot的整合.
(2). 项目结构
lixin-macbook:grpc-springboot-demo-parent lixin$ tree -L 1
.
├── client # 客户端
├── pom.xml
├── proto # PB定义的协议
└── server # 服务端
(3). grpc-springboot-demo-parent/pom.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>help.lixin.grpc.demo</groupId>
<artifactId>grpc-springboot-demo-parent</artifactId>
<packaging>pom</packaging>
<version>1.1.0</version>
<name>grpc-springboot-demo-parent ${project.version}</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-boot.version>2.4.1</spring-boot.version>
</properties>
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<modules>
<module>server</module>
<module>client</module>
<module>proto</module>
</modules>
</project>
(4). proto项目结构
lixin-macbook:grpc-springboot-demo-parent lixin$ tree proto
proto
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── help
│ │ └── lixin
│ │ └── proto
│ │ ├── HelloRequest.java
│ │ ├── HelloRequestOrBuilder.java
│ │ ├── HelloResponse.java
│ │ ├── HelloResponseOrBuilder.java
│ │ ├── HelloServiceGrpc.java
│ │ └── HelloServiceProto.java
│ ├── proto
│ │ └── HelloService.proto
│ └── resources
└── target
(5). proto/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>help.lixin.grpc.demo</groupId>
<artifactId>grpc-springboot-demo-parent</artifactId>
<version>1.1.0</version>
</parent>
<artifactId>grpc-springboot-demo-proto</artifactId>
<packaging>jar</packaging>
<version>1.1.0</version>
<!-- 源码编译,需要指定以下依赖,并配置scope -->
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.42.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.42.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.42.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.0</version>
</extension>
</extensions>
<resources>
<resource>
<directory>src/main/proto</directory>
<includes>
<include>**/*.proto</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.19.1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.42.1:exe:${os.detected.classifier}</pluginArtifact>
<!-- proto文件放置的目录 -->
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<!-- 生成文件的目录 -->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!-- 生成文件前是否把目标目录清空-->
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
(6). proto/src/main/proto/HelloService.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "help.lixin.proto";
option java_outer_classname = "HelloServiceProto";
option objc_class_prefix = "HLW";
package help.lixin.proto;
service HelloService {
rpc sayHello (HelloRequest) returns (HelloResponse) {}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
(7). server项目结构
lixin-macbook:grpc-springboot-demo-parent lixin$ tree server
server
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── help
│ │ └── lixin
│ │ └── demo
│ │ ├── Application.java
│ │ └── service
│ │ └── HelloService.java
│ └── resources
│ └── application.yml
└── target
(8). server/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>help.lixin.grpc.demo</groupId>
<artifactId>grpc-springboot-demo-parent</artifactId>
<version>1.1.0</version>
</parent>
<artifactId>grpc-springboot-demo-server</artifactId>
<packaging>jar</packaging>
<version>1.1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- grpc依赖添加 -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.13.1.RELEASE</version>
</dependency>
<!-- 添加协议依赖 -->
<dependency>
<groupId>help.lixin.grpc.demo</groupId>
<artifactId>grpc-springboot-demo-proto</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
</project>
(9). server/src/main/java/help/lixin/demo/service/HelloService.java
package help.lixin.demo.service;
import help.lixin.proto.HelloRequest;
import help.lixin.proto.HelloResponse;
import help.lixin.proto.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
// ************************************************************
// 自定义业务实现,并指定注解.
// ************************************************************
@GrpcService
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
try {
String name = request.getName();
responseObserver.onNext(HelloResponse.newBuilder().setMessage(name + " 你好哈!").build());
} finally {
responseObserver.onCompleted();
}
}
}
(10). server/src/main/java/help/lixin/demo/Application.java
package help.lixin.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
(11). server/src/main/resources/application.yml
spring:
application:
name: demo-server
server:
port: 8080
grpc:
server:
port: 8888
(12). client项目结构
lixin-macbook:grpc-springboot-demo-parent lixin$ tree client
client
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── help
│ │ └── lixin
│ │ └── demo
│ │ ├── GrpcClientApplication.java
│ │ └── controller
│ │ └── HelloController.java
│ └── resources
│ └── application.yml
└── target
(13). client/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>help.lixin.grpc.demo</groupId>
<artifactId>grpc-springboot-demo-parent</artifactId>
<version>1.1.0</version>
</parent>
<artifactId>grpc-springboot-demo-client</artifactId>
<packaging>jar</packaging>
<version>1.1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- grpc依赖添加 -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.13.1.RELEASE</version>
</dependency>
<dependency>
<groupId>help.lixin.grpc.demo</groupId>
<artifactId>grpc-springboot-demo-proto</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
</project>
(14). client/src/main/java/help/lixin/demo/controller/HelloController.java
package help.lixin.demo.controller;
import help.lixin.proto.HelloRequest;
import help.lixin.proto.HelloResponse;
import help.lixin.proto.HelloServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
// **************************************************************
// GRPC客户端.
// **************************************************************
@GrpcClient("demo-server")
private HelloServiceGrpc.HelloServiceBlockingStub helloService;
@GetMapping("/hello")
public String sayHello(String name) {
HelloResponse helloResponse = helloService.sayHello(HelloRequest.newBuilder().setName(name).build());
return helloResponse.getMessage();
}
}
(15). client/src/main/java/help/lixin/demo/GrpcClientApplication.java
package help.lixin.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GrpcClientApplication {
public static void main(String[] args) {
SpringApplication.run(GrpcClientApplication.class);
}
}
(16). client/src/main/resources/application.yml
spring:
application:
name: demo-client
server:
port: 7070
grpc:
client:
demo-server: # 定义微服务的名称
# 使用静态ip地址的方式访问
address: 'static://127.0.0.1:8888'
#
negotiationType: plaintext
(17). 测试访问
lixin-macbook:~ lixin$ curl http://localhost:7070/hello?name=lixin
lixin 你好哈!
(18). 总结
GRPC自身并没有提供与SpringBoot的集成,上面的依赖是来自于社区,从注解配置信息上能看得出来,这个社区对GRPC进行了扩展,允许负载均衡和服务发现来着的.