乐清网站建设公司,音乐网站制作教程步骤,网站 劣势,wordpress动漫RPC是什么
RPC是指远程过程调用#xff0c;也就是说两台服务器A#xff0c;B#xff0c;一个应用部署在A服务器上#xff0c;想要调用B服务器上应用提供的函数/方法#xff0c;由于不在一个内存空间#xff0c;不能直接调用#xff0c;需要通过网络来表达调用的语义和传…RPC是什么
RPC是指远程过程调用也就是说两台服务器AB一个应用部署在A服务器上想要调用B服务器上应用提供的函数/方法由于不在一个内存空间不能直接调用需要通过网络来表达调用的语义和传达调用的数据。
一个RPC框架的基本构成
序列化协议
万物皆字节我们需要一种途径将万物转化为字节序列在网络传输这个转化器便是序列化协议常见如Java原生序列化协议、Thrift、Hession、Json/XML、ProtoBuf。
传输层
目前而言主要是TCP/UDP对于Java生态而言大多使用NettyAPI来屏蔽底层实现细节
动态代理层
屏蔽业务感知远程调用等同于一个本地服务调用
1.1 远程过程调用要解决的新问题
1. Call ID映射
在RPC中所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时必须附上这个ID。还需要在客户端和服务端分别维护一个 {函数 – Call ID} 的对应表。两者的表不一定需要完全相同但相同的函数对应的Call ID必须相同。当客户端需要进行远程调用时它就查一下这个表找出相应的Call ID然后把它传给服务端服务端也通过查表来确定客户端需要调用的函数然后执行相应函数的代码。
2. 序列化和反序列化
客户端怎么把参数值传给远程的函数呢在本地调用中我们只需要把参数压到栈里然后让函数自己去栈里读就行。但是在远程过程调用时客户端跟服务端是不同的进程不能通过内存来传递参数。甚至有时候客户端和服务端使用的都不是同一种语言。这时候就需要将调用参数序列化成二进制格式进行传输并在接收端进行反序列化还原成参数对象这个过程叫序列化和反序列化。
3. 网络传输
远程调用往往用在网络上客户端和服务端是通过网络连接的。所有的数据都需要通过网络传输因此就需要有一个网络传输层。网络传输层需要把Call ID和序列化后的参数字节流传给服务端然后再把序列化后的调用结果传回客户端。只要能完成这两者的都可以作为传输层使用。因此它所使用的协议其实是不限的能完成传输就行。尽管大部分RPC框架都使用TCP协议但其实UDP也可以而gRPC干脆就用了HTTP2。Java的Netty也属于这层的东西。
1.2 业界常用的 RPC 框架
Dubbo: Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架使得应用可通过高性能的 RPC 实现服务的输出和输入功能可以和 Spring框架无缝集成。目前 Dubbo 已经成为 Spring Cloud Alibaba 中的官方组件支持多语言和多协议如Java、.NET、C、REST、HTTP等。gRPC gRPC是Google开源的跨语言高性能RPC框架支持多种语言包括C、C、Java、Python、Go、Ruby等。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务以实现负载平衡跟踪运行状况检查和身份验证。它也适用于分布式计算的最后一英里以将设备移动应用程序和浏览器连接到后端服务。Hessian Hessian是一个轻量级的 remoting-on-http 工具使用简单的方法提供了 RMI 的功能。 相比 WebServiceHessian 更简单、快捷。采用的是二进制 RPC协议因为采用的是二进制协议所以它很适合于发送二进制数据。Apache ThriftThrift是Apache开源的跨语言高效的RPC框架支持多种语言包括C、Java、Python、Ruby等。Apache AvroAvro是Apache开源的数据序列化系统也是一个支持跨语言的RPC框架支持多种语言包括Java、C、C、Python等。
1.3 gRPC是什么
grpc 是 google 给出的 rpc 调用方式它基于 google 的 protobuf 定义方式提供了一整套数据定义和 rpc 传输的方式。但是gRPC有些功能尚不完善GRPC尚未提供连接池也尚未提供“服务发现”、“负载均衡”机制。
1.4 gRPC的特点
基于标准协议gRPC使用Google开发的Protocol Buffers作为接口定义语言IDL支持多种语言包括C、C、Java、Python、Go、Ruby等。Protocol Buffers具有良好的跨语言和跨平台支持易于扩展和维护。支持多种序列化格式gRPC支持多种序列化格式包括二进制、JSON和ProtobufProtocol Buffers的二进制格式二进制格式的性能最佳而Protobuf格式则更为高效。高性能和效率gRPC使用HTTP/2作为传输协议支持多路复用、头部压缩、流控等特性可以减少网络开销提高性能和效率。支持多种认证和安全机制gRPC支持多种认证和安全机制包括SSL/TLS、OAuth2等可以保障数据的安全性和可靠性。
综上所述gRPC具有高效、高性能、跨平台、易于扩展和集成等优点广泛应用于微服务、分布式系统、云计算等领域。
二、proto语法
Protocol Buffers 是一种轻便高效的结构化数据存储格式可以用于结构化数据串行化或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
Protocol Buffers 是一种灵活高效自动化机制的结构数据序列化方法可类比 XML但是比 XML 更小3 ~ 10倍、更快20 ~ 100倍、更为简单。
2.1 如何使用ProtoBuf
创建pb文件
第一步创建一个.proto文件定义数据结构下面是一个非常简单的例子。假设你想定义一个“搜索请求”的消息格式每一个请求含有一个查询字符串、你感兴趣的查询结果所在的页数以及每一页多少条查询结果。可以采用如下的方式来定义消息类型的.proto文件了
syntax proto3;package attribution.sdk.test;option java_package com.attribution.sdk.test.channelinfo;
option java_outer_classname AdIdInfoNewProto;
option java_multiple_files true;message SearchRequest {string query 1;int32 page_number 2;int32 result_per_page 3;
}service AttributionService {rpc Search(SearchRequest) returns (SearchResponse);
}该文件的第一行指定您正在使用proto3语法如果不这样做protobuf 编译器将假定您正在使用proto2。这必须是文件的第一个非空的非注释行。package决定了proto文件内部service的全路径名称。java_package决定了proto中message类的生成路径。java_outer_classname决定了输出文件的类名。message可以理解为一个结构体转化为java之后为一个类。service为被调用的服务rpc为该服务下的一个方法。所述SearchRequest消息定义了三个字段对应着需要的三个消息内容。每个字段都有一个名称和类型。
指定字段类型
在上面的示例中所有字段都是标量类型两个整数page_number和result_per_page和一个字符串query。但是您还可以为字段指定合成类型包括枚举和其他消息类型。
分配标识号
正如上述文件格式在消息定义中每个字段都有唯一的一个数字标识符,通俗的说也就是这个字段所分配的序号。这些标识符是用来在消息的二进制格式中识别各个字段的一旦开始使用就不能够再改变。注[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号。
再举一个例子
创建 .proto 文件定义数据结构如下例
// 例1: 在 xxx.proto 文件中定义 Example1 message
message gps_data {optional string stringVal 1;optional bytes bytesVal 2;message EmbeddedMessage {int32 int32Val 1;string stringVal 2;}optional EmbeddedMessage embeddedExample1 3;repeated int32 repeatedInt32Val 4;repeated string repeatedStringVal 5;
}我们在上例中定义了一个名为 gps_data 的消息语法很简单message 关键字后跟上消息名称
message xxx {
}gps_data 的名称格式与为生成的java文件的名称是有关系的如果加入了下划线则默认生成的是GpsData 这个驼峰格式的名称。当然你也可以在文件里自定义java文件的名称
option java_outer_classname BatteryData;之后我们在其中定义了 message 具有的字段形式为
message xxx {// 字段规则required - 字段必须出现且只能出现 1 次// 字段规则optional - 字段可出现 0 次或1次// 字段规则repeated - 字段可出现任意多次包括 0// 类型int32、int64、sint32、sint64、string、32-bit ....// 字段编号0 ~ 536870911除去 19000 到 19999 之间的数字字段规则 类型 名称 字段编号;
}在上例中我们定义了
类型 string名为 stringVal 的 optional 可选字段字段编号为 1此字段可出现 0 或 1 次类型 bytes名为 bytesVal 的 optional 可选字段字段编号为 2此字段可出现 0 或 1 次类型 EmbeddedMessage自定义的内嵌 message 类型名为 embeddedExample1 的 optional 可选字段字段编号为 3此字段可出现 0 或 1 次类型 int32名为 repeatedInt32Val 的 repeated 可重复字段字段编号为 4此字段可出现 任意多次包括 0类型 string名为 repeatedStringVal 的 repeated 可重复字段字段编号为 5此字段可出现 任意多次包括 0
还可以指定改java代码的包路径命令如下
option java_package com.ks.test; 2.2 proto文件几种路径说明
syntax proto3;package com.ks.infra.grpc.test;option java_package com.ks.demo;
option java_outer_classname Demo;
option java_multiple_files true;message TestRequest {string value 1;
}message TestResponse {string value 1;
}service TestService {rpc Test (TestRequest) returns (TestResponse);rpc TestDeadline (TestRequest) returns (TestResponse);
}service TestStreamService {rpc Test (TestRequest) returns (stream TestResponse);rpc TestFailed (TestRequest) returns (stream TestResponse);rpc TestSlow (TestRequest) returns (stream TestResponse);rpc TestUpStream(stream TestRequest) returns (TestResponse);
}如上面proto文件所示一共有三个路径
proto文件本身所在路径假设是ks/demo使用场景是当其他proto文件需要引入当前proto文件时依赖这个路径形如 import “ks/demo/demo.proto”。这样就可以使用该文件内部定义的所有message了proto文件内部package指定路径com.ks.infra.grpc.test这个路径非常的核心任何迁移或者修改proto文件的操作都不应该修改这个package路径因为它决定了文件内部service的生成路径。一旦发生变化就会造成在实际gRPC调用时找不到服务方法而抛异常Unimplementedoption参数指定java输出路径com.ks.demo这个路径也比较核心定义好之后也不要轻易修改因为它决定了proto中message类的生成路径如果修改会造成源码不兼容编译阻塞
2.3 proto文件输出样式
proto文件输出样式由如下几个因素决定
proto文件的名称例如infra_demo.proto在没指定2的前提下会默认按照驼峰生成OuterClass对于本例为InfraDemo.java有意思的是当proto文件中的message跟默认生成java类名重名的时候会在生成类名后面加上OuterClass对于本例为InfraDemoOuterClassoption java_outer_classname Demo如果指定此选项则输出文件名称为指定名称Demooption java_multiple_files true指定此选项proto文件中的message会生成独立的java文件此选项定义好后也不要轻易修改否则也会造成编译阻塞推荐开启这个选项
2.4 protoc 编译 .proto 文件会生成什么
当你使用protoc 来编译一个.proto文件的时候编译器将利用你在文件中定义的类型生成你打算使用的语言的代码文件。生成的代码包括getting setting 接口和序列化反序列化接口。
对于C 编译器会从每个.proto文件生成一个.h和一个.cc文件并为您文件中描述的每种消息类型提供一个类。对于Java编译器生成一个.java文件其中包含每种消息类型的类以及Builder用于创建消息类实例的特殊类。
我们在 .proto 文件中定义了数据结构这些数据结构是面向开发者和业务程序的并不面向存储和传输。\
当需要把这些数据进行存储或传输时就需要将这些结构数据进行序列化、反序列化以及读写。ProtoBuf 将会通过编译器protoc为我们提供相应的接口代码。
可通过如下命令生成相应的接口代码
// $SRC_DIR: .proto 文件所在的源目录
// --java_out: 生成 java 代码
// $DST_DIR: 生成java代码的目标目录
// xxx.proto: 要针对哪个 proto 文件生成接口代码protoc -I$SRC_DIR --java_out$DST_DIR $SRC_DIR/xxx.proto