文档章节

gRPC学习笔记

OSC_fly
 OSC_fly
发布于 07/22 11:04
字数 1410
阅读 2
收藏 0

gRPC编程流程

1. gRPC服务的定义:proto文件

proto文件用于定义需要通过gRPC生成的接口,可以理解为接口定义文档

// proto语法声明
syntax = "proto3";

// option声明,相当于Java中的package声明
option go_package = "user";
option java_package = "com.ylifegroup.protobuf";

// 枚举变量定义
enum PhoneType {
    HOME = 0;
    WORK = 1;
    OTHER = 2;
}

// message定义,相当于Java中的class
message ProtobufUser {
    int32 id = 1;               // 参数定义,int32类型参数id,1表示其为第一个参数
    string name = 2;            // 参数定义,string类型参数name,2表示其为第二个参数

        // 相当于Java中的内部类
    message Phone{
        PhoneType phoneType = 1;    // 参数定义,phoneType类型参数phoneType,1表示其为第一个成员变量
        string phoneNumber = 2;     // 参数定义,string类型成员变量phoneNumber,2表示其为第二个成员变量
    }

    repeated Phone phones = 3;  // 参数定义,Phone类型成员变量phones,3表示其为第三个成员变量
}

// message声明,相当于Java中的class声明
message AddPhoneToUserRequest{
    int32 uid = 1;                  // 成员变量定义,int32类型成员变量uid,1表示其为第一个成员变量
    PhoneType phoneType = 2;        // 成员变量定义,PhoneType类型成员变量phoneType,2表示其为第二个成员变量
    string phoneNumber = 3;         // 成员变量定义,string类型成员变量phoneNumber,3表示其为第三个成员变量
}

// message声明,相当于Java中的class声明
message AddPhoneToUserResponse{
    bool result = 1;                // 成员变量定义,bool类型成员变量result,1表示其为第一个成员变量
}

// 服务定义,PhoneService服务
service PhoneService {
    // 服务方法定义,把电话添加到指定联系人的方法,请求参数AddPhoneToUserRequest,返回值AddPhoneToUserResponse
    rpc addPhoneToUser(AddPhoneToUserRequest) returns (AddPhoneToUserResponse);
}

2. 通过构建工具生成服务基类代码-Maven或Gradle

Gradle build文件代码示例:

// 插件声明
apply plugin: 'java'                        // java插件
apply plugin: 'eclipse'                     // eclipse插件
apply plugin: 'com.google.protobuf'         // protobuf插件

repositories {
    // gradle repository配置,相当于maven中配置maven repository
    jcenter()
}

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
    }
}

// 源代码集合
sourceSets {
    main {
        
        // java文件所在位置
        java{
            srcDir 'gen/main/java'
            srcDir 'gen/main/grpc'
        }
        
        // proto文件所在位置
        proto {
            srcDir 'src/main/proto'
        }
    }
}

jar {
    from {
        configurations.runtime.collect {
            it.isDirectory() ? it : zipTree(it)
        }
        
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    
    manifest {
        attributes 'Main-Class': 'com.ylifegroup.protobuf.server.GRpcServer'
    }
}

protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.1.0"
    }
    
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.0.3'
        }
    }
    
    generatedFilesBaseDir = "$projectDir/gen/"
        
    generateProtoTasks {
        all()*.plugins {
            grpc {}
        }
    }
}

// dependencies声明,相当于maven中的依赖声明
dependencies {
    compile 'io.grpc:grpc-netty:1.0.3'				// netty依赖
    compile 'io.grpc:grpc-protobuf:1.0.3'			// protobuf依赖
    compile 'io.grpc:grpc-stub:1.0.3'				// stub依赖
// The production code uses the SLF4J logging API at compile time
    compile 'org.slf4j:slf4j-api:1.7.21'

// Declare the dependency for your favourite test framework you want to use in your tests.
// TestNG is also supported by the Gradle Test task. Just change the
// testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
// 'test.useTestNG()' to your build script.
    testCompile 'junit:junit:4.12'
}

eclipse {
    classpath {
        defaultOutputDir = file('build/eclipse/bin')
    }
}

clean {
    delete protobuf.generatedFilesBaseDir
}

3. 服务端开发

服务端实现类须实现通过构建工具生成的服务基类

