一、接口调用
接口调用如果是远程调用,那么就构成了简单的分布式。最简单的远程接口实现方式是 web service 或 rest。当然一个合理的分布式应用不仅仅是远程接口调用这么简单。还需要有负载均衡、缓存等功能。最简单实现分布式的技术是 Rest 接口,因为 Rest 接口可以使用现存的各种服务器,比如负载均衡服务器和缓存服务器来实现负载均衡和缓存功能。
二、统一通信协议
关于通信协议,不同的公司有不同的选择,但是建议同一公司内部使用统一的通信协议,比较典型的有 grpc 和 brpc。
1. gRPC 简介
gRPC 是 Google 发布的基于 HTTP 2.0 传输层协议承载的高性能开源软件框架,提供了支持多种编程语言的、对网络设备进行配置和纳管的方法。由于是开源框架,通信的双方可以进行二次开发,所以客户端和服务器端之间的通信会更加专注于业务层面的内容,减少了对由 gRPC 框架实现的底层通信的关注。如下图,DATA 部分即业务层面内容,下面所有的信息都由 gRPC 进行封装。
grpc 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
grpc 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。
关于具体 gRPC 报文的结构,可以参考下图:
下面展示一下 gRPC 的交互过程
- 交换机在开启 gRPC 功能后充当 gRPC 客户端的角色,采集服务器充当 gRPC 服务器角色;
- 交换机会根据订阅的事件构建对应数据的格式(GPB/JSON),通过 Protocol Buffers 进行编写 proto 文件,交换机与服务器建立 gRPC 通道,通过 gRPC 协议向服务器发送请求消息;
- 服务器收到请求消息后,服务器会通过 Protocol Buffers 解译 proto 文件,还原出最先定义好格式的数据结构,进行业务处理;
- 数据梳理完后,服务器需要使用 Protocol Buffers 重编译应答数据,通过 gRPC 协议向交换机发送应答消息;
- 交换机收到应答消息后,结束本次的 gRPC 交互。
上图展示的是 gRPC 交互过程的具体流程,这也是 Telemetry 触发方式其中之一,称为 Dial-out 模式。简单地说,gRPC 就是在客户端和服务器端开启 gRPC 功能后建立连接,将设备上配置的订阅数据推送给服务器端。
2. brpc
与 grpc 类似,brpc 源自百度,目前支撑百度内部大约 75 万个同时在线的实例。
其实基于以上的几种选择都能够完成高效的开发,团队内部使用统一的标准,这样更有利于模块化和统一标准。
服务间的通信是通过轻量级的 web 服务,使用同步的 REST API 进行通信。在实际的项目应用中,一般推荐在查询的时候使用同步机制,在增删改使用异步的方式,结合消息队列来实现数据的操作,以保证最终的数据一致性。
具体可以使用 BRPC 做如下
- 搭建能在一个端口支持多协议的服务, 或访问各种服务
- Server 能同步或异步处理请求
- Client 支持同步、异步、半同步,或使用组合 channels 简化复杂的分库或并发访问
- 通过 http 界面调试服务, 使用 cpu, heap, contention profilers
- 获得更好的延时和吞吐
- 把你组织中使用的协议快速地加入 brpc,或定制各类组件, 包括命名服务 (dns, zk, etcd), 负载均衡 (rr, random, consistent hashing)
三、rest API
REST API 应为创建、检索、更新和删除操作使用标准 HTTP 动词,而且应特别注意操作是否幂等。
POST 操作可用于创建资源。POST 操作的明显特征是它不是幂等的。举例而言,如果使用 POST 请求创建资源,而且启动该请求多次,那么每次调用后都会创建一个新的唯一资源。
GET 操作必须是幂等的且不会产生意外结果。具体来讲,带有查询参数的 GET 请求不应用于更改或更新信息(而应使用 POST、PUT 或 PATCH)。
PUT 操作可用于更新资源。PUT 操作通常包含要更新的资源的完整副本,使该操作具有幂等性。
PATCH 操作允许对资源执行部分更新。它们不一定是幂等的,具体取决于如何指定增量并应用到资源上。例如,如果一个 PATCH 操作表明一个值应从 A 改为 B,那么它就是幂等的。如果它已启动多次而且值已是 B,则没有任何效果。对 PATCH 操作的支持仍不一致。例如,Java EE7 中的 JAX-RS 中没有 @PATCH 注释。
DELETE 操作用于删除资源。删除操作是幂等的,因为资源只能删除一次。但是,返回代码不同,因为第一次操作将成功 (200),而后续调用不会找到资源 (204)。
四、你们怎么解决
不同项目组之间使用的语言有可能不同,框架有可能不同,同样的,通信协议有可能不同,你们怎么解决的呢?