RPC框架实践之:Google gRPC

Stella981
• 阅读 895

RPC框架实践之:Google gRPC

My Desktop



概述

gRPC是Google开源的通用高性能RPC框架,它支持的是使用Protocol Buffers来编写Service定义,支持较多语言扩平台并且拥有强大的二进制序列化工具集。与文章《RPC框架实践之:Apache Thrift》 一文中实践的另一种通用RPC框架 Thrift 能通过Generator自动生成对应语言的Service接口类似,gRPC也能 自动地生成 Server和Client的 Service存根(Stub),我们只需要 一个命令 就能快速搭建起RPC运行环境。

下面实践一下gRPC框架,做的事情就是:Client端通过远程RPC调用Server的获取时间的接口,从而将服务器时间获取到本地并显示。

类似于之前对于 RPC框架: Thrift 的实践步骤,下面一一阐述。

注: 本文首发于 My 公众号 CodeSheep ,可 长按扫描 下面的 小心心 来订阅 ↓ ↓ ↓

RPC框架实践之:Google gRPC


开发gRPC-API

  • 首先创建一个基于Maven的项目: GrpcAPI

  • pom中加入grpc相关的依赖

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-all</artifactId>
            <version>1.12.0</version>
        </dependency>
    

这个grpc-all包含了很多grpc相关的组件:grpc-netty 、 grpc-protobuf 、grpc-stub 等等

RPC框架实践之:Google gRPC

  • pom中加入grpc相关的 build插件

这里添加两个Maven插件,目的是后面需要用这些插件来执行Protocol Buffers命令,从而自动生成相关的Stub代码:

os-maven-plugin:生成平台无关的属性 protobuf-maven-plugin:执行Protocol Buffers命令并生成Stub代码库

    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.4.1.Final</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.5.0</version>
                <configuration>
                    <pluginId>grpc-java</pluginId>
                    <protocArtifact>com.google.protobuf:protoc:3.0.2:exe:${os.detected.classifier}</protocArtifact>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.2.0:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  • 编写.proto的服务定义文件

这里.proto文件的作用和写法就和我的前一篇文章《RPC框架实践之:Apache Thrift》 一文中Thrift所要求的.thrift文件编写一样,是有其自己的语法要求的!

syntax = "proto3”;   // 语法版本

// stub选项
option java_package = "com.hansonwang99.grpc.api”;
option java_outer_classname = “RPCDateServiceApi”;
option java_multiple_files = true;

// 定义包名,类似于我的文章《RPC框架实践之:Apache Thrift》中的Thrift的namespace
package com.hansonwang99.grpc.api;

// 服务接口定义,服务端和客户端都要遵守该接口进行通信
service RPCDateService {
  rpc getDate (RPCDateRequest) returns (RPCDateResponse) {}
}

// 定义消息(请求)
message RPCDateRequest {
  string userName = 1;
}

// 定义消息(响应)
message RPCDateResponse {
  string serverDate = 1;
}
  • 执行mvn compile命令来自动生成代码Stub

mvn编译完成以后,在target/generated-sources目录下就能看到根据上面.proto文件自动转化生成的Java代码Stub

RPC框架实践之:Google gRPC

代码生成结果如下所示

RPC框架实践之:Google gRPC

好了,既然gRPC-API已经有了,下面可以分别编写服务端和客户端


开发gRPC服务端

  • 创建基于Maven的项目:Server

  • pom中添加 GrpcAPI 依赖

        <dependency>
            <groupId>com.hansonwang99</groupId>
            <artifactId>GrpcAPI</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    

接下来一步比较关键

  • 实现gRPC服务接口

    public class RPCDateServiceImpl extends RPCDateServiceGrpc.RPCDateServiceImplBase{ @Override public void getDate(RPCDateRequest request, StreamObserver responseObserver) { RPCDateResponse rpcDateResponse = null; Date now=new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("今天是"+"yyyy年MM月dd日 E kk点mm分”); String nowTime = simpleDateFormat.format( now ); try { rpcDateResponse = RPCDateResponse .newBuilder() .setServerDate( "Welcome " + request.getUserName() + ", " + nowTime ) .build(); } catch (Exception e) { responseObserver.onError(e); } finally { responseObserver.onNext( rpcDateResponse ); } responseObserver.onCompleted(); } }

我想此处重写的getDate()方法并不陌生吧,这正是上文 .proto 文件中定义的Service接口。 此处逻辑比较简单:获取当前时间,并且将其与请求RPCDateRequest中提取出的userName字段进行拼接,然后返回给调用端!形成一个闭环

  • 创建gRPC服务端启动类

    public class GRPCServer { private static final int port = 9999; public static void main( String[] args ) throws Exception { Server server = ServerBuilder. forPort(port) .addService( new RPCDateServiceImpl() ) .build().start(); System.out.println( "grpc服务端启动成功, 端口=" + port ); server.awaitTermination(); } }

端口自定义的9999,也就是在该端口监听。现在可以立即运行GRPCServer,来启动服务端

RPC框架实践之:Google gRPC


开发gRPC客户端

  • 创建基于Maven的项目:Client

  • pom中依然需要添加 GrpcAPI 依赖

        <dependency>
            <groupId>com.hansonwang99</groupId>
            <artifactId>GrpcAPI</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    
  • 创建gRPC客户端启动类

    public class GRPCClient { private static final String host = “localhost”; private static final int serverPort = 9999; public static void main( String[] args ) throws Exception { ManagedChannel managedChannel = ManagedChannelBuilder.forAddress( host, serverPort ).usePlaintext().build(); try { RPCDateServiceGrpc.RPCDateServiceBlockingStub rpcDateService = RPCDateServiceGrpc.newBlockingStub( managedChannel ); RPCDateRequest rpcDateRequest = RPCDateRequest .newBuilder() .setUserName(“hansonwang99”) .build(); RPCDateResponse rpcDateResponse = rpcDateService.getDate( rpcDateRequest ); System.out.println( rpcDateResponse.getServerDate() ); } finally { managedChannel.shutdown(); } } }

现在立即启动 GRPCClient!


C-S通信实验

还记得我们的目标吗?

RPC完成的即是远程的过程调用,在本实验中那就是客户端可以远程调用服务端的getDate()过程,并将结果取到客户端来显示!

RPC框架实践之:Google gRPC


后记

本文实验代码在码云 → 需要自取

作者更多的原创文章:在开源中国

作者其他一些RPC框架的实践如下:

作者一些关于容器化、微服务化方面的文章如下:


点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Eureka Server 开启Spring Security Basic认证
!Desktop(https://uploadimages.jianshu.io/upload_images/98242475ce94f98ae00f42f.jpg?imageMogr2/autoorient/strip%7CimageView2/2/w/1240)文章共503字,阅读大约需要2分钟!概述
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这