gRPC Java:Spring boot整合gRPC
2017-05-02
接下来我们需要把gRPC和Spring boot整合在一起,这里主要记录我们的整合方式。
项目目录结构 #
项目的目录结构如下:
1foo-svc
2├── foo-svc-proto
3│ ├── build.gradle
4│ └── src
5│ └── main
6│ └── proto
7│ ├── xx1_service.proto
8│ └── xx2_service.proto
9├── foo-svc-server
10│ ├── build.gradle
11│ └── src
12│ └── main
13│ ├── java
14│ └── resources
15│ └── application.yml
16├── build.gradle
17├── gradle.properties
18└── settings.gradle
一个gRPC服务的项目由两个子项目组成:
- proto项目,里面维护gRPC服务的proto文件
- server项目,gRPC服务的具体实现
gradle构建脚本 #
整个gRPC服务项目使用gradle构建,下面介绍父子项目的各个构建脚本的内容。
根项目foo-svc #
foo-svc/settings.gradle:
1include 'foo-svc-proto'
2include 'foo-svc-server'
3rootProject.name = 'foo-svc'
foo-svc/build.gradle:
1buildscript {
2 repositories {
3 mavenCentral()
4 }
5 ext {
6 springBootVersion = '1.5.4.RELEASE'
7 }
8 dependencies {
9 classpath 'com.github.ben-manes:gradle-versions-plugin:0.11.1'
10 classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
11 classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
12 }
13}
14
15apply plugin:'base'
16
17allprojects {
18 group = 'com.frognew.svc'
19 version = version
20 repositories {
21 maven {
22 mavenCentral()
23 }
24 }
25
26 ext {
27 grpcVersion = '1.4.0'
28 grpcSpringBootStarterVersion = '1.1.1.RELEASE'
29 jasyptSpringBootStarterVersion = '1.12'
30 mybatisSpringBootStarterVersion = '1.3.0'
31 logbackVersion = '1.2.2'
32 slf4jVersion='1.7.25'
33 protocVersion='3.3.0'
34 }
35}
36
37subprojects {
38 apply plugin: 'java'
39 apply plugin: 'eclipse'
40 apply plugin: 'com.github.ben-manes.versions'
41
42 configurations {
43 all*.exclude group:'com.sun.xml.bind',module:'jaxb-impl'
44 all*.exclude group:'xml-apis',module:'xml-apis'
45 all*.exclude group:'stax',module:'stax-api'
46 all*.exclude group:'org.slf4j',module:'slf4j-log4j12'
47 all*.exclude group:'commons-logging'
48 all*.exclude group:'c3p0'
49 }
50 sourceSets.main.resources.srcDirs += "src/main/java"
51 sourceSets.test.resources.srcDirs += "src/test/java"
52 compileJava {
53 sourceCompatibility=1.8
54 targetCompatibility=1.8
55 options.encoding='UTF-8'
56 }
57 compileTestJava {
58 sourceCompatibility=1.8
59 targetCompatibility=1.8
60 options.encoding='UTF-8'
61 }
62
63 tasks.eclipse.dependsOn cleanEclipse
64
65}
- 上面根项目的构建脚本foo-svc/build.gradle中主要定义了项目通用的依赖版本和一些插件信息,并对项目的构建行为做了一些限制。
子项目foo-svc-proto #
foo-svc/foo-svc-proto/build.gradle:
1apply plugin: 'com.google.protobuf'
2apply plugin: 'maven-publish'
3
4dependencies {
5 compile "io.grpc:grpc-netty:${grpcVersion}"
6 compile "io.grpc:grpc-protobuf:${grpcVersion}"
7 compile "io.grpc:grpc-stub:${grpcVersion}"
8}
9
10
11sourceSets {
12 main {
13 java {
14 srcDir 'build/generated/source/proto/main/java'
15 srcDir 'build/generated/source/proto/main/grpc'
16 }
17 }
18}
19
20
21protobuf {
22 protoc {
23 artifact = "com.google.protobuf:protoc:${protocVersion}"
24 }
25 plugins {
26 grpc {
27 artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
28 }
29 }
30 generateProtoTasks {
31 all()*.plugins {
32 grpc {
33 option 'enable_deprecated=false'
34 }
35 }
36 }
37}
38
39jar {
40 exclude("*.proto")
41}
42
43task sourceJar(type: Jar) {
44 from sourceSets.main.allJava
45}
46
47publishing {
48 repositories {
49 maven {
50 url "http://192.168.1.10:8081/nexus/content/repositories/snapshots/"
51 }
52 }
53 publications {
54 mavenJava(MavenPublication) {
55 from components.java
56 artifact sourceJar {
57 classifier "sources"
58 }
59 }
60 }
61}
62
63tasks.eclipse.dependsOn compileJava
foo-svc/foo-svc-proto/build.gradle中使用com.google.protobuf
插件将src/main/proto中的proto文件编译生成gRPC的java代码。
生成的代码位于build/generated/source/proto/main/java
和build/generated/source/proto/main/grpc
这两个目录中。
同时将这两个目录添加到了sourceSets.main.java中。使用maven-publish插件可以将构建生成的jar包发布到团队的私有maven仓库中,这样gRPC服务的java客户端可以直接使用仓库中的jar。
子项目foo-svc-server #
foo-svc/foo-svc-server/build.gradle:
1apply plugin: 'org.springframework.boot'
2
3dependencies {
4 compile project(':foo-svc-proto')
5
6 compile 'org.springframework.boot:spring-boot-starter'
7 compile 'org.springframework.boot:spring-boot-starter-data-redis'
8 compile "net.devh:grpc-server-spring-boot-starter:$grpcSpringBootStarterVersion"
9 compile "org.mybatis.spring.boot:mybatis-spring-boot-starter:$mybatisSpringBootStarterVersion"
10 compile "com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptSpringBootStarterVersion"
11 compile 'com.fasterxml.jackson.core:jackson-databind'
12
13 runtime 'mysql:mysql-connector-java'
14 runtime 'redis.clients:jedis:2.9.0'
15 runtime 'org.apache.commons:commons-pool2:2.4.2'
16
17 testCompile('org.springframework.boot:spring-boot-starter-test')
18}
从子项目foo-svc-server的构建脚本可以看出,foo-svc-server就是一个简单的spring-boot项目。 这里使用了yidongnan/grpc-spring-boot-starter这个项目简化了Spring-boot和gRPC整合的代码。
1@GrpcService(Xxx1ServiceGrpc.class)
2public class Xxx1ServiceService extends Xxx1ServiceImplBase {
3
4
5 @Override
6 public void sayHello(SayHelloReq request, StreamObserver<SayHelloResp> responseObserver) {
7 SayHelloResp.Builder respBuilder = SayHelloResp.newBuilder();
8 ......
9 responseObserver.onNext(respBuilder.build());
10 responseObserver.onCompleted();
11 }
服务的客户端 #
1import org.springframework.boot.SpringApplication;
2import org.springframework.boot.autoconfigure.SpringBootApplication;
3import org.springframework.context.annotation.Bean;
4
5import com.frognew.svc.foo.proto.Xxx1ServiceGrpc;
6
7import io.grpc.Channel;
8import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;
9
10@SpringBootApplication
11public class ClientDemoApplication {
12
13 @GrpcClient("foo-svc-server")
14 private Channel xxx1SvcChannel;
15
16 @Bean
17 public Xxx1ServiceGrpc.Xxx1ServiceBlockingStub xxx1ServiceBlockingStub() {
18 return Xxx1ServiceGrpc.newBlockingStub(xxx1SvcChannel);
19 }
20
21 public static void main(String[] args) {
22 SpringApplication.run(ApidemoApplication.class, args);
23 }
24}
将上面的Xxx1ServiceBlockingStub注入到业务组件中直接使用即可。
上面@GrpcClient("foo-svc-server")
中会读取客户端项目application.yml中的:
1grpc:
2 client:
3 foo-svc-server:
4 host:
5 - 127.0.0.1
6 port:
7 - 9090
获取gRPC服务的地址和端口。我们的服务最终是发布到Kubernetes中,上面的host和port最终设置成Kubernetes中对应Server的名称和端口即可,服务发现机制由Kubernetes提供。