# 接口交互详解

开放平台所提供的接口有几十个到几百个不等，同样支持的服务也是多个的。就拿[支付宝开放平台](https://docs.open.alipay.com/api)来说
它所提供的服务有，支付服务、会员服务、店铺服务、芝麻信用服务等。相信这些服务接口肯定不是写在同一个项目中，但是它的接口地址只有一个：https://openapi.alipay.com/gateway.do
从地址信息中可以看到，这是一个网关服务。也就是说，网关是所有请求的入口，然后通过请求分发的方式，把请求路由到具体某个服务中去。
虽然支付宝开放平台的实现方式我们不得而知，但是这种思路是可行的。

SOP也是采用这种方式实现，大致步骤如下：

- 每个服务注册到注册中心，在启动的时候把自己的路由信息上传到zookeeper，并且保证每一个接口都能对应到哪个服务。
- 网关启动时同样注册到注册中心，获取zookeeper上的接口信息，保存到本地，并监听zookeeper上的接口信息，一旦接口信息有修改，网关这边能及时进行更新。
- 网关收到客户端请求后，先进行签名校验，通过之后根据接口信息找到对应的服务，然后进行路由
- 网关对返回结果进行处理（或不处理），返回给客户端。

如何通过接口参数找到对应的服务呢？

在网关定义一个`Map<String, RouteInfo> routeMap = ...`，key为接口名+版本号。

网关启动时，从zookeeper中获取路由信息，并保存到routeMap中

```java
routeMap = buildFromZookeeper();
```

接口请求进来后，根据`方法名+版本号`获取路由信息，然后进行路由转发。

```java
String method = request.getParameter("method");
String version = request.getParameter("version");

RouteInfo routeInfo = routeMap.get(method + version);

doRoute(routeInfo);
```

因为有多个服务把路由信息注册到zookeeper，我们要确保接口名唯一，即`method`全局唯一。

我们推荐接口名的命名规则应该是：`服务模块.业务模块.功能模块.行为`，如：

mini.user.userinfo.get  小程序服务.用户模块.用户信息.获取

member.register.total.get 会员服务.注册模块.注册总数.获取

如果觉得命名规则有点长可以精简为：`服务模块.功能模块.行为`，如`member.usercount.get`，前提是确保前缀要有所区分，不和其它服务冲突。

得益于Spring Cloud的注册中心和和网关功能，我们能很方便的进行接口路由，并且还能实现LoadBalance，不需要自己再去实现。

整个SOP的架构如下图所示：

![SOP架构图](https://images.gitee.com/uploads/images/2019/0309/093312_8afb4789_332975.png "sop.png")

- 完整请求路线

```
客户端生成签名串 → 客户端发送请求 →【网关签名校验 → 权限校验 → 限流处理 → 路由转发】→ {微服务端业务参数校验 → 处理业务逻辑 → 微服务端返回结果}
                                                                                                                     ↓
客户端业务处理 ← 客户端验证服务端签名 ← 客户端收到结果 ← -------------【网关返回最终结果 ← 生成服务端签名 ← 网关处理结果】← 结果返回到网关   

【】：表示网关处理  
{}：表示微服务端处理                                     
```