A. 服务类的实现

PhoneServiceImp.java

package com.ylifegroup.protobuf.service;

import com.ylifegroup.protobuf.PhoneServiceGrpc;
import com.ylifegroup.protobuf.Phonebook.AddPhoneToUserRequest;
import com.ylifegroup.protobuf.Phonebook.AddPhoneToUserResponse;

import io.grpc.stub.StreamObserver;

public class PhoneServiceImp extends PhoneServiceGrpc.PhoneServiceImplBase{

    /**
     * 自定义的RPC服务方法
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void addPhoneToUser(AddPhoneToUserRequest request, StreamObserver<AddPhoneToUserResponse> responseObserver) {
        // gRPC自动生成的响应对象
        AddPhoneToUserResponse response = null;
        if(request.getPhoneNumber().length() == 11 ){
            System.out.printf("uid = %s , phone type is %s, nubmer is %s\n", request.getUid(), request.getPhoneType(), request.getPhoneNumber());
            // 构建gRPC响应
            response = AddPhoneToUserResponse.newBuilder().setResult(true).build();
        }else{
            System.out.printf("The phone nubmer %s is wrong!\n",request.getPhoneNumber());
            // 构建gRPC响应
            response = AddPhoneToUserResponse.newBuilder().setResult(false).build();
        }

        // 设置gRPC响应
        responseObserver.onNext(response);
        // 返回gRPC响应
        responseObserver.onCompleted();
    }

}

B. 服务发布

GRpcServer.java

package com.ylifegroup.protobuf.server;

import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
import java.util.logging.Logger;
import com.ylifegroup.protobuf.service.PhoneServiceImp;


// gRPC服务端实现代码
public class GRpcServer {
    private static final Logger logger = Logger.getLogger(GRpcServer.class.getName());

    private Server server;

    // 启动gRPC服务器,开启服务
    private void start() throws IOException {
        int port = 50051;           // 服务器端口
        server = ServerBuilder                          // 服务器构建器
                .forPort(port)                          // 指定服务器端口
                .addService(new PhoneServiceImp())      // 配置需要对外发布的服务,这里是否可以一次性发布多个服务?
                .build()                                // 构建服务器对象
                .start();                               // 启动服务器,开启服务
        logger.info("Server started, listening on " + port);
        
        // gRPC服务器关闭的回调钩子函数
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                GRpcServer.this.stop();
                System.err.println("*** server shut down");
            }
        });
    }

    // 关闭gRPC服务器
    private void stop() {
        if (server != null) {
            server.shutdown();
        }
    }

    /**
     * Await termination on the main thread since the grpc library uses daemon threads.
     */
    private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }
    
    public static void main(String[] args) throws IOException, InterruptedException {
        final GRpcServer server = new GRpcServer();
        server.start();                 // 启动gRPC服务器,开启服务
        server.blockUntilShutdown();    // 持续等待,直到服务器被关闭
    }
}

4. 客户端开发

GRpcClient.java

package com.ylifegroup.protobuf.client;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ylifegroup.protobuf.PhoneServiceGrpc;
import com.ylifegroup.protobuf.Phonebook.AddPhoneToUserRequest;
import com.ylifegroup.protobuf.Phonebook.AddPhoneToUserResponse;
import com.ylifegroup.protobuf.Phonebook.PhoneType;

public class GRpcClient {

    private static final Logger logger = Logger.getLogger(GRpcClient.class.getName());

    private final ManagedChannel channel;                                       // 客户端与服务端连接的通道

    private final PhoneServiceGrpc.PhoneServiceBlockingStub blockingStub;       // 客户端代理stub

