现现在微服务很流行,而微服务颇有多是使用不一样语言进行构建的。而微服务之间一般须要相互通讯,因此微服务之间必须在如下几个方面达成共识:git
如今最流行的一种API风格多是REST,它主要是经过HTTP协议来传输JSON数据。github
可是如今咱们能够看看gRPC(https://grpc.io/),它来自Google,而且支持众多主流的语言包括Go,Dart,C#,C/C++,Nodejs,Python等等。数组
下面就学习一下gRPC。服务器
构建(Web)API是挺麻烦的,由于构建API时咱们得考虑:网络
以上这些问题听说gRPC都能解决。。😱负载均衡
以前说了gRPC来自Google,它是一个开源的框架;它同时也是Cloud Native Computation基金会(CNCF)的一部分,就像Docker和Kubernetes同样。框架
gRPC容许你为RPC(Remote Procedure Call)定义请求和响应,而后gRPC会帮你处理一切剩余问题。函数
它速度快,执行效率高,基于HTTP/2构建,低延迟,支持流,与开发语言无关,而且能够很简单的插入身份认证、负载均衡、日志和监控等功能。微服务
RPC是(Remote Procedure Call)远程过程调用。学习
在客户端代码使用RPC调用的时候,就像直接调用了服务端的一个函数同样。
例如在服务器端代码是这样的:
而在“遥远”的客户端它是这样调用服务器端的逻辑的,就像调用本地方法同样:
而实际上客户端在调用这个方法的时候,是要走网络通讯的。
RPC它不是一个新的概念,很早它就出现了。可是它存在不少的问题。而gRPC它是对RPC一种很是简洁的实现而且解决了不少RPC的问题。
首先,你得学习Protocol Buffers(https://developers.google.com/protocol-buffers/),简单的说,它能够用来定义消息和服务。
而后,你只须要实现服务便可,剩余的gRPC代码将会自动为你生成。
.proto这个文件能够适用于十几种开发语言(包括服务端和客户端),而且它容许你使用同一个框架来支持每秒百万级以上的RPC调用。
gPRC使用的是合约优先的API开发模式,它默认使用Protocol buffers (protobuf) 做为接口设计语言(IDL),这个.proto文件包括两部分:
看一个官网的例子(protobuf):
在这里定义了一个Greeter服务,它里面定义了一个SayHello的rpc调用。SayHello会发送HelloRequest这个消息,接收HelloReply这个消息。
为何使用Protocol Buffers?
由于:
开发环境:
brew install clang-format
。
选个文件夹,创建一个名叫first.proto的文件:
1. 这行代码表示咱们使用的是语法是proto3,以前还有一个proto2;若是你不写这一行,那么protocol buffer编译器会认为你采用的是proto2。这个必须是文件的第一个非空非注释行。
2. 这里是定义了一个消息名称为FirstMessage,类型是message。它里面定义了三个字段,它们都是标量类型(Scalar Type),你也能够定义复合类型,这个之后再说。
3. 是指字段(Field)的类型
4. 字段的名称
5. 字段的数值(也叫Tag),这个数字是惟一的。它们是用来在信息格式里识别你的字段的,一旦该类型被使用了,那么这个数字就不要再改变了。
数值型有不少种形式:double, float, int32, int64, uint32, uint64, sint32, sint64, fixed32, fixed64, sfixed32, sfixed64。
根据须要选择对应的数值类型。
bool型能够有True和False两个值。
string表示任意长度的文本,可是它必须包含的是UTF-8编码或7位ASCII的文本,长度不可超过232。
bytes可表示任意的byte数组序列,可是长度也不能够超过232 ,最后是由你来决定如何解释这些bytes。例如你可使用这个类型来表示一个图片。
能够本身作一个例子,需求是这样的:这个信息表示的是一我的Person,使用proto3语法,字段以下:ID,姓名,身高,体重,头像,电子邮件,邮件是否已验证。
这个应该没有什么难度,不过要注意一下别忘记标点符号。
在Protocol Buffers里面,字段的名其实没那么重要,可是写C#代码的时候,字段名仍是很重要的。
对于protobuf来讲,这个tag是更为重要的。
可使用的最小的tag数值是1,最大值是229 - 1, 或者 536,870,911。可是你不可使用19000到19999之间的数,这部分数是保留的。
还有一点值得注意的是:
从1到15的Tag数只占用1个字节的空间,因此它们应该被用在频繁使用的字段上。而从16到2047,则占用两个字节,它们能够用在不频繁使用的字段上。
protobuf的字段必须知足如下两个规则之一:
大概意思就是指这个字段只能出现0或1次(不能超过一次),这也是proto3的默认字段规则。
与singular相对的就是repeated。若是你想作一个list或数组的话,你可使用重复字段这个概念。这个list能够有任何数量(包括0)的元素。它里面的值的顺序将会获得保留。
仍是使用前面的Person这个例子,咱们在里面添加一个repeated字段(电话号码):
就是在前面加上repeated这个关键字便可。
在proto3里面,标量类型的repeated字段采用的是packed编码。
proto文件里能够添加注释。它们一般被看成你定义的这些消息的文档。
注释很简单,仍是两种形式,直接看代码就明白了:
若是你对你定义的消息类型进行了更新,例如删除某个字段或者注释掉某个字段,那么其它开发者在之后更新这个消息类型的时候可能会从新使用被你删除/注释掉的字段的数值(tag)。若是之后还须要使用这个消息类型的老版本的proto文件,那么这将会引发严重的问题,例如数据损坏、隐私漏洞等等。
那么一种避免此类事情发生的解决办法就是将你删除/注释掉的这些字段的数值(或/而且包括字段名,由于字段名可引发JSON序列化的问题)标记为reserved,若是其余人再使用这个数值做为字段标识符,那么编译器就会有错误提示:
注意,不能够把reserved数值和字段名放在同一个reserved语句里。
当消息被解析的时候,若是编码的消息里不含有特定的一个singular元素,那么在被解析对象里相应的字段就会被设为默认值。
经常使用类型的默认值以下:
以前说了,枚举里面定义的第一个值就是这个枚举的默认值。
Enum的tag必须从0开始,因此0就是枚举的数值默认值。
咱们对Person添加一个枚举类型的字段:性别 Gender:
首先须要定义枚举类型,这里定义了一个枚举,名称是Gender,里面有3个值,默认值是NOT_SPECIFIED,数值默认值就是0。
而后使用这个枚举类型定义了一个字段,名称为gender,tag数为10。
枚举值是能够起别名的,起别名的做用就是容许两个枚举值拥有同一个数值。
要想起别名,首先须要设置allow_alias这个option为true:
而后咱们为FEMALE这个枚举值起了一个别名叫作WOMAN,它们的数值是同样的。一样的MAN是MALE的数值也是同样的。
枚举里面的常量的值必须不能超过32位整型的数值,不建议使用负数。
枚举能够定义在message里面,也能够在外边单独定义以便复用。若是另外一个消息想使用Person里面这个Gender枚举,那么可使用Person.Gender这种形式。
针对枚举值被删除/注释掉这种状况,它也可使用reserved:
数值和常量名也必须分开使用两个reserved语句。
其中max表示可能的最大的值。
可使用其它的信息类型做为字段的类型。
咱们能够在同一个proto文件里定义多个信息类型(为了截图方便,我去掉了Person的一些字段):
在这个文件里,除了Person信息类型外,我还定义了Date信息类型。
因此,我能够在Person里面使用Date做为它的字段类型:
若是想要使用的信息类型已经在其它的proto文件定义好了呢?这个时候就须要引入信息类型的定义。
如今我把Date定义移动到了date.proto这个文件里面:
而后在person.proto里面咱们能够引用date.proto:
Protocol Buffer容许在信息类型里面定义其它的信息类型。
直接看例子:
若是想在Person外边使用Address这个类型,那么就须要这样用:Person.Address。
你能够向proto文件添加可选的打包(package)说明符,以免消息类型间的名称冲突。
因此说打包是很必要的。
打包以后生成的C#代码就会使用命名空间来对应proto里面的package,可是命名方式会改成Pascal Case(每一个单词首字母大写)。
上面的代码在C#里面的状况就是:Person类在My.Project这个命名空间下。
可是若是你在proto文件里设置了option csharp_namespace这个选项,那么在C#里的命名空间就是该选项指定的命名空间了:
这时候,C#里面Perosn类的命名空间就是My.WebApis了,可是在proto文件里它的包仍是my.project。
protoc编译器主要就是用来生成代码的,它的下载地址目前是:https://github.com/protocolbuffers/protobuf/releases/
在里面选择你使用的操做系统的版本:
下载后解压缩到某个路径,而后把解压目录下的bin目录添加到系统的环境变量里。
而后打开命令行,输入protoc,若是有相似下面的东西出现,说明安装成功了:
这里面的--proto_path=PATH这个参数比较经常使用,它用来指定到哪一个文件见来查找引入。
再有就这个参数很经常使用:
--csharp_out=OUT_DIR用来指定存放生成的C#代码的目录。
咱们先试验一下,生成Person的C#代码:
执行成功后就没有任何提示,打开csharp目录,能够看到Person.cs这个文件:
而Person.cs文件里面的代码就比较多了:
千万不要去修改这个文件!
第一篇文章先到这。