• Spring Boot 集成 GRPC


    Spring Boot 集成 GRPC

    http://www.demodashi.com/demo/14110.html

    概述

    SpringBoot框架中集成Grpc服务

    详细

    一.背景

    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文件增加

      1. <parent>
      2. <groupId>org.springframework.boot</groupId>
      3. <artifactId>spring-boot-starter-parent</artifactId>
      4. <version>2.0.5.RELEASE</version>
      5. </parent>
      6. <dependencies>
      7. <dependency>
      8. <groupId>org.springframework.boot</groupId>
      9. <artifactId>spring-boot-starter-web</artifactId>
      10. </dependency>
      11. <dependency>
      12. <groupId>org.springframework.boot</groupId>
      13. <artifactId>spring-boot-starter-test</artifactId>
      14. </dependency>
      15. </dependencies>
    • 编写启动类
    1. publicstaticvoid main(String[] args){
    2. // 启动SpringBoot web
    3. SpringApplication.run(Launcher.class, args);
    4. }
    2. 增加GRPC支持和GRPC代码生成工具,集成GrpcServer端
    • 增加POM文件
    1. <dependency>
    2. <groupId>io.grpc</groupId>
    3. <artifactId>grpc-netty-shaded</artifactId>
    4. <version>1.15.0</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>io.grpc</groupId>
    8. <artifactId>grpc-protobuf</artifactId>
    9. <version>1.15.0</version>
    10. </dependency>
    11. <dependency>
    12. <groupId>io.grpc</groupId>
    13. <artifactId>grpc-stub</artifactId>
    14. <version>1.15.0</version>
    15. </dependency>
    • 增加maven工具
    1. <build>
    2. <extensions>
    3. <extension>
    4. <groupId>kr.motd.maven</groupId>
    5. <artifactId>os-maven-plugin</artifactId>
    6. <version>1.5.0.Final</version>
    7. </extension>
    8. </extensions>
    9. <plugins>
    10. <plugin>
    11. <groupId>org.xolstice.maven.plugins</groupId>
    12. <artifactId>protobuf-maven-plugin</artifactId>
    13. <version>0.5.1</version>
    14. <configuration>
    15. <protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
    16. <pluginId>grpc-java</pluginId>
    17. <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.15.0:exe:${os.detected.classifier}</pluginArtifact>
    18. </configuration>
    19. <executions>
    20. <execution>
    21. <goals>
    22. <goal>compile</goal>
    23. <goal>compile-custom</goal>
    24. </goals>
    25. </execution>
    26. </executions>
    27. </plugin>
    28. </plugins>
    29. </build>
    • 编写Server端实现类
    1. publicclassHelloWorldServiceextendsHelloWorldServiceGrpc.HelloWorldServiceImplBase{
    2. @Override
    3. publicvoid welcome(HelloWorld.NameRequest request,StreamObserver<HelloWorld.EchoResponse> responseObserver){
    4. HelloWorld.EchoResponseOrBuilder echoResponseOrBuilder =HelloWorld.EchoResponse.newBuilder();
    5. ((HelloWorld.EchoResponse.Builder) echoResponseOrBuilder).setMergename("welcome "+ request.getName());
    6. responseObserver.onNext(((HelloWorld.EchoResponse.Builder) echoResponseOrBuilder).build());
    7. responseObserver.onCompleted();
    8. }
    9. }
    • 增加Grpc启动器
    1. @Component("grpcLauncher")
    2. publicclassGrpcLauncher{
    3. privateLogger logger =LoggerFactory.getLogger(Launcher.class);
    4. /**
    5. * 定义Grpc Server
    6. */
    7. privateServer server;
    8. @Value("${grpc.server.port}")
    9. privateInteger grpcServerPort;
    10. /**
    11. * GRPC 服务启动方法
    12. * @param grpcServiceBeanMap
    13. */
    14. publicvoid grpcStart(Map<String,Object> grpcServiceBeanMap){
    15. try{
    16. SelfSignedCertificate ssc =newSelfSignedCertificate();
    17. ServerBuilder serverBuilder =ServerBuilder.forPort(grpcServerPort).useTransportSecurity(ssc.certificate(), ssc.privateKey());
    18. for(Object bean : grpcServiceBeanMap.values()){
    19. serverBuilder.addService((BindableService) bean);
    20. logger.info(bean.getClass().getSimpleName()+" is regist in Spring Boot");
    21. }
    22. server = serverBuilder.build().start();
    23. logger.info("grpc server is started at "+ grpcServerPort);
    24. server.awaitTermination();
    25. Runtime.getRuntime().addShutdownHook(newThread(()->{grpcStop();}));
    26. }catch(IOException e){
    27. e.printStackTrace();
    28. }catch(InterruptedException e){
    29. e.printStackTrace();
    30. }
    31. }
    32. /**
    33. * GRPC 服务Stop方法
    34. */
    35. privatevoid grpcStop(){
    36. if(server !=null){
    37. server.shutdownNow();
    38. }
    39. }
    40. }
    • 添加自定义注解用于扫描Grpc服务
    1. /**
    2. * 自定义注解,用于获取Spring扫描到的类
    3. */
    4. @Target({ElementType.TYPE})
    5. @Retention(RetentionPolicy.RUNTIME)
    6. @Documented
    7. @Component
    8. public@interfaceGrpcService{
    9. }
    • 在SpringBoot中增加Grpc启动器,并将Spring管理的类,添加到Grpc服务中
    1. /**
    2. * Spring Boot 启动器
    3. */
    4. @SpringBootApplication
    5. publicclassLauncher{
    6. publicstaticvoid main(String[] args){
    7. // 启动SpringBoot web
    8. ConfigurableApplicationContext configurableApplicationContext =SpringApplication.run(Launcher.class, args);
    9. Map<String,Object> grpcServiceBeanMap = configurableApplicationContext.getBeansWithAnnotation(GrpcService.class);
    10. GrpcLauncher grpcLauncher = configurableApplicationContext.getBean("grpcLauncher",GrpcLauncher.class);
    11. grpcLauncher.grpcStart(grpcServiceBeanMap);
    12. }
    13. }

    至此Server端,集成完毕

    3. 增加Client端
    • 获取Chanel
    1. @Component
    2. publicclassGrpcClientMananer{
    3. @Value("${grpc.client.host}")
    4. privateString host;
    5. @Value("${grpc.client.port}")
    6. privateInteger port;
    7. publicManagedChannel getChannel(){
    8. NettyChannelBuilder ncb =NettyChannelBuilder.forAddress(host, port).sslContext(SslContextBuilder.forClient()
    9. .sslProvider(OpenSsl.isAlpnSupported()?SslProvider.OPENSSL :SslProvider.JDK)
    10. .ciphers(Http2SecurityUtil.CIPHERS,SupportedCipherSuiteFilter.INSTANCE)
    11. .trustManager(InsecureTrustManagerFactory.INSTANCE)
    12. .applicationProtocolConfig(
    13. newApplicationProtocolConfig(
    14. ApplicationProtocolConfig.Protocol.ALPN,
    15. ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,
    16. ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT,
    17. ApplicationProtocolNames.HTTP_2,
    18. ApplicationProtocolNames.HTTP_1_1))
    19. .build());
    20. return ncb.build();
    21. }
    22. }
    • 调用方式
    1. @Component
    2. publicclassHelloWorldClient{
    3. @Autowired
    4. privateGrpcClientMananer grpcClientMananer;
    5. publicvoid call(){
    6. ManagedChannel channel = grpcClientMananer.getChannel();
    7. HelloWorld.NameRequestOrBuilder nameRequestOrBuilder =HelloWorld.NameRequest.newBuilder();
    8. ((HelloWorld.NameRequest.Builder) nameRequestOrBuilder).setName("Geek");
    9. HelloWorldServiceGrpc.HelloWorldServiceBlockingStub stub =HelloWorldServiceGrpc.newBlockingStub(channel);
    10. HelloWorld.EchoResponse echoResponse = stub.welcome(((HelloWorld.NameRequest.Builder) nameRequestOrBuilder).build());
    11. System.out.println(echoResponse.getMergename());
    12. }
    13. }
    14. `

    四.其他补充

    暂没

  • 相关阅读:
    android连接wifi模块
    idea 控制台乱码debug
    线程控制
    jvm 垃圾回收
    java 单例模式
    http报头
    java 构造函数 , 参数传递 , lamda表达式
    mysql 杂识
    spring mvc 配置 拦截器不起作用
    spring mvc 每次请求后是否自动销毁线程
  • 原文地址:https://www.cnblogs.com/xiondun/p/16390153.html
Copyright © 2020-2023  润新知