一.背景
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
Grpc 由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
项目定位是电商平台和WMS系统中间的插件服务,wms采用.net语言开发,电商平台采用java开发,所以出现了多语言间的数据交换,开始考虑使用json协议,方便快捷,但是考虑到效率和系统发展的问题,考虑使用RPC框架,斟酌之后敲定为GRPC。
但是,我们拓展服务使用的SpringBoot,Grpc和SpringBoot集成的文章不是很多,大部分都是采用github上*-springboot.grpc.starter的项目,看了一下,并不是很感兴趣,所以自己根据官网的demo,尝试与SpringBoot集成,所以在这和大家分享下
二. 准备工作
开发环境
Spring Boot 2.0.5.RELEASE Grpc 1.15.0 Inteliji Idea 2018.3
项目截图

三.实现过程
1. 配置SpringBoot项目
Pom文件增加
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version></parent><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></dependency></dependencies>
编写启动类
public static void main(String[] args) {// 启动SpringBoot webSpringApplication.run(Launcher.class, args);}
2. 增加GRPC支持和GRPC代码生成工具,集成GrpcServer端
增加POM文件
<dependency><groupId>io.grpc</groupId><artifactId>grpc-netty-shaded</artifactId><version>1.15.0</version></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-protobuf</artifactId><version>1.15.0</version></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-stub</artifactId><version>1.15.0</version></dependency>
增加maven工具
<build><extensions><extension><groupId>kr.motd.maven</groupId><artifactId>os-maven-plugin</artifactId><version>1.5.0.Final</version></extension></extensions><plugins><plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.5.1</version><configuration><protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact><pluginId>grpc-java</pluginId><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.15.0:exe:${os.detected.classifier}</pluginArtifact></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins></build>
编写Server端实现类
public class HelloWorldService extends HelloWorldServiceGrpc.HelloWorldServiceImplBase {@Overridepublic void welcome(HelloWorld.NameRequest request, StreamObserver<HelloWorld.EchoResponse> responseObserver) {HelloWorld.EchoResponseOrBuilder echoResponseOrBuilder = HelloWorld.EchoResponse.newBuilder();((HelloWorld.EchoResponse.Builder) echoResponseOrBuilder).setMergename("welcome " + request.getName());responseObserver.onNext(((HelloWorld.EchoResponse.Builder) echoResponseOrBuilder).build());responseObserver.onCompleted();}}
增加Grpc启动器
@Component("grpcLauncher")public class GrpcLauncher {private Logger logger = LoggerFactory.getLogger(Launcher.class);/*** 定义Grpc Server*/private Server server;@Value("${grpc.server.port}")private Integer grpcServerPort;/*** GRPC 服务启动方法* @param grpcServiceBeanMap*/public void grpcStart(Map<String, Object> grpcServiceBeanMap) {try{ServerBuilder serverBuilder = ServerBuilder.forPort(grpcServerPort);for (Object bean : grpcServiceBeanMap.values()){serverBuilder.addService((BindableService) bean);logger.info(bean.getClass().getSimpleName() + " is regist in Spring Boot");}server = serverBuilder.build().start();logger.info("grpc server is started at " + grpcServerPort);server.awaitTermination();Runtime.getRuntime().addShutdownHook(new Thread(()->{grpcStop();}));} catch (IOException e){e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}/*** GRPC 服务Stop方法*/private void grpcStop(){if (server != null){server.shutdownNow();}}}
添加自定义注解用于扫描Grpc服务
/*** 自定义注解,用于获取Spring扫描到的类*/@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface GrpcService {}
在SpringBoot中增加Grpc启动器,并将Spring管理的类,添加到Grpc服务中
/*** Spring Boot 启动器*/@SpringBootApplicationpublic class Launcher {public static void main(String[] args) {// 启动SpringBoot webConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(Launcher.class, args);Map<String, Object> grpcServiceBeanMap = configurableApplicationContext.getBeansWithAnnotation(GrpcService.class);GrpcLauncher grpcLauncher = configurableApplicationContext.getBean("grpcLauncher",GrpcLauncher.class);grpcLauncher.grpcStart(grpcServiceBeanMap);}}
至此Server端,集成完毕

3. 增加Client端
获取Chanel
@Componentpublic class GrpcClientMananer {@Value("${grpc.client.host}")private String host;@Value("${grpc.client.port}")private Integer port;public ManagedChannel getChannel(){ManagedChannel channel = ManagedChannelBuilder.forAddress(host,port).disableRetry().idleTimeout(2, TimeUnit.SECONDS).build();return channel;}}
调用方式
@Component public class HelloWorldClient {@Autowiredprivate GrpcClientMananer grpcClientMananer;public void call(){ManagedChannel channel = grpcClientMananer.getChannel();HelloWorld.NameRequestOrBuilder nameRequestOrBuilder = HelloWorld.NameRequest.newBuilder();((HelloWorld.NameRequest.Builder) nameRequestOrBuilder).setName("Geek");HelloWorldServiceGrpc.HelloWorldServiceBlockingStub stub = HelloWorldServiceGrpc.newBlockingStub(channel);HelloWorld.EchoResponse echoResponse = stub.welcome(((HelloWorld.NameRequest.Builder) nameRequestOrBuilder).build());System.out.println(echoResponse.getMergename());}}
