gRPC在Android中的应用

gRPC的特性:

gRPC 由 Google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。

基于HTTP/2
HTTP/2 提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。gRPC 的协议设计上使用了HTTP2 现有的语义,请求和响应的数据使用HTTP Body 发送,其他的控制信息则用Header 表示。

IDL使用ProtoBuf
gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。

多语言支持
gRPC支持多种语言(C, C++, Python, PHP, Nodejs, C#, Objective-C、Golang、Java),并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。

gRPC优缺点:
优点
protobuf二进制消息,性能好/效率高(空间和时间效率都很不错)
proto文件生成目标代码,简单易用
序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射(XML,JSON都是这种方式)
支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级
支持多种语言(可以把proto文件看做IDL文件)
Netty等一些框架集成
缺点:
GRPC尚未提供连接池,需要自行实现
尚未提供“服务发现”、“负载均衡”机制
因为基于HTTP2,绝大部多数HTTP Server、Nginx都尚不支持,即Nginx不能将GRPC请求作为HTTP请求来负载均衡,而是作为普通的TCP请求。(nginx1.9版本已支持)
Protobuf二进制可读性差(貌似提供了Text_Fromat功能)
默认不具备动态特性(可以通过动态定义生成消息类型或者动态编译支持)

grpc主要使用场景:

1.低延时、高可用的分布式系统;
2.移动端与云服务端的通讯;
3.使用protobuf,独立于语言的协议,支持多语言之间的通讯;
4.可以分层扩展,如:身份验证,负载均衡,日志记录,监控等。
在微服务场景中使用究竟是否要使用grpc呢?开源社区较为成熟的微服务框架有
dubbo、spring cloud。dubbo虽然在服务治理上做的比较完善,但是不支持跨语言。个人觉得,如果不考虑跨语言问题,选用dubbo。考虑跨语言,可以选用grpc、Thrift,但是grpc、Thrift没有服务发现和负载均衡机制,一般使用代理转发负载均衡控制策略。
在移动端app应用场景中,grpc以其优异的性能,因pb和http2的特性,为移动端用户节省流量、电量。对比传统的http1.1+json方式,建议可以先尝试小范围使用grpc,待系统稳定后,再扩大grpc使用范围。

Android Studio中gRPC的配置

1.导入相关依赖(小编用的Gradle)可以通过Github上的 https://github.com/grpc/grpc-java 熟悉搭建过程。小编用的这是1.27.0这个版本,小编搭建的时候GitHub还没有

compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+

包,小编就自己引了一个annotations的包,这里还是推荐用GitHub上的这个吧。

implementation 'io.grpc:grpc-okhttp:1.27.0'implementation 'io.grpc:grpc-protobuf:1.27.0'implementation 'io.grpc:grpc-stub:1.27.0'

protocbuf依赖

implementation 'com.google.protobuf:protobuf-java:3.11.0'

2.安装插件,在项目的根配置中添加插件,全部配置内容如下:

buildscript {    repositories {        google()        jcenter()        mavenCentral()        maven {url 'http://maven.aliyun.com/nexus/content/groups/public/'}        maven { url 'https://www.jitpack.io' }    }    dependencies {        classpath 'com.android.tools.build:gradle:3.5.3'        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'    }}allprojects {    repositories {        google()        jcenter()    }}task clean(type: Delete) {    delete rootProject.buildDir}

在Model的build.gradle配置内容如下:

apply plugin: 'com.android.application'apply plugin: 'com.google.protobuf'android {    compileSdkVersion 29    buildToolsVersion "29.0.3"    defaultConfig {        applicationId "com.example.myapplication"        minSdkVersion 27        targetSdkVersion 29        versionCode 1        versionName "1.0"        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        }    }    sourceSets {        main {            proto {                srcDir 'src/main/proto'            }        }    }}allprojects {    repositories {        maven { url 'https://www.jitpack.io' }    }}protobuf {    protoc {        artifact = "com.google.protobuf:protoc:3.11.0"    }    plugins {        grpc {            artifact = 'io.grpc:protoc-gen-grpc-java:1.27.0'        }    }    generateProtoTasks {        all().each {            task ->                task.plugins {//                    javalite {}                    grpc {                        // Options added to --grpc_out                        option 'lite'                    }                }                task.builtins {                    remove java                }                task.builtins {                    java {}                    // Add cpp output without any option.                    // DO NOT omit the braces if you want this builtin to be added.//                    cpp {}                }        }        all()*.plugins { grpc {} }    }    generatedFilesBaseDir = "$projectDir/src/generated"    generateProtoTasks {        all()*.plugins {            grpc{                setOutputSubDir 'java'            }        }    }}dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    implementation 'androidx.appcompat:appcompat:1.0.2'    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'    testImplementation 'junit:junit:4.12'    androidTestImplementation 'androidx.test.ext:junit:1.1.0'    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'    implementation 'com.squareup.picasso:picasso:2.5.2'    implementation 'io.grpc:grpc-okhttp:1.27.0'    implementation 'io.grpc:grpc-protobuf:1.27.0'    implementation 'io.grpc:grpc-stub:1.27.0'    implementation 'com.google.protobuf:protobuf-java:3.11.0'    implementation 'com.google.code.findbugs:jsr305:3.0.0'    implementation 'com.google.guava:guava:20.0'    implementation 'javax.annotation:javax.annotation-api:1.2'}

以上内容完成后,gRPC插件的配置就已经成功。下一步需要创建proto文件。

3.在src/main下创建proto文件夹,创建目录是根据下面代码设置的,上面已经添加好了,如果需要修改,可自行修改目录。

sourceSets {    main {        proto {            srcDir 'src/main/proto'        }    }}

创建后如下图所示:

4.在proto文件夹下创建***.proto文件,Studio中有个插件 Protobuf Support,系统一般会提示安装的。不提示就自行安装就好。proto文件的语法请参考https://github.com/protocolbuffers/protobuf(GitHub上的知识初学者看不懂就多看几遍,小编也是看了好些次才明白)这里注意gRPC是使用protoc3的。

syntax = "proto3";package com.rpc.proto.user;option  java_package = "com.rpc.proto.user";option  java_outer_classname = "UserProto";option  java_multiple_files = true;service UserRpcServer{    rpc login(loginRequest) returns(loginResponse){}}message loginRequest{    string username = 1;    string password = 2;    int32 power = 3;}message loginResponse{    string state = 1;}

以上是一个用户的登录功能实现。编写完成后构建项目,就会生成proto文件。生成目录在src/generated/debug/java下。当然这个目录也可以在build.gradle中进行设置。
5.编写Android客户端代码

public class GrpcChannel {    public static final String SERVER_IP = "192.168.137.1";    private static final int PORT = 8282;    public static ManagedChannel getChannel(){        return ManagedChannelBuilder.forAddress(SERVER_IP,PORT)                .usePlaintext().build();    }}public class UserServer {    private UserRpcServerGrpc.UserRpcServerFutureStub futureStub;    public UserServer(ManagedChannel channel){        futureStub = UserRpcServerGrpc.newFutureStub(channel);    }    public void login(String user, String password, final myCallBack callBack){        if ("".equals(user)||user == null||"".equals(password)||password == null)            throw new NullPointerException("user and password no null!");        final loginRequest request = loginRequest                .newBuilder()                .setUsername(user)                .setPassword(password)                .setPower(1)                .build();        ListenableFuture<loginResponse> future = futureStub.login(request);        //构建非阻塞调用,阻塞方式用BlockingStub        Futures.addCallback(future, new FutureCallback<loginResponse>() {            @Override            public void onSuccess(@NullableDecl loginResponse result) {            callBack.onSuccess(result.getState());            }            @Override            public void onFailure(Throwable t) {                callBack.onFailure("网络异常!");            }        }, Executors.newCachedThreadPool());    }}public interface myCallBack {    void onSuccess(Object object);    void onFailure(Object object);}

到这里客户端的gRPC就基本完成了,需要登陆时直接调用login()方法就可以了。
服务端语言自行选择吧,这里就不介绍了,只要是pb支持的语言都可以的。

更多相关文章

  1. Mac OSX Android源码编译-环境搭建、源码下载、源码编译、导入An
  2. 如何实现在 Android(安卓)Studio 上开发系统应用(自带系统签名)
  3. Android(安卓)studio进阶之多语言/图片--国际化
  4. Android(安卓)XML文件链接错误
  5. android中的Plurals(Quantity Strings)类型
  6. Android(安卓)Studio 新建一个简单的Jni-demo,实现了so库的生成与
  7. 【Android】【学习笔记】运行时资源替换-Runtime Resource Overl
  8. Android情景分析之属性服务
  9. android基础2——android工程目录结构

随机推荐

  1. 元素的样式来源 基本选择器/上下文选择器
  2. MyCms 自媒体 CMS 系统 v2.4,灵活的辅助属
  3. SSH爆破:是什么?怎么查?怎么预防?
  4. vscode 常用插件
  5. 在Centos 7上配置阿里云Pouch 镜像方法
  6. 一个简易的课程表和注册表单
  7. 阿里云CentOS 镜像配置方法
  8. 阿里云Centos镜像虚拟机安装方法
  9. 意派Epub360丨年终总结H5,这么做才精彩!
  10. 元素样式来源和选择器