    /** Construct client connecting to gRPC server at {@code host:port}. */
    // 构建信道,客户端代理,绑定远程IP,服务端口
    public GRpcClient(String host, int port) {
        ManagedChannelBuilder<?> channelBuilder = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true);
        channel = channelBuilder.build();           // 信道构建
        blockingStub = PhoneServiceGrpc.newBlockingStub(channel);   // 构建客户端代理
    }

    // 等待5s, 5s后关闭客户端连接
    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    /** add phone to user. */
    public void addPhoneToUser(int uid, PhoneType phoneType, String phoneNubmer) {
        logger.info("Will try to add phone to user " + uid);
        // 构建gRPC请求对象
        AddPhoneToUserRequest request = AddPhoneToUserRequest.newBuilder().setUid(uid).setPhoneType(phoneType)
                .setPhoneNumber(phoneNubmer).build();
        AddPhoneToUserResponse response;
        try {
            // 发送请求,获取响应
            response = blockingStub.addPhoneToUser(request);
        } catch (StatusRuntimeException e) {
            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
            return;
        }

        // 获取响应结果
        logger.info("Result: " + response.getResult());
    }

    public static void main(String[] args) throws Exception {
        // 创建gRPC连接客户端,指定远程IP及端口
        GRpcClient client = new GRpcClient("localhost", 50051);
        try {
            client.addPhoneToUser(1, PhoneType.WORK, "13888888888");
        } finally {
            // 关闭客户端连接
            client.shutdown();
        }
    }
}

参考文档

gRPC简单实例及流程分析

gRPC初体验

通过实例带你学习RPC框架gRPC

© 著作权归作者所有

共有 人打赏支持
OSC_fly
粉丝 1
博文 23
码字总数 6264
作品 0
通州
程序员
[笔记] consul用grpc做健康检查注意点

先上个代码片段开胃 protobuf写一个Health服务: https://github.com/grpc/grpc/blob/master/doc/health-checking.md package必须写成 ... consul源代码里写死了调用grpc的health check http......

疯狂的小企鹅
04/21
0
0
mac下grpc(golang server + php client)实践

目前微服务这么流行,RPC框架也是百花齐放,本文讲述一下mac下grpc的开发环境搭建,其中server端使用golang,客户端使用php。 服务端 golang grpc安装 这里列出了一个参考,由于grpc在githu...

陈晓风
07/01
0
0
gRPC Windows编译应用

gRPC Windows编译 从github上clone出来后进行cmake的编译,参考上面的文档,需要注意的点: 必须安装所有的依赖,包括Perl,Go,YASM,Git,CMake 不要使用--recursive来递归clone,因为墙的...

水海云
06/20
0
0
grpc| python 实战 grpc

date: 2018-5-15 22:12:32 title: grpc| python 实战 grpc description: 只要代码可以跑起来, 很多难题都会迎刃而解. so, keep coding and stay hungry. 之前用 swoole 写 server 时就接触过...

daydaygo
05/16
0
0
Spring Boot 使用 gRPC 轻松调用远程方法

gRPC 简介 gRPC 是一个现代开源的高性能 RPC 框架,可以在任何环境下运行。它可以有效地将数据中心内和跨数据中心的服务与可插拔支持进行负载均衡、跟踪、健康检查和认证。它也适用于分布式计...

Anoyi
04/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

python3.6 取整除法

python3.6 中取整除法运算逻辑如下: d 非零,那么商 q 满足这样的关系: a = qd + r ,且0 ≤ r n1=7//3#7 = 3*2 +1n2=-6.1//3#-7 = 3*(-3)+2'{},{}'.format(n1,n2) 从运行结果可以...

colinux
24分钟前
3
0
阶段总结——用虚拟机搭建一个高可用负载均衡集群架构

[toc] linux基本知识已经介绍完,现有一个业务需要操作,通过对这个项目的操作,可以复习、总结、巩固之前的知识点; ** 用13台虚拟机搭建一个高可用负载均衡集群架构出来,并运行三个站点,...

feng-01
27分钟前
0
0
mysql 设置utf8字符集 (CentOS)

1.查看数据库及mysql应用目前使用的编码方式 (1)链接mysql 客户端 (2)执行:status 结果: 2.修改mysql 应用的字符编码(server characterset ) (1)打开配置文件:vim /etc/mysql/my...

qimh
28分钟前
0
0
windows无法格式化u盘解决方法

1。点开始-运行-输入cmd-format f: /fs: fat32 (这里f:是指U盘所在盘符) 这个格式化会很慢 请耐心等待

大灰狼wow
39分钟前
0
0
MySql 8.0连接失败

原来,MySql 8.0.11 换了新的身份验证插件(caching_sha2_password), 原来的身份验证插件为(mysql_native_password)。而客户端工具Navicat Premium12 中找不到新的身份验证插件(caching_s...

放飞E梦想O
56分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部