gRPC Java:Spring boot整合gRPC

2017-05-02 阅读: gRPC

接下来我们需要把gRPC和Spring boot整合在一起,这里主要记录我们的整合方式。

项目目录结构

项目的目录结构如下:

foo-svc
├── foo-svc-proto
│   ├── build.gradle
│   └── src
│       └── main
│           └── proto
│               ├── xx1_service.proto
│               └── xx2_service.proto
├── foo-svc-server
│   ├── build.gradle
│   └── src
│       └── main
│           ├── java
│           └── resources
│               └── application.yml
├── build.gradle
├── gradle.properties
└── settings.gradle

一个gRPC服务的项目由两个子项目组成:

  • proto项目,里面维护gRPC服务的proto文件
  • server项目,gRPC服务的具体实现

gradle构建脚本

整个gRPC服务项目使用gradle构建,下面介绍父子项目的各个构建脚本的内容。

根项目foo-svc

foo-svc/settings.gradle:

include 'foo-svc-proto'
include 'foo-svc-server'
rootProject.name = 'foo-svc'

foo-svc/build.gradle:

buildscript {
	repositories {
	    mavenCentral()
	}
	ext {
		springBootVersion = '1.5.4.RELEASE'
	}
	dependencies {
	    classpath 'com.github.ben-manes:gradle-versions-plugin:0.11.1'
	    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
	    classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
	}
}

apply plugin:'base'

allprojects {
    group = 'com.frognew.svc'
    version = version	
    repositories {
        maven {
	       mavenCentral()
	    }
    }

	ext {
		grpcVersion = '1.4.0'
		grpcSpringBootStarterVersion = '1.1.1.RELEASE'
		jasyptSpringBootStarterVersion = '1.12'
		mybatisSpringBootStarterVersion = '1.3.0'
		logbackVersion = '1.2.2'
		slf4jVersion='1.7.25'
		protocVersion='3.3.0'
	}
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'com.github.ben-manes.versions'
    
    configurations { 
		all*.exclude group:'com.sun.xml.bind',module:'jaxb-impl'
		all*.exclude group:'xml-apis',module:'xml-apis'
		all*.exclude group:'stax',module:'stax-api'
		all*.exclude group:'org.slf4j',module:'slf4j-log4j12'
		all*.exclude group:'commons-logging'
		all*.exclude group:'c3p0'
    }
    sourceSets.main.resources.srcDirs += "src/main/java"
    sourceSets.test.resources.srcDirs += "src/test/java"
    compileJava {
        sourceCompatibility=1.8
        targetCompatibility=1.8
        options.encoding='UTF-8'
   }
   compileTestJava {
        sourceCompatibility=1.8
        targetCompatibility=1.8
        options.encoding='UTF-8'
   }
    
   tasks.eclipse.dependsOn cleanEclipse

}
  • 上面根项目的构建脚本foo-svc/build.gradle中主要定义了项目通用的依赖版本和一些插件信息,并对项目的构建行为做了一些限制。

子项目foo-svc-proto

foo-svc/foo-svc-proto/build.gradle:

apply plugin: 'com.google.protobuf'
apply plugin: 'maven-publish'

dependencies {
    compile "io.grpc:grpc-netty:${grpcVersion}"
    compile "io.grpc:grpc-protobuf:${grpcVersion}"
    compile "io.grpc:grpc-stub:${grpcVersion}"
}


sourceSets {
   main {
   	java {
   		srcDir 'build/generated/source/proto/main/java'
   		srcDir 'build/generated/source/proto/main/grpc'
   	}
   }
}


protobuf {
  protoc {
    artifact = "com.google.protobuf:protoc:${protocVersion}"
  }
  plugins {
    grpc {
      artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
    }
  }
  generateProtoTasks {
    all()*.plugins {
      grpc {
        option 'enable_deprecated=false'
      }
    }
  }
}

jar {
    exclude("*.proto")
}

task sourceJar(type: Jar) {
    from sourceSets.main.allJava
}

publishing {
    repositories {
        maven {
            url "http://192.168.1.10:8081/nexus/content/repositories/snapshots/"
        }
    }
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact sourceJar {
                classifier "sources"
            }
        }
    }
}

tasks.eclipse.dependsOn compileJava

foo-svc/foo-svc-proto/build.gradle中使用com.google.protobuf插件将src/main/proto中的proto文件编译生成gRPC的java代码。 生成的代码位于build/generated/source/proto/main/javabuild/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:

apply plugin: 'org.springframework.boot'

dependencies {
	compile project(':foo-svc-proto')
	
	compile 'org.springframework.boot:spring-boot-starter'
	compile 'org.springframework.boot:spring-boot-starter-data-redis'
	compile "net.devh:grpc-server-spring-boot-starter:$grpcSpringBootStarterVersion"
	compile "org.mybatis.spring.boot:mybatis-spring-boot-starter:$mybatisSpringBootStarterVersion"
	compile "com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptSpringBootStarterVersion"
	compile 'com.fasterxml.jackson.core:jackson-databind'
	
	runtime 'mysql:mysql-connector-java' 
	runtime 'redis.clients:jedis:2.9.0'
	runtime 'org.apache.commons:commons-pool2:2.4.2'
	
	testCompile('org.springframework.boot:spring-boot-starter-test')
}

从子项目foo-svc-server的构建脚本可以看出,foo-svc-server就是一个简单的spring-boot项目。 这里使用了yidongnan/grpc-spring-boot-starter这个项目简化了Spring-boot和gRPC整合的代码。

@GrpcService(Xxx1ServiceGrpc.class)
public class Xxx1ServiceService extends Xxx1ServiceImplBase {
	
	
	@Override
	public void sayHello(SayHelloReq request, StreamObserver<SayHelloResp> responseObserver) {
		SayHelloResp.Builder respBuilder = SayHelloResp.newBuilder();
		......
		responseObserver.onNext(respBuilder.build());
		responseObserver.onCompleted();
	}

服务的客户端

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.frognew.svc.foo.proto.Xxx1ServiceGrpc;

import io.grpc.Channel;
import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;

@SpringBootApplication
public class ClientDemoApplication {

    @GrpcClient("foo-svc-server")
    private Channel xxx1SvcChannel;
	
	@Bean
	public Xxx1ServiceGrpc.Xxx1ServiceBlockingStub xxx1ServiceBlockingStub() {
		return Xxx1ServiceGrpc.newBlockingStub(xxx1SvcChannel);
	}
	
	public static void main(String[] args) {
		SpringApplication.run(ApidemoApplication.class, args);
	}
}

将上面的Xxx1ServiceBlockingStub注入到业务组件中直接使用即可。

上面@GrpcClient("foo-svc-server")中会读取客户端项目application.yml中的:

grpc:
  client:
    foo-svc-server:
      host:
        - 127.0.0.1
      port:
        - 9090

获取gRPC服务的地址和端口。我们的服务最终是发布到Kubernetes中,上面的host和port最终设置成Kubernetes中对应Server的名称和端口即可,服务发现机制由Kubernetes提供。

参考

标题:gRPC Java:Spring boot整合gRPC
本文链接:https://blog.frognew.com/2017/05/grpc-spring-boot.html
转载请注明出处。

目录