问道gRPC_v1.0.0

文章目录

      • 简介
        • 诞生
        • 主要用途
      • 基础
        • 数据结构
        • gRPC如何调用
      • gRPC与微服务
        • 与SpringCloud整合
          • 预配置
          • 编码
          • 实现&&配置
          • 调用RPC,执行客户端代码,即可调用
          • 新增字段
          • 资源消耗
        • 报错
          • 服务提供者不在线

文件名称 版本号 作者 qq 版本
问道gRPC v1.0.0 学生宫布 8416837 net-devh-grpc.version 2.7.0.RELEASE
grpc.version 1.29.0
protobuf.version 3.4.0

简介

诞生

Google的孩子

主要用途

进程通信

基础

  • 检测是否安装protobuf
go version
protoc --version
  • 下载 protoc-3.10.1-win64.zip
  • 将安装目录/bin配置到Win环境变量
    在这里插入图片描述

数据结构

数据格式Protobuf
查看我写的protobuf教程
一个简单的proto文件

syntax = 'proto3';

package proto;

message Human {
	int32 age = 1;
	string name = 2;
	int32 sex = 3;
}

安装编译插件

go get -u github.com/golang/protobuf/protoc-gen-go

问道gRPC_v1.0.0_第1张图片
进入该文件目录使用gitbash编译该文件
protoc --go_out=. --python_out=. fruit.proto
编译完毕,说明插件安装成功:
在这里插入图片描述

gRPC如何调用

grpc提供的原生接口服务无法被http模式访问

  • 在golang代码里调用 查看教程
  • 查看GitHub代码

gRPC与微服务

  • 服务消费模式,与FeignClient、Dubbo RPC模式接近
  • 路由表 来自注册中心
  • 负载均衡 软负载 根据路由表轮询、一致性hash、活跃度等

与SpringCloud整合

  • 基础→ Protocol Buffers教程
  • 进入安装Nacos教程,gRPC服务注册到Nacos
预配置
  • pom.xml 核心配置节选
			<plugin>
                <groupId>org.xolstice.maven.pluginsgroupId>
                <artifactId>protobuf-maven-pluginartifactId>
                <version>0.5.0version>
                <configuration>
                    <protocArtifact>
                        com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
                    protocArtifact>
                    <pluginId>grpc-javapluginId>

                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}pluginArtifact>
                    
                    <protoSourceRoot>${project.basedir}/src/main/protoprotoSourceRoot>
                    
                    
                    <outputDirectory>${project.basedir}/src/main/javaoutputDirectory>
                    
                    <clearOutputDirectory>falseclearOutputDirectory>

                configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compilegoal>
                            <goal>compile-customgoal>
                        goals>
                    execution>
                executions>
            plugin>
  • 引入插件,可能报红↓
    问道gRPC_v1.0.0_第2张图片
    引入变量就不会报红了↓
<properties>
        <grpc.version>1.29.0grpc.version>
        <os.detected.classifier>windows-x86_64os.detected.classifier>
        <net-devh-grpc.version>2.7.0.RELEASEnet-devh-grpc.version>
    properties>
编码
  • 新建目录src\main\proto
    问道gRPC_v1.0.0_第3张图片

  • 编辑Human.proto文件

syntax = "proto3"; // 版本号。与proto2差别不大
option java_package = "test.pro.domain";
option java_outer_classname = "HumanDomain";

// 简单定义一个rpc服务和一个接口 定义了接口的输入输出 而输入输出都在下述结构体
service TheFirstRpc {
    rpc SayHello ( HelloParams) returns ( Human ) {}
}

message HelloParams { // 类结构体
    string name = 1;
}
message Human { // 类结构体
    int32 id = 1; // 结构体属性
    int32 sex = 2; // 数字作为key,省空间。不一定要连续
    string age = 3;
}

实现&&配置
  • 引入protobuf依赖↓
    父项目
<properties>
        <protobuf.version>3.4.0protobuf.version>
... ...
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.google.protobufgroupId>
                <artifactId>protobuf-javaartifactId>
				<version>${protobuf.version}version>
            dependency>
            <dependency>
            <groupId>io.grpcgroupId>
            <artifactId>grpc-allartifactId>
            <version>${grpc.version}version>
        dependency>

子项目

