迎关注我的头条号:Wooola,10 年 Java 软件开发及架构设计经验,专注于 Java、Go 语言、微服务架构,致力于每天分享原创文章、快乐编码和开源技术。
API是服务之间通信的契约,通过API可以忽略服务内部实现的细节。如果接口设计良好,则可以降低团队间的耦合度,加快开发速度。
优秀API的设计原则设计出优秀的API通常需要遵循如下原则。
· 简单:API应该符合大多数人正常的思维逻辑,避免异想天开的交互,满足需求的同时,越简单越好。
· 易懂:优秀的API可读性好,尽量做到不需要文档就能读懂接口名称、参数的大概含义,提供给第三方开发者的接口要进行详细地描述,包括参数的取值范围、错误码、异常返回规则、SLA相关指标等。
· 一致:对于同一个公司、站点提供的API,最好有统一的规则,让开发者只要看过几个API之后,基本都能猜到剩余API的含义。
· 稳定:最好在开始的时候就考虑好,不要轻易修改API,否则会给使用者造成非常大的麻烦。如果修改API无法避免,那么最好通过增加接口而不是修改已有接口做到兼容。如果一定要改变已有接口,也要通过明确的版本号加以区分,并且预留足够的时间。
· 安全:设计时要考虑超出预期的情况如何处理,给出被限流的情况。下面是GitHub API使用的两个相关的头部参数。
¡ X-RateLimit-Limit:每小时允许发送请求的最大值。
¡ X-RateLimit-Remaining:当前时间窗口剩下的可用请求数目。
如果提供给第三方,则要考虑如何认证,租户之间如何隔离,并且尽量使用HTTPS协议。如果验证失败,则要返回401 Unauthorized状态码;如果没有被授权访问,则要返回403 Forbidden状态码,并且提供详细的错误信息。
服务间通信——RPCRPC(Remote Procedure Call)是指远程过程调用。简单来说,RPC希望达到的效果是,调用远程方法就像调用本地方法一样。由于调用方和被调用方实际上分布在不同的机器上,一般情况下,会有一个框架来支撑,以便屏蔽底层通信细节,让双方开发起来更简单。
一个普通的RPC调用流程如图2-11所示,具体调用过程如下。
(1)客户端在业务服务中发起请求。
(2)调用本地stub,本地stub对消息进行序列化、封装等处理。
(3)客户端stub调用网络通信模块将消息送达服务端,中间还可能包括寻址、建连接等一系列操作。
(4)服务端网络通信模块把接收到的消息转发给stub进行反序列化。
(5)stub转发给业务服务进行处理并返回结果。
(6)stub将结果进行序列化,调用网络通信模块。
(7)服务端通过网络通信模块将结果返回到客户端网络通信模块中。
(8)客户端网络通信模块将消息转发给stub。
(9)stub进行反序列化并转发给客户端业务服务。
(10)客户端得到最终结果。
我们的目标是让(2)到(9)对开发者不可见。
既然要求像调用本地方法一样调用远程方法,那就不只是要屏蔽复杂度,还要在性能上进行考虑。
影响RPC性能的因素如下。
· 序列化。常用的RPC序列化协议包括:Thrift、Protobuf、Avro、Kryo、MsgPack 、Hessian、Jackson。
图2-11 RPC调用流程图
· 传输协议。常用的传输协包括:HTTP、Socket、TCP、UDP等。
· 连接。连接包括:长连接、短连接。
· IO模型。常用的网络IO模型:同步阻塞IO(Blocking IO)、同步非阻塞IO(Non-blocking IO)、IO多路复用(IO Multiplexing)、异步IO(Asynchronous IO)。
序列化——ProtobufProtobuf是由Google开源的消息传输协议,用于将结构化的数据序列化、反序列化通过网络进行传输,目前被广泛应用的主要版本有Protobuf 2和Protobuf 3。Protobuf首先解决的是如何在不同语言之间传递数据的问题,目前支持的编程语言有Java、C 、Python、Ruby、PHP、Go等。通过Protobuf可以很容易地实现一个Client和一个Server之间的数据传递,Client和Server可以使用不同语言。
Protobuf是一个高性能、易扩展的序列化框架,通常是RPC调用追求高性能的首选。它本身非常简单,易于开发,结合Netty可以非常便捷地实现RPC调用。同时,可以利用Netty为Protobuf解决有关Socket通信中“半包、粘包”等问题(反序列化时,字节成帧)。
Protobuf比JSON、XML等更快、更轻、更小,并且可以跨平台。Protobuf最新的版本为3.x,如果使用它,首先要编写proto文件,即IDL文件(后缀为“.proto”的文本文件),然后通过客户端生成Java相关类进行序列化、反序列化。
下面我们就简单描述一下基于Protobuf实现序列化、反序列化的步骤。
1.安装客户端
通过brew可以实现在Mac下安装Protobuf,执行命令如下。
brew install protobuf
如果出现如下执行结果,意味着已经安装成功了。
/usr/local/Cellar/protobuf/3.5.1: 267 files, 18.0MB
也可以通过如下命令检验是否安装成功。
protoc –version
2.安装工具
为了在编辑proto文件的时候获得更好的体验,可以先安装插件。idea里可以安装Protobuf Support,在插件库中搜索后直接安装即可,如图2-12所示。
图2-12 idea安装Protobuf Support插件
Protobuf Support可以对语法高亮显示、错误提示,如图2-13所示。
图2-13 Protobuf Support插件效果
3.编辑proto文件
本节采用的Protobuf 3.x,需要遵循proto 3的语法。关于Protobuf的数据类型和Java的数据类型如何对应,可以参照表2-3提供的对应关系。