电子商务网站推广的方法有哪些,爱站网站排行榜,重庆建设人才网,免费行情软件app网站红色SpringBoot基于gRPC进行RPC调用 一、gRPC1.1 什么是gRPC#xff1f;1.2 如何编写proto1.3 数据类型及对应关系1.4 枚举1.5 数组1.6 map类型1.7 嵌套对象 二、SpringBoot gRPC2.1 工程目录2.2 jrpc-api2.2.1 引入gRPC依赖2.2.2 编写 .proto 文件2.2.3 使用插件机制生产proto相关… SpringBoot基于gRPC进行RPC调用 一、gRPC1.1 什么是gRPC1.2 如何编写proto1.3 数据类型及对应关系1.4 枚举1.5 数组1.6 map类型1.7 嵌套对象 二、SpringBoot gRPC2.1 工程目录2.2 jrpc-api2.2.1 引入gRPC依赖2.2.2 编写 .proto 文件2.2.3 使用插件机制生产proto相关文件 2.2 jrpc-server2.2.1 引入 jrpc-api 依赖2.2.2 编写impl2.2.3 编写Config2.2.4 yaml 2.3 jrpc-client2.3.1 引入 jrpc-api 依赖2.3.2 编写config2.3.3 yaml2.3.4 测试验证 一、gRPC
1.1 什么是gRPC In gRPC, a client application can directly call a method on a server application on a different machine as if it were a local object, making it easier for you to create distributed applications and services. As in many RPC systems, gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client side, the client has a stub (referred to as just a client in some languages) that provides the same methods as the server. 在 gRPC 中客户端应用程序可以直接调用服务器应用程序上的方法 在另一台机器上就好像它是本地对象一样使你更容易 创建分布式应用程序和服务。与许多 RPC 系统一样gRPC 是 基于定义服务的思想指定可以 使用其参数和返回类型进行远程调用。在服务器端 server 实现此接口并运行 gRPC 服务器来处理客户端调用。 在客户端客户端有一个存根在某些客户端中称为客户端 languages它提供与服务器相同的方法。
gRPC 客户端和服务器可以在各种 环境 - 从 Google 内部的服务器到您自己的桌面 - 并且可以 用 gRPC 支持的任何语言编写。因此例如您可以轻松地 在 Java 中创建一个 gRPC 服务器客户端使用 Go、Python 或 Ruby。另外 最新的 Google API 将具有其接口的 gRPC 版本让您 轻松将 Google 功能构建到您的应用程序中。
gRPC 使用 proto buffers 作为服务定义语言编写 proto 文件即可完成服务的定义。 1.2 如何编写proto
syntax proto3;option java_multiple_files true;
// 生成位置
option java_package com.lizq.jrpc.api;
option java_outer_classname UserService;package user;service User {rpc SayHello (UserRequest) returns (UserResponse) {}
}message UserRequest {string name 1;int32 age 2;string addr 3;
}message UserResponse {string name 1;int32 age 2;string addr 3;OtherMsg otherMsg 4;mapstring, string otherMap 5;// 嵌套对象message OtherMsg {string ext1 1;string ext2 2;}
}syntax proto3;指定使用的protobuf版本option java_multiple_files true;如果为 false则只会.java为此文件生成一个.proto文件以及所有 Java 类/枚举/等。为顶级消息、服务和枚举生成的将嵌套在外部类中。如果为 true.java将为每个 Java 类/枚举/等生成单独的文件。为顶级消息、服务和枚举生成并且为此.proto文件生成的包装 Java 类将不包含任何嵌套类/枚举/等。 如果不生成 Java 代码则此选项无效。package user;定义本服务的包名避免不同服务相同消息类型产生冲突option java_package com.lizq.jrpc.api;生成java文件包名option java_outer_classname UserService;生成java文件类名称。如果文件中没有明确 java_outer_classname指定.proto则将通过将.proto文件名转换为驼峰式来构造类名因此 foo_bar.proto变为FooBar.javamessage UserResponse定义服务的接口名称rpc SayHello (UserRequest) returns (UserResponse) {}远程调用方法名参数及响应类型message XXXXX{}定义数据类型
1.3 数据类型及对应关系
.proto类型NotesC TypeJava/KotlinPythondoubledoubledoublefloatfloatfloatfloatfloatint32使用可变长度编码。对负数进行编码效率低下——如果您的字段可能有负值请改用 sint32。int32intintint64使用可变长度编码。对负数进行编码效率低下——如果您的字段可能有负值请改用 sint64。int64longint/longuint32使用可变长度编码。uint32intint/longuint64使用可变长度编码。uint64longint/longsint32使用可变长度编码。带符号的 int 值。这些比常规 int32 更有效地编码负数。int32intintsint64使用可变长度编码。带符号的 int 值。这些比常规 int64 更有效地编码负数。int64longint/longfixed32总是四个字节。如果值通常大于 228则比 uint32 更有效uint32intint/longfixed64总是八个字节。如果值通常大于 256则比 uint64 更有效。uint64longint/longsfixed32总是四个字节。int32intintsfixed64总是八个字节。int64longint/longboolboolbooleanboolstring字符串必须始终包含 UTF-8 编码或 7 位 ASCII 文本并且不能超过 232。stringStringstr/unicodebytes可能包含不超过 2 32的任意字节序列。stringByteStringstr (Python 2)、bytes (Python 3)
1.4 枚举
enum Sex {NONE 0;MAN 1;WOMAN 2;
}message UserRequest {string name 1;int32 age 2;string addr 3;Sex sex 4;
}**注意**第一个枚举的值必须为0因为0 是默认值0 必须是第一个保持和proto2 兼容
1.5 数组
使用 repeated 关键字来定义数组。
message UserRequest {string name 1;int32 age 2;string addr 3;Sex sex 4;// 定义一个数组repeated string cellphones 5;
}1.6 map类型
在开发的过程中经常需要使用关联字段很自然的想到使用mapprotobuf也提供了map的类型。
message UserResponse {string name 1;mapstring, string otherMap 2;
}注意 map 字段前面不能是repeated
1.7 嵌套对象
message UserResponse {string name 1;int32 age 2;string addr 3;OtherMsg otherMsg 4;mapstring, string otherMap 5;// 嵌套对象message OtherMsg {string ext1 1;string ext2 2;}
}二、SpringBoot gRPC
2.1 工程目录 2.2 jrpc-api
2.2.1 引入gRPC依赖
dependencygroupIdio.grpc/groupIdartifactIdgrpc-all/artifactIdversion1.28.1/version
/dependency2.2.2 编写 .proto 文件
syntax proto3;option java_multiple_files true;
// 生成位置
option java_package com.lizq.jrpc.api;
option java_outer_classname UserService;package user;service User {rpc SayHello (UserRequest) returns (UserResponse) {}
}message UserRequest {string name 1;int32 age 2;string addr 3;
}message UserResponse {string name 1;int32 age 2;string addr 3;OtherMsg otherMsg 4;mapstring, string otherMap 5;// 嵌套对象message OtherMsg {string ext1 1;string ext2 2;}
}2.2.3 使用插件机制生产proto相关文件
在 jrpc-api pom.xml 中添加如下
buildextensionsextensiongroupIdkr.motd.maven/groupIdartifactIdos-maven-plugin/artifactIdversion1.6.2/version/extension/extensionspluginsplugingroupIdorg.xolstice.maven.plugins/groupIdartifactIdprotobuf-maven-plugin/artifactIdversion0.6.1/versionconfiguration!--lt;!ndash; ${os.detected.classifier} 变量由${os.detected.name} 和 ${os.detected.arch} 组成--protocArtifactcom.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}/protocArtifactpluginIdgrpc-java/pluginIdpluginArtifactio.grpc:protoc-gen-grpc-java:1.28.1:exe:${os.detected.classifier}/pluginArtifact!--protoSourceRoot 默认src/main/proto--protoSourceRootsrc/main/proto/protoSourceRoot/configurationexecutionsexecutiongoalsgoalcompile/goalgoalcompile-custom/goal/goals/execution/executions/plugin/plugins
/build执行命令生产proto相关文件 将生成的文件拷贝到工程中如下 2.2 jrpc-server
jrpc-server 为 springboot 项目。
2.2.1 引入 jrpc-api 依赖
dependencygroupIdcom.example/groupIdartifactIdjrpc-api/artifactIdversion1.0.0-SNAPSHOT/version
/dependency2.2.2 编写impl
Service
public class UserServiceImpl extends UserGrpc.UserImplBase {Overridepublic void sayHello(UserRequest request, StreamObserverUserResponse responseObserver) {MapString, String otherMap new HashMap();otherMap.put(test, testmap);UserResponse response UserResponse.newBuilder().setName(server: request.getName()).setAddr(server: request.getAddr()).setAge(request.getAge()).setOtherMsg(UserResponse.OtherMsg.newBuilder().setExt1(ext1).setExt2(ext2).build()).putAllOtherMap(otherMap).build();responseObserver.onNext(response);responseObserver.onCompleted();}
}2.2.3 编写Config
Configuration
public class GrpcServerConfiguration {Value(${grpc.server-port})private int port;Beanpublic Server server() throws Exception {System.out.println(Starting gRPC on port {}. port);// 构建服务端ServerBuilder? serverBuilder ServerBuilder.forPort(port);// 添加需要暴露的接口this.addService(serverBuilder);// startServer server serverBuilder.build().start();System.out.println(gRPC server started, listening on {}. port);// 添加服务端关闭的逻辑Runtime.getRuntime().addShutdownHook(new Thread(() - {System.out.println(Shutting down gRPC server.);if (server ! null) {// 关闭服务端server.shutdown();}System.out.println(gRPC server shut down successfully.);}));if (server ! null) {// 服务端启动后直到应用关闭都处于阻塞状态方便接收请求server.awaitTermination();}return server;}Autowiredprivate UserServiceImpl userService;/*** 添加需要暴露的接口* param serverBuilder*/private void addService(ServerBuilder? serverBuilder) {serverBuilder.addService(userService);}
}
2.2.4 yaml
server:port: 8081
spring:application:name: spring-boot-jrpc-server
grpc:server-port: 180812.3 jrpc-client
2.3.1 引入 jrpc-api 依赖
dependencygroupIdcom.example/groupIdartifactIdjrpc-api/artifactIdversion1.0.0-SNAPSHOT/version
/dependency2.3.2 编写config
Configuration
public class GrpcClientConfiguration {Value(${server-host})private String host;/*** gRPC Server的端口*/Value(${server-port})private int port;Beanpublic ManagedChannel managedChannel() {// 开启gRPC客户端ManagedChannel managedChannel ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();System.out.println(gRPC client started, server address: host , port);// 添加客户端关闭的逻辑Runtime.getRuntime().addShutdownHook(new Thread(() - {try {// 调用shutdown方法后等待1秒关闭channelmanagedChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);System.out.println(gRPC client shut down successfully.);} catch (InterruptedException e) {e.printStackTrace();}}));return managedChannel;}Autowiredprivate ManagedChannel managedChannel;Beanpublic UserGrpc.UserBlockingStub userBlockingStub(ManagedChannel channel) {// 通过channel获取到服务端的stubreturn UserGrpc.newBlockingStub(managedChannel);}
}2.3.3 yaml
server:port: 8080
spring:application:name: spring-boot-jrpc-client# 本地测试
server-host: 127.0.0.1
server-port: 180812.3.4 测试验证
RestController(/user)
public class UserController {Autowiredprivate UserGrpc.UserBlockingStub userBlockingStub;GetMapping(/sayHello)public String sayHello(String name, String addr, int age) {UserRequest request UserRequest.newBuilder().setName(name).setAddr(addr).setAge(age).build();UserResponse response;try {response userBlockingStub.sayHello(request);} catch (StatusRuntimeException e) {e.printStackTrace();return e.getMessage();}return response.toString();}
}浏览器访问http://localhost:8080/user/sayHello?nametestaddraddrage99 返回
name: server:test age: 99 addr: server:addr otherMsg { ext1: ext1 ext2: ext2 } otherMap { key: test value: testmap }