<dependency>
            <groupId>com.google.protobufgroupId>
            <artifactId>protobuf-javaartifactId>
        dependency>
        <dependency>
            <groupId>io.grpcgroupId>
            <artifactId>grpc-allartifactId>
        dependency>
        
  • 编译 找到Maven插件
    问道gRPC_v1.0.0_第4张图片
    执行插件compile && compile-custom命令,或自己打命令(不推荐)
    若报错:在这里插入图片描述
    说明缺少依赖

编译成功
在这里插入图片描述
问道gRPC_v1.0.0_第5张图片
这样proto就变成了Java类,以备后续使用

  • 服务端实现RPC
    服务提供者配置
grpc:
  server:
    port: 9080 # 不配置默认9090

服务端引入依赖包

<net-devh-grpc.version>2.7.0.RELEASEnet-devh-grpc.version>

<dependency>
                <groupId>net.devhgroupId>
                <artifactId>grpc-client-spring-boot-starterartifactId>
                <version>${net-devh-grpc.version}version>
            dependency>
            <dependency>
                <groupId>net.devhgroupId>
                <artifactId>grpc-server-spring-boot-starterartifactId>
                <version>${net-devh-grpc.version}version>
            dependency>

前提是服务端和客户端都引入RPC相关Java类
上一步只是编译了RPC结构,并未实现它。因此,可以在服务端(提供者)编写实现代码,以备客户端(消费者)调用。
注意:有些类的名字改成你自己的。这些类主要与proto关联。

package test.rpc;

/**
 * 功能:rpc实现
 *
 * @author: cc
 * @qq: 8416837
 * @date: 2020/5/17 15:48
 */

import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import test.pro.domain.HumanDomain;
import test.pro.domain.TheFirstRpcGrpc;

@Slf4j
@GrpcService
public class HelloService extends TheFirstRpcGrpc.TheFirstRpcImplBase {
	@Override
	public void sayHello(HumanDomain.HelloParams request, StreamObserver<HumanDomain.Human> responseObserver) {
		String name = request.getName();
		log.debug("{} === {}", "[请求参数]", request);
		final HumanDomain.Human.Builder replyBuilder = HumanDomain.Human.newBuilder().setSex(1).setAge(18).setName(name);
		responseObserver.onNext(replyBuilder.build());
		responseObserver.onCompleted();
	}
}

  • 客户端配置文件
# grpc
grpc:
  client:
    TheFirstRpc: # 服务名称
      address: static://localhost:9080
      negotiationType: plaintext
    # 服务
    # GLOBAL:
      # address: static://localhost:9080 // 服务端的端口号
      # negotiation-type: plaintext
  • 客户端代码,节选,注意区分:
	@GrpcClient("TheFirstRpc")
	private TheFirstRpcGrpc.TheFirstRpcBlockingStub theFirstRpcBlockingStub;
	@GetMapping("/grpc/{name}")
	public Object sayHello(@PathVariable("name") String name) throws InterruptedException {

		//		服务端默认ip是微服务ip,端口是9090
		HumanDomain.Human response = theFirstRpcBlockingStub.sayHello(HumanDomain.HelloParams.newBuilder().setName(name).build());
		String resStr = response.toString();
		return resStr;
	}
调用RPC,执行客户端代码,即可调用

使用REST API触发客户端调用服务端RPC,即可完成调用,原理见上述代码
把RPC调用结果toString后再返回,避免REST Json返回响应时报错。按上述代码,实操调用成功。

  • 调用成功
    问道gRPC_v1.0.0_第6张图片
新增字段

在proto新增字段之后,执行命令↓
问道gRPC_v1.0.0_第7张图片

资源消耗
  • 开启grpc Nacos通讯后,Nacos消耗运存情况:
    在这里插入图片描述
    运存占用不多,持续增长中,但是吃cpu,nacos 是1.2.1, 可能是bug, 多方运行核实一下,例如普通的不带grpc的微服务会不会出现这种大量吃cpu的情况

报错

服务提供者不在线

报错:

io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
	at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:244) ~[grpc-stub-1.29.0.jar:1.29.0]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]

解决办法:开启服务

你可能感兴趣的:(技术栈-微服务-gRPC,gRPC,微服务通信,gRPC实战,SpringCloud,gRPC负载均衡)