hdsyscms企业建站系统,php做网站需要什么技术,wordpress很卡,沂水住房与城乡建设局网站文章目录 RPC简介gPRC简介protobuf1.文件编写规范2.字段类型3.定义服务(Services) 在Spring Boot中使用grpc1.父工程pom配置2.grpc-api模块2.1.pom配置2.2.proto文件编写2.3.把proto文件编译成class文件 3.grpc-server模块3.1.pom文件和application.yaml3.2.实现grpc-api模块的… 文章目录 RPC简介gPRC简介protobuf1.文件编写规范2.字段类型3.定义服务(Services) 在Spring Boot中使用grpc1.父工程pom配置2.grpc-api模块2.1.pom配置2.2.proto文件编写2.3.把proto文件编译成class文件 3.grpc-server模块3.1.pom文件和application.yaml3.2.实现grpc-api模块的接口3.3.启动服务 4.grpc-client模块4.1.pom文件和application.yaml4.2.创建http接口调用grpc-server4.3.启动服务测试 项目配套代码 RPC简介
RPC简介:
RPCRemote Procedure Call是一种用于实现分布式系统中不同节点之间通信的协议。它允许一个节点称为客户端调用另一个节点称为服务器上的远程方法就像调用本地方法一样。RPC的目标是隐藏底层通信细节使得远程调用过程对开发者透明。在RPC中客户端通过发送请求消息给服务器来调用远程方法服务器接收到请求后执行相应的方法并将结果返回给客户端。RPC可以跨越不同的网络和操作系统使得分布式系统中的不同节点能够进行高效的通信和协作。RPC的实现方式有多种常见的包括基于HTTP协议的RESTful API、基于TCP/IP协议的Socket编程、以及基于消息队列的异步通信等。不同的实现方式有不同的特点和适用场景开发者可以根据具体需求选择合适的RPC框架或协议。
gPRC简介
gprc官网 https://grpc.io/docs/ gRRC的g代表google,gRPC最初是由Google创建的,是一个现代的开源高性能远程过程调用(RPC)框架可以在任何环境中运行。它可以高效地连接数据中心内和跨数据中心的服务支持负载平衡、跟踪、运行状况检查和身份验证。它也适用于分布式计算的最后一英里将设备、移动应用程序和浏览器连接到后端服务。
gRPC的特性 看官方文档的介绍有以下几点特性
grpc可以跨语言使用。支持多种语言 支持C、Java、Go、Python、Ruby、C#、Node.js、Android - Java、Objective-C、PHP等编程语言基于 IDL ( 接口定义语言Interface Define Language)文件定义服务通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub通信协议基于标准的 HTTP/2 设计支持·双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性这些特性使得 gRPC - 在移动端设备上更加省电和节省网络流量序列化支持 PBProtocol Buffer和 JSONPB - 是一种语言无关的高性能序列化框架基于 HTTP/2 PB, 保障了 RPC 调用的高性能。
性能 gRPC消息使用一种有效的二进制消息格式protobuf进行序列化。Protobuf在服务器和客户机上的序列化非常快。Protobuf序列化后的消息体积很小能够有效负载在移动应用程序等有限带宽场景中显得很重要。与采用文本格式的JSON相比采用二进制格式的protobuf在速度上可以达到前者的5倍Auth0网站所做的性能测试结果显示protobuf和JSON的优势差异在Java、Python等环境中尤为明显。下图是Auth0在两个Spring Boot应用程序间所做的对比测试结果。
gRPC是为HTTP/2而设计的它是HTTP的一个主要版本与HTTP 1.x相比具有显著的性能优势二进制框架和压缩。HTTP/2协议在发送和接收方面都很紧凑和高效。通过单个TCP连接复用多个HTTP/2调用。多路复用消除了线头阻塞。
代码生成
gRPC框架都为代码生成提供了一流的支持。gRPC开发的核心文件是*.proto文件 它定义了gRPC服务和消息的约定。根据这个文件gRPC框架将生成服务基类消息和完整的客户端代码。通过在服务器和客户端之间共享*.proto文件可以从端到端生成消息和客户端代码。客户端的代码生成消除了客户端和服务器上的重复消息并为您创建了一个强类型的客户端。无需编写客户端代码可在具有许多服务的应用程序中节省大量开发时间。
严格的规范
不存在具有JSON的HTTP API的正式规范。开发人员不需要讨论URLHTTP动词和响应代码的最佳格式。想想是用Post还是Get好使用Get还是用Put好一想到有选择恐惧症的你是不是又开了纠结然后浪费了大量的时间该gRPC规范是规定有关gRPC服务必须遵循的格式。gRPC消除了争论并节省了开发人员的时间因为gPRC在各个平台和实现之间是一致的。
流
HTTP/2为长期的实时通信流提供了基础。gRPC通过HTTP/2为流媒体提供一流的支持。gRPC服务支持所有流组合 一元没有流媒体 简单rpc 这就是一般的rpc调用一个请求对象对应一个返回对象。客户端发起一次请求服务端响应一个数据即标准RPC通信。 (rpc Method(request) returns (response)){} 服务器流RPC是指客户端发一个对象服务器返回一个Stream流式消息(rpc Method(request) returns (stream response)){} 客户端流RPC,客户端发一个流给服务器,服务器返回一个对象(rpc Method(stream request) returns ( response)){} 双向流媒体双向流式rpc 结合客户端流式rpc和服务端流式rpc可以传入多个对象返回多个响应对象。应用场景聊天应用。(rpc Method(stream request) returns (stream response)){}
gRPC非常适合以下场景
微服务gRPC设计为低延迟和高吞吐量通信。gRPC非常适用于效率至关重要的轻型微服务。点对点实时通信 gRPC对双向流媒体提供出色的支持。gRPC服务可以实时推送消息而无需轮询。多语言混合开发环境 gRPC工具支持所有流行的开发语言使gRPC成为多语言开发环境的理想选择。网络受限环境使用Protobuf一种轻量级消息格式序列化gRPC消息。gRPC消息始终小于等效的JSON消息。
protobuf
官方文档 https://protobuf.dev/programming-guides/proto3/
protobuf 即 Protocol Buffers是一种轻便高效的结构化数据存储格式与语言、平台无关可扩展可序列化。Protocol Buffers 是一种灵活高效自动化机制的结构数据序列化方法可类比 XML但是比 XML 更小3 ~ 10倍、更快20 ~ 100倍、更为简单。json、xml都是基于文本格式protobuf 是以二进制方式存储的占用空间小但也带来了可读性差的缺点。protobuf 在通信协议和数据存储等领域应用广泛。例如著名的分布式缓存工具 Memcached 的 Go 语言版本groupcache 就使用了 protobuf 作为其 RPC 数据格式。Protobuf 在 .proto 定义需要处理的结构化数据可以通过 protoc 工具将 .proto 文件转换为C、Golang、Java、Python 等多种语言的代码兼容性好易于使用。
1.文件编写规范
syntax proto3;
package main;message User {string name 1;bool enabled 2;repeated int32 roles 3;
}逐行解读user.proto
protobuf 有2个版本默认版本是 proto2如果需要 proto3则需要在非空非注释第一行使用 syntax “proto3” 标明版本。package即包名声明符是可选的用来防止不同的消息类型有命名冲突。消息类型 使用 message 关键字定义User 是类型名name, enabled, roles 是该类型的 3 个字段类型分别为 string, bool 和 []int32。字段可以是标量类型也可以是合成类型。每个字段的修饰符默认是 singular一般省略不写repeated 表示字段可重复即用来表示数组类型。每个字符 后面的数字称为标识符每个字段都需要提供一个唯一的标识符。标识符用来在消息的二进制格式中识别各个字段一旦使用就不能够再改变标识符的取值范围为 [1, 2^29 - 1] 。.proto 文件可以写注释单行注释 //多行注释 /* … */ 一个 .proto 文件中可以写多个消息类型即对应多个结构体(struct)。
2.字段类型
基础字段类型
枚举(Enumerations) 举类型适用于提供一组预定义的值选择其中一个。例如我们将用户状态定义为枚举类型。 enum Status {ENABLED 0;DISABLED 1;}message User {string name 1;string password2;Status status 3;
}嵌入其它消息体 可以再message里面嵌套message,和java内嵌一个原理
// 返回结果
message LoginResultVo {Result result 1; // 状态信息UserInfo data 2; // 数据
}
message Result {int32 code 1;string msg 2;
}3.定义服务(Services)
如果消息类型是用来远程通信的(Remote Procedure Call, RPC)可以在 .proto 文件中定义 RPC 服务接口。例如我们定义了一个名为 UserServiceApi 的 RPC 服务提供了login接口入参是 LoginInfoDTO 类型返回类型是 LoginResultVo 类型
service UserServiceApi {rpc login (LoginInfoDTO) returns (LoginResultVo);
}// 请求参数
message LoginInfoDTO {string username 1;string password2;
}在Spring Boot中使用grpc
创建一个聚合项目,分三个子模块
grpc-api: 封装需要远程调用的API和dubbo类似grpc-server: 远程调用的服务提供者grpc-client: 客户端调用者
1.父工程pom配置 modulesmodulegrpc-api/modulemodulegrpc-server/modulemodulegrpc-client/module/modulespropertiesjava.version1.8/java.version!-- grpc依赖--grpc.version1.53.0/grpc.versiongrpc.spring.boot.version2.14.0.RELEASE/grpc.spring.boot.versionprotoc.version3.22.0/protoc.versionprotobuf.java.version3.21.7/protobuf.java.version!--grpc编译插件--protobuf.plugin.version0.6.1/protobuf.plugin.versionos.maven.plugin.version1.7.1/os.maven.plugin.version!-- 自定义grpc api模块版本--grpc-api.version0.0.1-SNAPSHOT/grpc-api.version/properties!--统一管理版本号--dependencyManagementdependencies!-- gRpc 依赖 --dependencygroupIdio.grpc/groupIdartifactIdgrpc-bom/artifactIdversion${grpc.version}/versiontypepom/typescopeimport/scope/dependency!-- gRpc Protobuf --dependencygroupIdio.grpc/groupIdartifactIdgrpc-protobuf/artifactIdversion${grpc.version}/version/dependency!-- gRpc Stub --dependencygroupIdio.grpc/groupIdartifactIdgrpc-stub/artifactIdversion${grpc.version}/version/dependency!-- protobuf-java --dependencygroupIdcom.google.protobuf/groupIdartifactIdprotobuf-java/artifactIdversion${protobuf.java.version}/version/dependency!-- gRpc Server --dependencygroupIdnet.devh/groupIdartifactIdgrpc-server-spring-boot-starter/artifactIdversion${grpc.spring.boot.version}/version/dependency!-- gRpc Client --dependencygroupIdnet.devh/groupIdartifactIdgrpc-client-spring-boot-starter/artifactIdversion${grpc.spring.boot.version}/version/dependencydependencygroupIdcom.ljm.boot.grpc/groupIdartifactIdgrpc-api/artifactIdversion${grpc-api.version}/version/dependency/dependencies/dependencyManagement2.grpc-api模块
2.1.pom配置
.proto文件编译成java文件需要引入已下三个依赖和两个插件 dependenciesdependencygroupIdcom.google.protobuf/groupIdartifactIdprotobuf-java/artifactId/dependencydependencygroupIdio.grpc/groupIdartifactIdgrpc-protobuf/artifactId/dependencydependencygroupIdio.grpc/groupIdartifactIdgrpc-stub/artifactId/dependency/dependenciesbuildextensions!-- OS 插件 --extensiongroupIdkr.motd.maven/groupIdartifactIdos-maven-plugin/artifactIdversion${os.maven.plugin.version}/version/extension/extensionspluginsplugingroupIdorg.xolstice.maven.plugins/groupIdartifactIdprotobuf-maven-plugin/artifactIdversion${protobuf.plugin.version}/versionconfigurationpluginIdgrpc-java/pluginIdprotoSourceRootsrc/main/proto/protoSourceRootprotocArtifactcom.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}/protocArtifactpluginArtifactio.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}/pluginArtifact/configurationexecutionsexecutiongoalsgoalcompile/goalgoalcompile-custom/goal/goals/execution/executions/plugin/plugins/build2.2.proto文件编写 第一步 在src.main目录下新建proto目录第二步 在commom包下面新建result.proto文件封装通用的响应信息第三部 在user包下面新建user.proto文件封装用户相关的接口信息
result.proto文件内容如下
syntax proto3;package api.common;option java_package com.ljm.boot.grpc.api.common; //包名
option java_outer_classname ResultProto; //编译后的类名
option java_multiple_files true; //生成多个文件message Result {bool ok 1; // 是否成功int32 code 2; // 状态码string message 3; // 消息
}user.proto文件如下 syntax proto3;package api.login;import api/common/result.proto; //引入common包下的result.proto模块 api/common路径对应result.proto里的 package api.common;option java_package com.ljm.boot.grpc.api.user; //包名
option java_outer_classname UserServiceProto; //编译后的类名
option java_multiple_files true; //生成多个文件// 接口类
service UserServiceApi {rpc login (LoginInfoDTO) returns (LoginResultVo);
}// 请求参数
message LoginInfoDTO {string username 1;string password2;
}// 返回结果
message LoginResultVo {api.common.Result result 1; // 状态信息UserInfo data 2; // 数据
}message UserInfo {string token 1; // token信息int32 id 2; // 用户Id
}2.3.把proto文件编译成class文件
在grpc-api目录下执行install命令
cd grpc-api
mvn clean install 看到如上信息就可以去target目录下找编译后的文件 和接口相关的三个类 xxxApiGrpc、 xxxApiGrpc.xxxImplBase、xxxApiStub xxxApiGrpc: 对应上面编写user.proto文件中service UserServiceApi xxxApiGrpc.xxxImplBase: 抽象类,需要grpc-server模块去具体业务类中继承这个类然后重写方法里写具体业务代码 xxxApiGrpc.xxxApiStub 这个类中的login方法就是grpc-client需要调用的接口 UserServiceApiGrpc文件就是对应接口编译后service类 在 UserServiceApi类下面有个静态类UserServiceApiStub这个类下面的login方法就是grpc-client需要调用的接口 在 UserServiceApi类下面有个抽象类UserServiceApiImplBase需要grpc-server去继承这个类然后重写方法里写具体业务代码
3.grpc-server模块
3.1.pom文件和application.yaml
pom文件 需要继承父工程 parentgroupIdcom.ljm.boot.grpc/groupIdartifactIdparent/artifactIdversion0.0.1-SNAPSHOT/version/parentdependenciesdependencygroupIdcom.ljm.boot.grpc/groupIdartifactIdgrpc-api/artifactId/dependency!-- gRpc Server --dependencygroupIdnet.devh/groupIdartifactIdgrpc-server-spring-boot-starter/artifactId/dependency/dependencies application.yaml 默认端口是9090,可以通过下面配置修改
grpc:server:port: 9090 #默认90903.2.实现grpc-api模块的接口
GrpcService 注解表示这个接口是需要通过grpc调用.newBuilder()实例化对象onNext()设置返回结果onCompleted() 可以理解为return,表示这次调用结束
GrpcService
public class UserServiceApi extends UserServiceApiGrpc.UserServiceApiImplBase {Overridepublic void login(LoginInfoDTO request, StreamObserverLoginResultVo responseObserver) {LoginResultVo.Builder builderLoginResultVo.newBuilder();Result.Builder rBuilderResult.newBuilder();if (!admin.equals(request.getUsername()) || !123456.equals(request.getPassword())){rBuilder.setOk(false);rBuilder.setCode(101);rBuilder.setMessage(用户名或密码错误);}else{rBuilder.setOk(true);rBuilder.setCode(200);rBuilder.setMessage(登录成功!);builder.setData(UserInfo.newBuilder().setToken(UUID.randomUUID().toString()).setId(1).build());}builder.setResult(rBuilder);responseObserver.onNext(builder.build());responseObserver.onCompleted();}}3.3.启动服务
启动类和普通的springboot项目并无区别
SpringBootApplication
public class GrpcServerApplication {public static void main(String[] args) {SpringApplication.run(GrpcServerApplication.class, args);}
}运行程序后可以看到gRPC服务已启动,绑定的端口是9090
4.grpc-client模块
4.1.pom文件和application.yaml
pom文件 相比于server模块添加了web服务模块 parentgroupIdcom.ljm.boot.grpc/groupIdartifactIdparent/artifactIdversion0.0.1-SNAPSHOT/version/parentdependenciesdependencygroupIdcom.ljm.boot.grpc/groupIdartifactIdgrpc-api/artifactId/dependency!-- gRpc Client --dependencygroupIdnet.devh/groupIdartifactIdgrpc-client-spring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependenciesapplication.yaml文件配置
server:port: 8037grpc:client:#GrpcClient注解需要和下面的grpc-server一致grpc-server:#grpc服务端的调用地址address: static://127.0.0.1:9090enable-keep-alive: truekeep-alive-without-calls: true#传输类型设置为明文negotiation-type: plaintext4.2.创建http接口调用grpc-server
GrpcClient注解内的值需要和grpc.client.grpc-server保持一致
RequestMapping
RestController
public class UserController {GrpcClient(grpc-server)private UserServiceApiGrpc.UserServiceApiBlockingStub serviceApiBlockingStub;PostMapping(/login)public String login(RequestParam String username, RequestParam String password) {LoginInfoDTO loginInfoDTO LoginInfoDTO.newBuilder().setUsername(username).setPassword(password).build();LoginResultVo loginResultVo serviceApiBlockingStub.login(loginInfoDTO);String result;if (loginResultVo.getResult().getOk()) {result String.format(登录成功token%s, userId%d, loginResultVo.getData().getToken(), loginResultVo.getData().getId());} else {result String.format(登录失败code%d,msg%s, loginResultVo.getResult().getCode(), loginResultVo.getResult().getMessage());}return result;}
}4.3.启动服务测试
SpringBootApplication
public class GrpcClientApllication {public static void main(String[] args) {SpringApplication.run(GrpcClientApllication.class, args);}
}通过接口测试工具调用 http://localhost:8037/login接口
设置账号密码和后台一致测试 设置密码错误再测试
由上可以看到结果和预期一致,使用gRPC分页查询数据的在gitee代码中提交了篇幅有限就不一一概括了。
项目配套代码
gitee代码地址
创作不易,要是觉得我写的对你有点帮助的话,麻烦在gitee上帮我点下 Star
【SpringBoot框架篇】其它文章如下,后续会继续更新。
1.搭建第一个springboot项目2.Thymeleaf模板引擎实战3.优化代码,让代码更简洁高效4.集成jta-atomikos实现分布式事务5.分布式锁的实现方式6.docker部署,并挂载配置文件到宿主机上面7.项目发布到生产环境8.搭建自己的spring-boot-starter9.dubbo入门实战10.API接口限流实战11.Spring Data Jpa实战12.使用druid的monitor工具查看sql执行性能13.使用springboot admin对springboot应用进行监控14.mybatis-plus实战15.使用shiro对web应用进行权限认证16.security整合jwt实现对前后端分离的项目进行权限认证17.使用swagger2生成RESTful风格的接口文档18.使用Netty加websocket实现在线聊天功能19.使用spring-session加redis来实现session共享20.自定义Configuration配置类启用开关21.对springboot框架编译后的jar文件瘦身22.集成RocketMQ实现消息发布和订阅23.集成smart-doc插件零侵入自动生成RESTful格式API文档24.集成FastDFS实现文件的分布式存储25.集成Minio实现文件的私有化对象存储26.集成spring-boot-starter-validation对接口参数校验27.集成mail实现邮件推送带网页样式的消息28.使用JdbcTemplate操作数据库29.Jpavue实现单模型的低代码平台30.使用sharding-jdbc实现读写分离和分库分表31.基于分布式锁或xxx-job实现分布式任务调度32.基于注解redis实现表单防重复提交33.优雅集成i18n实现国际化信息返回34.使用Spring Retry完成任务的重试35.kafka环境搭建和收发消息36.整合Tess4J搭建提供图片文字识别的Web服务37.使用gRPC实现远程服务调用