Spring Boot 集成 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文件增加
 
<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 web
  	SpringApplication.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 {
    @Override
    public 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
@Component
public @interface GrpcService {
}
- 在SpringBoot中增加Grpc启动器,并将Spring管理的类,添加到Grpc服务中
 
/**
 * Spring Boot 启动器
 */
@SpringBootApplication
public class Launcher {
    public static void main(String[] args) {
        // 启动SpringBoot web
        ConfigurableApplicationContext 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
 
@Component
public 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 {
    @Autowired
    private 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());
    }
}
四.其他补充
暂没
Spring Boot 集成 GRPC
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
Spring Boot 集成 GRPC的更多相关文章
- Spring Boot集成Jasypt安全框架
		
Jasypt安全框架提供了Spring的集成,主要是实现 PlaceholderConfigurerSupport类或者其子类. 在Sring 3.1之后,则推荐使用PropertySourcesPl ...
 - Spring boot集成swagger2
		
一.Swagger2是什么? Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件. Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格 ...
 - Spring Boot 集成 Swagger,生成接口文档就这么简单!
		
之前的文章介绍了<推荐一款接口 API 设计神器!>,今天栈长给大家介绍下如何与优秀的 Spring Boot 框架进行集成,简直不能太简单. 你所需具备的基础 告诉你,Spring Bo ...
 - spring boot 集成 zookeeper 搭建微服务架构
		
PRC原理 RPC 远程过程调用(Remote Procedure Call) 一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远程系统资源,R ...
 - Spring Boot 集成Swagger
		
Spring Boot 集成Swagger - 小单的博客专栏 - CSDN博客https://blog.csdn.net/catoop/article/details/50668896 Spring ...
 - spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,guava限流,定时任务案例, 发邮件
		
本文介绍spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,定时任务案例 集成swagger--对于做前后端分离的项目,后端只需要提供接口访问,swagger提供了接口 ...
 - Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件
		
上一篇文章,写了如何搭建一个简单的Spring boot项目,本篇是接着上一篇文章写得:Spring boot入门:快速搭建Spring boot项目(一),主要是spring boot集成mybat ...
 - (转)Spring Boot(十八):使用 Spring Boot 集成 FastDFS
		
http://www.ityouknow.com/springboot/2018/01/16/spring-boot-fastdfs.html 上篇文章介绍了如何使用 Spring Boot 上传文件 ...
 - Spring Boot集成JPA的Column注解命名字段无效的问题
		
偶然发现,Spring Boot集成jpa编写实体类的时候,默认使用的命名策略是下划线分隔的字段命名. Spring Boot版本:1.5.4.release 数据表: id int, userNam ...
 
随机推荐
- Android开发FAQ集锦!!!
			
.Android SDK应该从什么地方下载?为什么(http://developer.Android.com/ )经常上不上去? 答:谷歌官网的 (http://developer.Android.c ...
 - KJHttp框架使用讲解
			
摘要 本文原创,转载请注明地址:http://kymjs.com/code/2015/05/12/01写给那些在用.想用.还没有用过KJFrame的朋友. KJFrameForAndroid总共分为四 ...
 - andriod studio 获得程序名
			
getResources().getString(R.string.app_name)
 - Oracle中索引的使用 索引性能优化调整
			
索引是由Oracle维护的可选结构,为数据提供快速的访问.准确地判断在什么地方需要使用索引是困难的,使用索引有利于调节检索速度. 当建立一个索引时,必须指定用于跟踪的表名以及一个或多个表列.一旦建立了 ...
 - std::vector 两种操作的比较
			
swap assign 这里只想说明这三种操作的用处和效率.swap和assign都可以用在将一个vector的内容全部复制给另外一个vector,区别是swap会改变源vector,而assign会 ...
 - SQL Server基础知识三十三问 (7-14)
			
8. 一般什么时候使用update_statistics命令? 答: 这个命令基本上是在很多数据被处理过了之后才使用的. 如果大量的删除, 修改, 或这大量的数据插入已经发生了, 那么index就需 ...
 - jQuery用面向对象的思想来编写验证表单的插件
			
本人的重点是怎么构建一个简单有效可扩展的jQuery表单验证插件,这篇文章没有教你怎么用 validate plugin.我们的重点在学习一些jQuery,Javascript面向对象编程的知识. 下 ...
 - css表格单元格中的长文本的显示问题
			
自动换行问题,正常字符的换行是比较合理的,而连续的数字和英文字符常常将容器撑大,挺让人头疼,下面介绍的是CSS如何实现换行的方法 对于div,p等块级元素 正常文字的换行(亚洲文字和非亚洲文字)元素拥 ...
 - IOS调试—断点调试以及动态输出
			
在开发App的过程中,需要反复的修改和优化我们的代码,特别是当程序出现bug,需要快速的找出错误的原因,进行修改,以保证程序的正确执行. 断点调试,是最常用最简单的一种调试方式,可以一步步跟踪程序执行 ...
 - 基于Sql Server 2008的分布式数据库的实践(终结)
			
学习.操作心得 以前在做网站程序的时候一直用的是MYSQL,但是网上搜到MYSQL不支持分布式操作,然后便开始查询MSSQL的分布式数据库的设计与操作,后来在网上找到了<基于SQL SERVER ...